17项关于webpack的性能优化
本文主要优化两个方面:1.优化开发体验 2.优化输出质量
优化开发体验
- 提升效率
- 优化构建速度
- 优化使?体验
优化输出质量
- 优化要发布到线上的代码,减少?户能感知到的加载时间
- 提升代码性能,性能好,执?就快
以下基于webpack4进行优化。
- 优化loader配置
- test、include、exclude三个配置项来缩?loader的处理范围
- 推荐include
优化前的构建时间:
Time: 2429ms
进行修改代码优化:
优化之后的构建时间:
Time: 2110ms
减少了319ms
resolve.modules用于配置webpack去哪些目录下寻找第三方模块,默认是 ['node_modules']。寻找第三方,默认是在当前项目目录下的node_modules里面去找,如果没有找到,就会去上一级目录https://juejin.cn/node_modules找,再没有会去/node_modules中找,以此类推,和Node.js的模块寻找机制很类似。
如果我们的第三?模块都安装在了项?根?录下,就可以直接指明这个路径。
优化之后的构建时间:
Time: 1532ms
减少了578ms
resolve.alias配置通过别名来将原导?路径映射成?个新的导?路径。拿react为例,我们引?的react库,?般存在两套代码:
-
cjs
采?commonJS规范的模块化代码
-
umd
已经打包好的完整代码,没有采?模块化,可以直接执?
默认情况下,webpack会从?件https://juejin.cn/post/node_modules/bin/react/index开始递归解析和处理依赖的?件。我们可以直接指定?件,避免这处的耗时。
优化之后的构建时间:
Time: 1362ms
减少了170ms
resolve.extensions在导?语句没带?件后缀时,webpack会?动带上后缀后,去尝试查找?件是否存在。
默认值:
- 后缀尝试列表尽量的?
- 导?语句尽量的带上后缀。
如果想优化到极致的话,不建议用extensionx, 因为它会消耗一些性能。虽然它可以带来一些便利。
我们可以将?些JS?件存储在CDN上(减少Webpack打包出来的js体积),在index.html中通过标签引?,如:
我们希望在使?时,仍然可以通过import的?式去引?(如:import $ from 'jquery' ),并且希望webpack不会对其进?打包,此时就可以配置 externals 。
CDN通过将资源部署到世界各地,使得?户可以就近访问资源,加快访问速度。要接?CDN,需要把网页的静态资源上传到CDN服务上,在访问这些资源时,使?CDN服务提供的URL。
使用条件:
- 公司得有cdn服务器地址
- 确保静态资源?件的上传与否
- 借助optimize-css-assets-webpack-plugin
- 借助cssnano
先安装:
借助html-webpack-plugin
先安装
创建webapck.dev.js文件
创建webpack.prod.js文件
package.js
基于环境变量区分
借助cross-env
package配置命令脚本,传?参数
在webpack.config.test.js?拿到参数进行判断
webpack2.x开始?持tree shaking概念,顾名思义,"摇树",就是清除无用css,js(Dead Code)
Dead Code?般具有以下?个特征:
- 代码不会被执?,不可到达
- 代码执?的结果不会被?到
- 代码只会影响死变量(只写不读)
- Js tree shaking只?持ES module的引式!!!!
Css tree shaking
JS tree shaking
只?持import?式引?,不?持commonjs的?式引?
案例:增加expo.js文件
只要mode是production就会?效,mode是develpoment的tree shaking是不?效的,因为webpack为了?便你的调试。
可以查看打包后的代码注释以辨别是否?效。
?产模式不需要配置,默认开启。
或者在数组排除不需要tree shaking的模块
单应?spa:
打包完后,所有只?成了?个bundle.js。
- 代码体积变?,不利于下载
- 没有合理利?浏览器资源
多应?mpa:
如果多个引?了?些公共模块,那么可以把这些公共的模块抽离出来,单独打包。公共代码只需要下载?次就缓存起来了,避免了重复下载。
假如我们引个第三?的?具库,体积为1mb,?我们的业务逻辑代码也有1mb,那么打包出来的体积会在2mb,这就会导致问题:
- 文件体积?,加载时间?。
- 业务逻辑会变化,而第三具库不会,所以业务逻辑?变更,第三具库也要跟着变。
例如我们使用第三方库lodash:
其实code Splitting概念与webpack并没有直接的关系,只不过webpack中提供了?种更加?便的?法供我们实现代码分割。
打包后dist目录下多了一个文件vendors~main.js,这个文件就是分离出来的lodash
splitChunks的其他可配置项:
我们可以配置缓存组
打包之后
一般使?下?配置即可:
作?域提升(Scope Hoisting)是指webpack通过ES6语法的静态分析,分析出模块之间的依赖关系,尽可能地把模块放到同?个函数中。下?通过代码示例来理解:
新建hello.js
新建index.js
打包后,hello.js的内容和index.js会分开
我们通过配置optimization.concatenateModules=true开启Scope Hoisting
我们发现hello.js内容和index.js的内容合并在?起了!
所以通过Scope Hoisting的功能可以让Webpack打包出来的代码?件更?、运?的更快。
- speed-measure-webpack-plugin:可以测量各个插件和 loader 所花费的时间:
打包后
- webpack-bundle-analyzer:分析webpack打包后的模块依赖关系:
启动webpack构建,会默认打开?个窗?
Dll动态链接库,其实就是做缓存。
.dll?件称为动态链接库,在windows系统会经常看到.百度百科:baike.baidu.com/item/.dll/2…
项?中引?了很多第三?库,这些库在很?的?段时间内,基本不会更新,打包的时候分开打包来提升打包速度,?DllPlugin动态链接库插件,其原理就是把依赖的基础模块抽离出来打包到dll?件中, 当需要导?的模块存在于某个dll中时,这个模块不再被打包,?是去dll中获取。
- 动态链接库只需要被编译?次。项?中?到的第三?模块,版本比较稳定,例如react,react-dom,只要没有升级的需求,就可以使用。
webpack已经内置了对动态链接库的?持:
- DllPlugin:?于打包出?个个单独的动态链接库?件
- DllReferencePlugin:?于在主要的配置?件中引?DllPlugin插件打包好的动态链接库?件
新建webpack.dll.config.js?件,打包基础模块。
我们在index.js中使?了第三?库react、react-dom,接下来,我们先对这两个库先进?打包。
在package.json中添加
运?
你会发现多了?个dll?件夹,?边有dll.js?件,这样我们就把我们的React这些已经单独打包了:
- dll?件包含了?量模块的代码,这些模块被存放在?个数组?。?数组的索引号为ID,通过变量将暴露在全局中,就可以在window.xxx访问到其中的模块。
- Manifest.json 描述了与其对应的dll.js包含了哪些模块,以及ID和路径。
接下来怎么使?呢?
要给web项?构建接?动态链接库,需要完成以下事情:
- 将依赖的基础模块抽离,打包到单独的动态链接库,?个动态链接库是可以包含多个模块的。
- 当需要导?的模块存在于某个动态链接库中时,不要再次打包,直接使?构建好的动态链接库即可。
- 依赖的所有动态链接库都需要被加载。 这?推荐使?add-asset-html-webpack-plugin插件帮助我们做这个事情。
安装?个依赖 npm i add-asset-html-webpack-plugin ,它会将我们打包后的dll.js?件注?到我们?成的index.html中.在webpack.base.config.js?件中进?更改。
这个理解起来不费劲,操作起来很费劲。所幸,在Webpack5中已经不?它了,?是?HardSourceWebpackPlugin,?样的优化效果,但是使?却及其简单
- 提供中间缓存的作?
- ?次构建没有太?的变化
- 第?次构建时间就会有较?的节省
我们在webpack4中使用hard-source-webpack-plugin:
运?在Node.js之上的Webpack是单线程模型的,也就是说Webpack需要?个?个地处理任务,不能同时处理多个任务。Happy Pack就能让Webpack做到这?点,它将任务分解给多个?进程去并发执?,?进程处理完后再将结果发送给主进程。从?发挥多核CPU电脑的威?。
主要在构建时间比较久,项目复杂的时候用。