webpack性能优化
主要从下面两个方面入手
- 优化开发体验
- 优化输出质量
优化开发体验
- 提升效率
- 优化构建速度
- 优化使用体验
优化输出质量
- 优化要发布到线上的代码, 减少用户能感知到的加载时间
- 提升代码性能,性能好,执行就快
缩⼩⽂件范围 Loader
优化loader配置
- test include exclude三个配置项来缩⼩loader的处理范围
- 推荐include
{ |
优化resolve.modules配置
resolve.modules⽤于配置webpack去哪些⽬录下寻找第三⽅模块,默认是[‘node_modules’]
寻找第三⽅模块,默认是在当前项⽬⽬录下的node_modules⾥⾯去找,
如果没有找到,就会去上⼀级⽬录../node_modules找,再没有会去../../node_modules中找,
以此类推,和Node.js的模块寻找机制很类似。
如果我们的第三⽅模块都安装在了项⽬根⽬录下,就可以直接指明这个路径。
module.exports={ |
优化resolve.alias配置
resolve.alias配置通过别名来将原导⼊路径映射成⼀个新的导⼊路径
拿react为例,我们引⼊的react库,⼀般存在两套代码
cjs 采⽤commonJS规范的模块化代码
umd 已经打包好的完整代码,没有采⽤模块化,可以直接执⾏
默认情况下,webpack会从⼊⼝⽂件./node_modules/bin/react/index开始递归解析和处理依赖
的⽂件。我们可以直接指定⽂件,避免这处的耗时。
alias: { |
优化resolve.extensions配置
resolve.extensions在导⼊语句没带⽂件后缀时,webpack会⾃动带上后缀后,去尝试查找⽂件是否存
在。
默认值:
extensions:['.js','.json','.jsx','.ts'] |
- 后缀尝试列表尽量的⼩
- 导⼊语句尽量的带上后缀。
使⽤externals优化cdn静态资源
前提是公司有cdn, 不建议使用免费cdn
/公司有cdn
//静态资源有部署到cdn 有链接了
// 我想使⽤cdn!!!!!!!!
我的bundle⽂件⾥,就不⽤打包进去这个依赖了,体积会⼩
我们可以将⼀些JS⽂件存储在 CDN 上(减少 Webpack 打包出来的 js 体积),在 index.html 中通过
标签引⼊。
同时,我们希望在使⽤时,仍然可以通过 import 的⽅式去引⽤(如 import $ from ‘jquery’ ),并且希望
webpack 不会对其进⾏打包,此时就可以配置 externals 。
//webpack.config.js |
使⽤静态资源路径publicPath(CDN)
CDN通过将资源部署到世界各地,使得⽤户可以就近访问资源,加快访问速度。要接⼊CDN,需要把⽹
⻚的静态资源上传到CDN服务上,在访问这些资源时,使⽤CDN服务提供的URL。
// webpack.config.js |
- 咱们公司得有cdn服务器地址
- 确保静态资源⽂件的上传与否
借助MiniCssExtractPlugin 完成抽离css
如果不做抽取配置,我们的 css 是直接打包进 js ⾥⾯的,我们希望能单独⽣成 css ⽂件。 因为单独⽣
成css,css可以和js并⾏下载,提⾼⻚⾯加载效率
// npm install mini-css-extract-plugin -D |
压缩css
- 借助 optimize-css-assets-webpack-plugin
- 借助cssnano
// npm install cssnano -D |
压缩HTML
- 借助html-webpack-plugin
new htmlWebpackPlugin({ |
区分环境打包
webpack-merge, 用于合并配置
const merge = require("webpack-merge") |
修改package.json
//package.js |
借助cross-env 区分环境
npm i cross-env -D |
修改 package.json文件
"dev": "cross-env NODE_ENV=development webpack --config ./webpack.config.dev.js", |
webpack.config.js中可以拿到变量
process.env.NODE_ENV |
如果module.exports是一个函数的话,可以通过参数接收
//外部传⼊的全局变量 |
tree Shaking
webpack2.x开始⽀持 tree shaking概念,顾名思义,”摇树”,清除⽆⽤ css,js(Dead Code)
Dead Code ⼀般具有以下⼏个特征
- 代码不会被执⾏,不可到达
- 代码执⾏的结果不会被⽤到
- 代码只会影响死变量(只写不读)
- Js tree shaking只⽀持ES module的引⼊⽅式!!!!,
Css tree shaking
// npm i glob-all purify-css purifycss-webpack --save-dev |
修改webpack.config.js
plugins: [ |
js tree shaking
只⽀持import⽅式引⼊,不⽀持commonjs的⽅式引⼊
//webpack.config.js |
只要mode是production就会⽣效,develpoment的tree shaking是不⽣效的,
因为webpack为了⽅便你的调试
⽣产模式不需要配置,默认开启
代码分割 code Splitting
为什么要代码分割 ?
单页面应用(spa)
打包完后,所有⻚⾯只⽣成了⼀个bundle.js
- 代码体积变⼤,不利于下载
- 没有合理利⽤浏览器资源
多页面应用(mpa)
如果多个⻚⾯引⼊了⼀些公共模块,那么可以把这些公共的模块抽离出来,单独打包。公共代码只需要
下载⼀次就缓存起来了,避免了重复下载。
import _ from "lodash"; |
其实code Splitting概念 与 webpack并没有直接的关系,只不过webpack中提供了⼀种更加⽅便的⽅法
供我们实现代码分割
基于https://webpack.js.org/plugins/split-chunks-plugin/
optimization: { |
所有的配置项,如下
optimization: { |
DllPlugin插件打包第三⽅类库 优化构建性能
Dll动态链接库 其实就是做缓存
.dll⽂件称为动态链接库,在windows系统会经常看到.
项⽬中引⼊了很多第三⽅库,这些库在很⻓的⼀段时间内,基本不会更新,打包的时候分开打包来提升
打包速度,⽽DllPlugin动态链接库插件,其原理就是把⽹⻚依赖的基础模块抽离出来打包到dll⽂件中,
当需要导⼊的模块存在于某个dll中时,这个模块不再被打包,⽽是去dll中获取。
- 动态链接库只需要被编译⼀次,项⽬中⽤到的第三⽅模块,很稳定,例如react,react-dom,只要
没有升级的需求
webpack已经内置了对动态链接库的⽀持
- DllPlugin:⽤于打包出⼀个个单独的动态链接库⽂件
- DllReferencePlugin:⽤于在主要的配置⽂件中引⼊DllPlugin插件打包好的动态链接库⽂件
新建webpack.dll.config.js⽂件,打包基础模块
我们在 index.js 中使⽤了第三⽅库 react 、 react-dom ,接下来,我们先对这两个库先进⾏打包。
const path = require("path"); |
在package.json中添加
"dev:dll": "webpack --config ./build/webpack.dll.config.js", |
然后,运行
npm run dev:dll |
你会发现多了⼀个dll⽂件夹,⾥边有dll.js⽂件,这样我们就把我们的React这些已经单独打包了
dll⽂件包含了⼤量模块的代码,这些模块被存放在⼀个数组⾥。⽤数组的索引号为ID,通过变量讲
⾃⼰暴露在全局中,就可以在window.xxx访问到其中的模块Manifest.json 描述了与其对应的dll.js包含了哪些模块,以及ID和路径。
接下来怎么使⽤呢?
要给web项⽬构建介⼊动态链接库,需要完成以下事情:
将⽹⻚依赖的基础模块抽离,打包到单独的动态链接库,⼀个动态链接库是可以包含多个模块的。
当需要导⼊的模块存在于某个动态链接库中时,不要再次打包,直接使⽤构建好的动态链接库即
可。## webpack.dev.config.js 添加 下面plugin
new DllReferencePlugin({
manifest: path.resolve(__dirname,"./dll/react-manifest.json")
}),⻚⾯依赖的所有动态链接库都需要被加载。
|
⼿动添加使⽤,体验不好,这⾥推荐使⽤add-asset-html-webpack-plugin插件帮助我们做这个事情。
安装⼀个依赖 npm i add-asset-html-webpack-plugin ,它会将我们打包后的 dll.js ⽂件注⼊到我
们⽣成的 index.html 中.在 webpack.base.config.js ⽂件中进⾏更改。
new AddAssetHtmlWebpackPlugin({ |
npm run dev
这个理解起来不费劲,操作起来很费劲。所幸,在Webpack5中已经不⽤它了,⽽是
⽤ HardSourceWebpackPlugin ,⼀样的优化效果,但是使⽤却及其简单