一、前言
如果觉得本文内有些代码或路径编写让人感觉比较绕的,建议把项目拉到本地,参照着项目结构去阅读文章。
项目结构
本文会以 demo08 作为项目文件夹,各文件直接拿之前项目 demo07 的,接下来做些修改。
1 | { |
1 | { |
1 | ... |
为了方便后面案例的讲述,去除 webpack.ProvidePlugin 这个插件的使用。
1 | ... |
在本文中一些目录及文件不需要 ESLint 去进行代码检测。
1 | ... |
1 | import $ from 'jquery' |
1 | import $ from 'jquery' |
安装依赖
1 | npm ci |
二、Webpack 性能优化
跟上技术迭代
在项目开发中尽可能去使用新版本的 Webpack、node 以及 npm、yarn 等包管理工具。新版本的工具能够利用一些特性去提高我们的打包速度。
在尽可能少的模块上使用 Loader
一般在打包 js 文件时,我们会通过 babel 去进行转译,但在引入第三方模块的 js 文件,该文件已经被打包编译过了,再对它进行一次转译是没有意义的,只会降低打包的速度。
我们可以在打包 js 文件时进行一些设置来避免对第三方模块 js 文件的再次转译。
1 | rules:[ |
当 exclude 和 include 同时存在,会包含 include 的所有内容,不包含 exclude 的所有内容,但如果 exclude 和 include 存在相同的内容,就会引起报错。
Plugin 尽可能精简并确保可靠
例如之前文章的案例中,对 css 压缩处理只在生产环境去使用该插件,开发环境并不需要该插件,这时候开发环境就节约了代码压缩这部分的打包时间。
插件的选择上,一般会使用 Webpack 官网推荐的插件,这些插件的性能经过了官方的测试,是比较快的,以及可以选择社区认可的插件来使用。
resolve 参数的合理配置
extensions
在一些项目开发中,我们可能会遇到过这样一种情况,引入文件不需要写后缀名也能成功引入。例如本文中的代码,index.js 对 jquery.ui.js 的引入,写的是 import $ form './jquery.ui'
而不是 import $ form './jquery.ui.js'
。
Webpack 默认支持省略引入文件 js 后缀名的编写,可以通过在 Webpack 的打包配置文件里设置 resolve 配置项实现其他文件后缀名的省略。
1 | ... |
当我们配置了太多的文件后缀名,例如:extensions: ['.jpg', '.css', '.js', '.vue']
,就意味着每当引入一个文件就需要进行很多次的查找,实际上是有性能损耗的,所以一般去引入一些逻辑性的文件,例如 js、vue 才会去进行相应的设置。
mainFiles
假设现在 src 目录下有个 child 目录,child 目录下有个 index.js,那么 src 目录下的 index.js 通过 import child form ./child/
就可以引入 child 目录下的 index.js,因为 Webpack 默认进行了相应的配置,我们可以通过设置 mainFiles 去实现其他文件名的省略。
1 | resolve: { |
当 mainFiles 配置了太多的文件名,同样存在性能上的问题。一般不需要去设置 mainFiles,默认找 index 命名的文件即可。
alias
假设现在 src 目录下的 index.js 引入这样一个 child 目录下的 index.js 文件:
1 | import child form './a/b/c/child/index.js' |
引入的文件路径比较长,我们就可以进行 alias 配置项的设置。
1 | resolve: { |
这时候 index.js 内只需这样引入:
1 | import child form 'child' |
控制打包文件大小
当在项目中引入了一些模块却没有使用,就需要配置 Tree Shaking 或者手动去除引入,减小打包体积。
还可以通过 Code Splitting 把大文件拆分为几个小文件来提高 Webpack 打包速度。
合理使用 SourceMap
我们需要思考在不同环境下使用什么样的 SourceMap 是最合适的,结合业务场景去使用。
结合 stats 分析打包结果
通过运行命令把打包过程及结果存储到 stats.json,把该文件结合线上或者本地的打包分析工具,查看哪些打包模块耗时比较久,体积比较大,来做相应的优化。
多进程打包
Webpack 默认是通过 NodeJS 来运行的,是个单进程的打包过程,有时候可以借助 node 中的多进程来帮助我们提高打包速度,接触 thread-loader、parallel-webpack、happypack 这些,使用到 node 中的多进程,同时使用多个 cpu 进行项目打包,提高打包速度。
课程内没有具体展开去讲,对 thread-loader、parallel-webpack、happypack 这些多进程打包工具感兴趣的小伙伴可以去搜索相关文档。
开发环境使用 DDLPlugin 提高打包速度
当项目中引入了第三方模块后对打包速度会有些影响,每次重新打包都需要重新去分析这些第三方模块进行打包,现在我们的项目 demo08 中引入了 lodash 以及 jquery,运行开发环境打包命令进行打包,打包三四次观察打包耗时,都在 1600ms 以上。
1 | npm run dev-build |
我们希望项目中引入的第三方模块只在第一次打包时做分析,打包到一个 js 文件里,第二第三次就没必要重新分析了,直接拿第一次打包生成的 js 文件使用,提高打包速度。
在 build 目录下新建 webpack.dll.js 做第三方模块打包用的配置文件。
1 | const path = require('path') |
package.json 新增 scripts 脚本命令打包第三方模块
1 | { |
运行第三方模块打包命令
1 | npm run build:dll |
项目根路径下生成 dll 目录以及 dll 目录下 vendors.dll.js,该 js 文件内就打包了我们项目中需要的第三方模块 jquery 以及 lodash。
这时候需要 dist 目录下 index.html 引入 vendors.dll.js 进行使用,安装插件 add-asset-html-webpack-plugin。
1 | npm install add-asset-html-webpack-plugin@3.1.2 -D |
在开发环境使用该插件
1 | ... |
运行开发环境打包命令,把生成的 dist 目录下 index.html 放入浏览器,在控制台打印 vendors,能够正常打印结果。
但现在项目内去获取第三方模块还是到 node_modules 目录下取,想要做到引入第三方模块时使用我们打包的 dll 文件引入,还需在打包 dll 文件时做一个映射。
1 | ... |
重新运行第三方模块打包命令,dll 目录下除了 vendors.dll.js,还新增了 vendors.manifest.json 这个映射文件。
接着在开发环境使用一个引用 dll 的插件
1 | ... |
这时候重新运行开发环境打包命令,能够发现确实比一开始的打包速度快了一些,感知不明显是因为我们案例涉及代码量太少。
模块拆分
当 dll 文件想要做模块的拆分,可以进行相应的配置。
1 | ... |
运行第三方模块打包命令,dll 目录下新增 lodash.dll.js 以及 lodash.manifest.json。
接着配置下开发环境的打包配置文件,还是上面那套流程,需要在打包后生成的 index.html 内引入 lodash.dll.js 以及分析 lodash.manifest.json 内映射关系。
1 | ... |
在大型项目中,打包生成的 dll 文件也许会很多,就需要不断地配置 AddAssetHtmlWebpackPlugin 以及 webpack 的 DllReferencePlugin。这时候我们可以换一种写法,通过 node 去分析 dll 目录下有几个文件,动态地往 plugins 里添加相应的插件配置。
1 | ... |
运行开发环境打包命令,正常打包。
开发环境内存编译(devServer)
在开发环境中我们使用 WebpackDevServer,它不会生成 dist 目录,而是把编译的文件放到内存里,内存读取肯定比硬盘读取快得多,因此通过 WebpackDevServer,开发中打包的性能得到了很大提升。
开发环境无用插件剔除
开发环境把 mode 设为 development,Webpack 打包代码不会去进行压缩,方便我们调试,没有意义的压缩代码只会让打包速度下降。以及开发环境中不需要对 css 代码压缩处理等等。
小结
提高 Webpack 打包性能的方法及配置非常多,需要我们在未来的实战配置中逐步积累经验。
三、多页面打包配置
像我们现在常用的 vue 这些主流的框架,都是单页面应用开发,但在涉及一些老项目,我们需要去了解下 Webpack 多页面的打包配置。
首先,在 src 目录下新建 list.js 以及 detail.js。
1 | document.write('list') |
1 | document.write('detail') |
修改打包配置文件 webpack.common.js
1 | ... |
运行生产环境打包命令
1 | npm run build |
这时候就完成了多页面的打包配置,达到的效果是 dist 目录下生成 index.html、list.html、detail.html 三个 html 文件。每个 html 文件除了都引入需要的 runtime、vendors 这两个 chunk 相关 js 文件,还会去引入自身需要的 js 文件,index.html 引入 index,list.html 引入 list,detail.html 引入 detail。
各 html 文件放入浏览器能够正常显示页面效果,证明打包是成功的。
除了这种写法,我们还可以通过 node 去读取配置文件里的 entry,动态往 plugins 里添加相应的插件配置。
1 | ... |
四、总结
通过以上学习,我们了解了怎样对 Webpack 的打包性能进行优化以及多页面应用的打包配置。
在我们进行 Webpack 的配置时,不仅仅就是去编写一些配置,还可以通过 node 的语法去增加一些逻辑进行处理,这样我们的打包配置就非常灵活了。
这次并没有专门一个小节去推官方文档建议看的内容,大家可以结合本文涉及的知识点,对有疑惑或者感兴趣的地方去网上进行拓展学习。
本文最后的代码我会上传到 码云(gitee.com/phao97)上,项目文件夹为 demo08。
如果觉得本篇文章对你有帮助,不妨点个赞或者给相关的 Git 仓库一个 Star,你的鼓励是我持续更新的动力!
- 本文标题:Webpack 4.0 学习笔记(八)
- 本文作者:phao
- 创建时间:2022-05-19 19:37:28
- 本文链接:http://phaode.cn/2022/05/19/Webpack-4-0-学习笔记(八)/
- 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!