最近一直在折腾构建工具,主要针对以前的工程进行改造,尝试着能搭建一套比较好用的构建工具,在这个过程中也做了一些新的实践。下面我就来谈谈在这次改造中的心得体会,内容不局限于某一款构建工具,不管用 webpack 、 JDF、gulp 、grunt 还是我比较喜欢的 fis,都可以很容易地实现。
容易上手
好用的第一步就是容易上手。不管是新手还是老鸟,使用工具的目的都是为了解放双手,提高效率,所以一款好用的构建工具在使用上一定要简单,特别在多人协作的时候,其他开发人员可以快速上手,减少沟通成本。
我认为容易上手可以体现在几个方面:
1. 方便安装npm install or setup.exe
最好运行一条命令或者一个安装包就可以装好整个工具
2. 配置简单
提倡约定大于配置的原则,用很少的配置或者不需要配置就可以先 run 起来,如果需要修改其中某些项,可以创建一个配置文件覆盖默认配置项。
3. 依赖模块
我个人比较喜欢固定依赖模块的版本号,保证不同的人,或者同一个人在不同时间安装的模块版本是一样的,这点主要基于以下考虑:
兼容问题:不同版本的模块可能会有不兼容的情况。
模块之间的依赖:模块和模块之间也有版本强依赖,比如 vue 和 vue-template-compiler,它们的版本号必须要一致,否则编译就会报错。
生产环境文件比对:同一套代码不同的人、不同的时间打包出来的文件始终不变(曾经遇到过这样的尬尴,只改了一行代码,结果打包后有一堆文件不一样)。
拿 npm 来说,安装模块后,检查一下 package.json 文件中的版本号确保是你想要的。
开发体验好
第二步是要有好的开发体验,好的工具不仅上手要容易,还要持续用着爽。比如合理的目录结构及编码规范,集成了常用的功能插件,方便调试及前后端协同工作等。
1. 目录结构、编码规范
合理的规范应该是以提升开发效率为目的,而不是约束开发人员。比如使用 ESLint 来排除一些低级的错误和风格统一,在 git hook 中集成 ESLint ,每次提交代码时检查一遍。
关于 git hook 推荐一个模块 husky,安装过后会自动创建 hook 文件到 .git 目录,你只需要在 package.json 的 script 中添加 precommit 和 prepush 就可以了。
2. 常用的代码编译插件
工程中也许会用到 Sass、Less、postcss、babel 等编译插件,根据项目的需要集成进来。
3. 模块化
模块化解决了 js 的独立作用域及依赖管理问题,让代码组织更简单,已经成为了前端在开发的标配。
4. 组件化widget
└ header
├ header.vm
├ header.js
├ header.png
└ header.css
组件化就是将页面的各个部分拆分成小部件,按文件夹组织代码和资源,代码相对独立,方便多人开发、维护和复用。
5. 数据模拟
在后端接口还没准备好的时候,前端往往需要自己模拟数据来开发页面和交互,所以能够方便地模拟数据是构建工具的必备功能之一。我通常的做法是使用 express 启一个简单的 web server来实现。
数据模拟分为 异步接口数据模拟 和 页面渲染数据模拟。
5.1 异步接口数据模拟
异步接口的数据模拟需要考虑两种场景:一是本地开发,二是与后端联调。
假设有如下一个 URL 映射表,key 表示前端请求的地址匹配,local 表示本地数据模拟文件,可以是一个简单的 json 文件,也可以是 express 中间件的 js 文件,server 表示远端服务器的接口地址。
const mockConfig = {
'^/api/index': {
local: '/mock/index.json',
server: '/api/index.html'
},
'^/api/list': {
local: '/mock/list.js',
server: '/api/list.html'
}
}
本地开发时:编写 express 中间件读取表中匹配的 local 值,如果是 json 就读取文件内容,如果是 js 文件,就当作 express 的中间件使用。
与后端联调时:读取表中的 server 值,使用 http-proxy-middleware 将异步请求转发到联调服务器,并将联调服务器的响应数据返回给浏览器
注意:nodejs 在 require 一个模块后会缓存起来,除非重启 express,想要数据文件不被缓存,先 delete require.cache[xxx] 再 require 进来
5.2 页面渲染数据模拟
模拟页面渲染时的数据需要用到模板引擎,express 支持很多模板引擎,可以充分模拟服务端渲染页面时的数据模拟。数据来源可以是和模拟文件同名的 .mock 文件,比如如下一个文件结构:
project
├ common.mock // 全局模拟数据
└ page
├ index.vm
└ index.mock // index.vm 的模拟数据
当渲染 index.vm 的时候,首先读取全局模拟数据文件 common.mock,再读取模板对应的模拟数据文件 index.mock,合并起来作为模板引擎的数据来源。
注:目前大多数的后端模板引擎都有 nodejs 版本的实现,比如 JAVA 中常用的 velocity,可以将其集成到 express 中模拟 JAVA 的模板渲染,由前端接管模板的编写,做到前后端的模板共用。
部署体验
部署是最后一步,也是比较麻烦的一步。构建工具需要考虑性能优化、与IDE集成、与开发流程对接等。
1. 性能优化静态资源的压缩、合并、内嵌
替换被引用资源的生产路径、添加CDN域名
非覆盖式的版本发布(推荐文件名加md5后缀)
2. 与IDE集成
大多数IDE都支持主流的构建工具,即使有不支持的,也可以使用 npm script 来执行任务。
3. 与开发流程对接
各团队可能有自己的一套开发流程,比如我们这边是:本地开发联调、视觉走查、前后端联调、测试环境测试、预发布环境测试,上线。
本地开发时要同时支持本地和本地,本地和远端的联调
将静态代码部署到内网 server 方便设计师视觉走查
测试环境的代码不需要压缩合并,方便定位 bug
预发及上线时需要给资源引用代码添加 CDN 域名
以上就是我在这次构建工具改造中所做的收获,当然这些还远远不够,最终的目标还是要迈向前端工程化体系,而构建工具只是工程化的第一步而已。所以欢迎小伙伴们来一起交流和学习,共同进步。