前言
书接上回。我们Elpis完成了内核core的开发,也算是开了个好头。这回我们要完成Elpis的工程化配置,为日后的业务功能开发搭好舞台。
什么是工程化
前端工程化是指将软件工程方法和工业化生产思维引入前端开发,通过规范化流程、自动化工具和系统化架构,提升前端项目的开发效率、代码质量和可维护性,使其从"手工作坊模式"升级为"标准化流水线生产"------------ DeepSeek
三个字总结就是定规矩。通过规范来约束开发者统一遵守,以达到提高效率降低成本的目的。当然哈,这是基于多人协作及长期维护角度来看,你要是写个demo自己玩,那你随心所欲就行啦。
多页面构建
Elips是沉淀80%的重复性工作即不同平台功能类似的页面,但是这仅限于业务场景相同。举个栗子,后台管理系统是不是都大同小异,但是后台管理系统和在线课堂或者电商平台系统又有很大差异化,不可能一套模版套全部,所以针对不同的系统,我们需要有所区分。所以我们采用多页面+单页面应用的构建方式,即: 相对A后台管理系统和B后台管理系统来说,他们都是单页面应用,同样的模板填充不一样的内容;而相对A后台管理系统和C电商系统,他们各自有自己的模版,各自填充各自的内容是多页面应用。所以在打包时,需要配置多个模板页面即多个入口。
less
// 获取 app/pages 目录下所有入口文件
const entryList = path.resolve(process.cwd(), './app/pages/**/entry.*.js');
glob.sync(entryList).forEach(file => {
const entryName = path.basename(file, '.js');
// 构造 entry
pageEntries[entryName] = file;
// 构造最终渲染的页面
htmlWebpackPluginList.push(
new HtmlWebpackPlugin({
// 产物 (最终模版) 输出路径
filename: path.resolve(process.cwd(), './app/public/dist/', `${entryName}.tpl`),
// 指定要使用的模板文件
template: path.resolve(process.cwd(), './app/view/entry.tpl'),
// 要注入的代码块
chunks: [ entryName ]
})
)
})
分包策略
下来我们看看分包策略。打包时项目内主要是四种类型的文件js,css,html,图片/字体等静态资源文件,不同的文件类型采用不同的Loader进行解析打包,不再赘述。不过js文件是大头,里面有我们自己写的业务强相关的,模块公共文件以及组件和第三方库的,各自分工不同,加载时机和频次也不同。因此我们把js文件打包成三种类型:
- vendor:第三方 lib 库,基本不会改的,除非依赖版本升级
- common: 业务组件代码的公共部分,改动较少
- entry.{page}:不同页面 entry 里的业务组件代码的差异部分,会经常改动
目的就是把改动和引用频率不一样的 js 区分出来,以达到更好的利用浏览器缓存的效果。
javascript
/**
* 把 js 文件打包成三种类型
* 1. vendor:第三方 lib 库,基本不会改的,除非依赖版本升级
* 2. common: 业务组件代码的公共部分,改动较少
* 3. entry.{page}:不同页面 entry 里的业务组件代码的差异部分,会经常改动
* 目的:把改动和引用频率不一样的 js 区分出来,以达到更好的利用浏览器缓存的效果
*/
splitChunks: {
chunks: 'all', // 对同步和异步模块都进行分割
maxAsyncRequests: 10, // 每次异步加载的最大并行请求
maxInitialRequests: 10, // 入口点的最大并行请求数
cacheGroups: {
vendor: { // 第三方依赖库
test: /[\\/]node_modules[\\/]/, // 打包 node_module 中的文件
name: 'vendor', // 模块名称
priority: 20, // 优先级,数字越大优先级越高
enforce: true, // 强制执行
reuseExistingChunk: true // 复用已有的公共 chunk
},
common: { // 公共模块
test: /[\\/]common|widgets[\\/]/,
name: 'common', // 模块名称
minChunks: 2, // 被2处引用即为公共模块
minSize: 1, // 最小分割文件大小 (单位是byte)
priority: 10, // 优先级,数字越大优先级越高
reuseExistingChunk: true // 复用已有的公共 chunk
}
}
},
// 将 webpack 运行时生成的代码打包到 runtime.js
runtimeChunk: true
环境区分及热更新
上面所有问题都是为了方便项目,给用户提供较好的体验,那么接下来就该改善下我们开发者的体验了。上面的配置都可以平滑迁移给生产环境,对于开发环境就不是很友好了,毕竟谁也不想改一行代码就得重启下项目吧。 所以我们给开发环境配置加点料~
- 打包文件不落盘,放在缓存里,引入webpack-dev-middleware监控文件改动;
- 引入webpack-hot-middleware通知浏览器,我改了代码;
- HotModuleReplacementPlugin允许我们项目在运行过程中替换模块,实时刷新最新代码
这样我们每次改动浏览器就会实时刷新最新代码,再也不用一遍遍build啦。不过还没结束,
- 开发环境联调需要配置下跨域
- 配置eval-cheap-module-source-map代码工具,呈现代码的映射关系,便于在开发过程中调试代码
开发环境搞定了,别忘了生产环境也加点料
- 配置多线程打包,打包提速(happypack,thread-loader,cssloader等);
- 每次build前都清空输出目录,防止残留文件影响及磁盘占用;
- 打包前还要清除所有的console.log。
搞定!收工!