优化前的准备工作
- 准备基于时间的分析工具:我们需要一类插件,来帮助我们统计项目构建过程中在编译阶段的耗时情况。
speed-measure-webpack-plugin分析插件加载的时间 - 使用
webpack-bundle-analyzer分析产物内容
代码优化:
无用代码消除,是许多编程语言都具有的优化手段,这个过程称为 DCE (dead code elimination),即 删除不可能执行的代码;
例如我们的 UglifyJs,它就会帮我们在生产环境中删除不可能被执行的代码,例如:
var fn = function() {
return 1;
// 下面代码便属于 不可能执行的代码;
// 通过 UglifyJs (Webpack4+ 已内置) 便会进行 DCE;
var a = 1;
return a;
}
摇树优化 (Tree-shaking),这是一种形象比喻。我们把打包后的代码比喻成一棵树,这里其实表示的就是,通过工具 “摇” 我们打包后的 js 代码,将没有使用到的无用代码 “摇” 下来 (删除)。即 消除那些被 引用了但未被使用 的模块代码。
- 原理: 由于是在编译时优化,因此最基本的前提就是语法的静态分析,ES6的模块机制 提供了这种可能性。不需要运行时,便可进行代码字面上的静态分析,确定相应的依赖关系。
- 问题: 具有 副作用 的函数无法被
tree-shaking- 在引用一些第三方库,需要去观察其引入的代码量是不是符合预期;
- 尽量写纯函数,减少函数的副作用;
- 可使用
webpack-deep-scope-plugin,可以进行作用域分析,减少此类情况的发生,但仍需要注意;
code-spliting: 代码分割技术,将代码分割成多份进行 懒加载 或 异步加载,避免打包成一份后导致体积过大,影响页面的首屏加载;
Webpack中使用SplitChunksPlugin进行拆分;- 按 页面 拆分: 不同页面打包成不同的文件;
- 按 功能 拆分:
- 将类似于播放器,计算库等大模块进行拆分后再懒加载引入;
- 提取复用的业务代码,减少冗余代码;
- 按 文件修改频率 拆分: 将第三方库等不常修改的代码单独打包,而且不改变其文件 hash 值,能最大化运用浏览器的缓存;
scope hoisting: 作用域提升,将分散的模块划分到同一个作用域中,避免了代码的重复引入,有效减少打包后的代码体积和运行时的内存损耗;
编译性能优化:
- 升级至 最新 版本的
webpack,能有效提升编译性能; - 使用
dev-server/ 模块热替换 (HMR) 提升开发体验;- 监听文件变动 忽略 node_modules 目录能有效提高监听时的编译效率;
- 缩小编译范围
modules: 指定模块路径,减少递归搜索;mainFields: 指定入口文件描述字段,减少搜索;noParse: 避免对非模块化文件的加载;includes/exclude: 指定搜索范围/排除不必要的搜索范围;alias: 缓存目录,避免重复寻址;
babel-loader- 忽略
node_moudles,避免编译第三方库中已经被编译过的代码 - 使用
cacheDirectory,可以缓存编译结果,避免多次重复编译
- 忽略
- 多进程并发
webpack-parallel-uglify-plugin: 可多进程并发压缩 js 文件,提高压缩速度;HappyPack: 多进程并发文件的Loader解析;
- 第三方库模块缓存:
DLLPlugin和DLLReferencePlugin可以提前进行打包并缓存,避免每次都重新编译;
- 使用分析
Webpack Analyse / webpack-bundle-analyzer对打包后的文件进行分析,寻找可优化的地方- 配置profile:true,对各个编译阶段耗时进行监控,寻找耗时最多的地方
source-map:- 开发:
cheap-module-eval-source-map - 生产:
hidden-source-map;
- 开发:
优化webpack打包速度
- 减少文件搜索范围
- 比如通过别名
loader的test,include & exclude
Webpack4默认压缩并行Happypack并发调用babel也可以缓存编译Resolve在构建时指定查找模块文件的规则- 使用
DllPlugin,不用每次都重新构建 externals和DllPlugin解决的是同一类问题:将依赖的框架等模块从构建过程中移除。它们的区别在于- 在 Webpack 的配置方面,
externals更简单,而DllPlugin需要独立的配置文件。 DllPlugin包含了依赖包的独立构建流程,而externals配置中不包含依赖框架的生成方式,通常使用已传入 CDN 的依赖包externals配置的依赖包需要单独指定依赖模块的加载方式:全局对象、CommonJS、AMD 等- 在引用依赖包的子模块时,
DllPlugin无须更改,而externals则会将子模块打入项目包中
- 在 Webpack 的配置方面,
优化打包体积
- 提取第三方库或通过引用外部文件的方式引入第三方库
- 代码压缩插件
UglifyJsPlugin - 服务器启用
gzip压缩 - 按需加载资源文件
require.ensure - 优化
devtool中的source-map - 剥离
css文件,单独打包 - 去除不必要插件,通常就是开发环境与生产环境用同一套配置文件导致
Tree Shaking在构建打包过程中,移除那些引入但未被使用的无效代码- 开启
scope hosting- 体积更小
- 创建函数作用域更小
- 代码可读性更好

本文探讨了Webpack的性能优化策略,包括代码优化如DCE和Tree-shaking,避免副作用,代码分割技术以实现懒加载,作用域提升,以及编译性能优化措施,如忽略node_modules,缓存编译结果,多进程并发处理,同时提供了配置优化建议,以减少文件搜索范围和提升打包速度。
317

被折叠的 条评论
为什么被折叠?



