本章学习让我认识到:工程化的核心不是记住某个构建工具怎么配置,而是理解业务代码从源码到浏览器可运行资源之间,究竟经历了什么。换句话说,工具可以换,但"解析编译、模块分包、压缩优化"这些工程化内部职责是相对稳定的。
工程化设计:业务代码如何变成可运行资源
在前端开发中,我们写的业务代码需要经过构建工具处理后,才能在浏览器中正确运行。可以把工程化设计拆成三个核心环节。
1. 解析和编译
执行构建命令后,构建工具会从入口文件开始,递归读取并解析模块:通过 loader 转换资源,通过 parser 分析 import / require 等依赖声明,最终构建出模块依赖图(后续的模块分包和 chunk 拆分,都是基于这张依赖图进行的)。在解析各个模块时,再通过对应的 loader 或解析器,把新语法、新 API、框架代码等编译成浏览器可识别并运行的资源。
解析编译能力让代码具备了在不同版本浏览器中正确运行的基础,也提升了代码兼容性。
2. 模块分包
当项目变复杂后,模块依赖增多,编译输出的资源体积也会增大。如果一次性加载过大资源,浏览器加载时间会变长,体验变差。因此需要对编译后的资源做合理拆分,按改动频率和引用频率组织模块,并结合按需加载和浏览器/CDN 缓存,提升运行时体验。
3. 压缩优化
压缩优化是在编译和分包之后进一步处理资源,包括剔除无用代码、压缩代码、利用多线程和缓存等。它的目标有两个:一是提高打包构建速度,二是提高浏览器加载资源的速度。
工程化搭建:用 webpack5 落地工程化思想
带着上面的设计思想,使用 webpack5 搭建工程化配置,重点包括入口、解析编译、模块分包和压缩优化。
1. 入口配置
当项目存在多入口或混合型入口时,写死入口文件并不合适。更合理的做法是预先约定入口目录和输出目录,利用 Node 的文件系统模块解析入口目录,动态创建入口配置对象。这样同一套配置可以适配单入口和多入口场景。
2. 解析编译配置
通过配置相应的 loader,对匹配到的资源进行编译,提高代码的运行能力和兼容性。这里的配置不是孤立地"加 loader",而是服务于"让业务代码在目标浏览器中正确运行"。
3. 模块分包配置
模块分包的主要目的,是把不同业务代码按改动频率和引用频率拆分,达到模块复用、减小打包体积、更好利用浏览器缓存的效果。
4. 压缩优化配置
压缩优化需要根据环境区分配置。
开发环境下,重点是开发体验。通过 devServer 实现代码修改后实时查看页面效果、及时定位错误。其内部原理可以概括为三步:
- 监听业务代码变化,发生变化就触发编译;
- 重新执行解析编译、分包和压缩优化,产出入口文件,依赖资源存放在内存中;
- HMR 与浏览器建立通道,检测到内存资源变化后通知浏览器更新模块,浏览器重新从内存下载资源,实现实时刷新。
生产环境下,重点是代码兼容性、运行性能和构建效率。
- 一方面通过解析编译提高兼容性和运行能力,通过模块分包拆分管理业务代码,通过压缩优化提升运行性能;
- 另一方面配置 cache、多进程打包等能力提高构建速度,整体提升打包体验和代码性能。
elpis 基础建设:把工程化思想落到项目基础能力
工程化不仅是构建配置,也包括项目基础能力的统一和复用。
1. 配置统一的启动文件
多入口项目往往会使用 vue-router、element-plus、store 等三方库。如果每个入口都重复引入,既冗余又繁琐。通过统一启动文件,可以集中注册页面组件和依赖的三方库,减少重复代码。
2. 区分 router 的使用方式
项目采用 SSR 和 CSR 组合渲染方式,实现前后端路由结合。例如通过服务端渲染首页,利用其 SEO 友好的特性;前端组件中的 vue-router 再渲染组件页面,保持加载不同内容的灵活性。
3. 关注代码性能细节
编写代码时应根据运行场景选择遍历方式,例如 for 或 forEach。但也要注意,这类差异通常有限,不应绝对化;更合理的是保持可读性,在热点路径上再评估性能。重要的是养成性能意识,通过积少成多构建稳定系统。
4. 封装公共部分
以基础 ajax 请求封装为例:统一管理请求参数和签名参数处理;统一处理请求异常和错误信息返回;统一处理请求结果的成功与失败提示及返回信息。这样能提升复用性和维护性。
总结
这次学习的主线可以概括为:先让代码能运行,再让资源加载更快,再让开发更高效,最后让项目更可维护、可复用。 解析编译、模块分包、压缩优化是工程化设计的核心环节;webpack5 是落地手段;elpis 基础建设则体现了工程化思想在项目基础能力上的延伸。理解这条主线,比单纯记住某个配置项更重要。