- alias路径查找优化
loader解析转换慢:配置loader的test、include、exclude,缩小文件解析搜索范围。
- publicPath配置cdn
- 文件压缩:生产模式,代码自动压缩
第三方依赖多,搜索解析文件慢:
采用缓存策略,hard-source-webpack-plugin为依赖模块提供中间缓存,极大程度地提升二次构建速度。
2、
3、
压缩打包资源plugin执行慢:比如uglify-webpack-plugin,可以开启缓存、多进程。
按需加载:代码分割 & 提取公共代码
code split
主要有 2 种方式:
- 分离业务代码和第三方库( vendor )
- 按需加载(利用 import() 语法
chunk 有两种形式:
- initial(初始化) 是入口起点的 main chunk。此 chunk 包含为入口起点指定的所有模块及其依赖项。
- non-initial 是可以延迟加载的块。可能会出现在使用 动态导入(dynamic imports) 或者 SplitChunksPlugin 时。
optimization: {
splitChunks: {
chunks: "all", // 所有的 chunks 代码公共的部分分离出来成为一个单独的文件
},
},
dll vs externals
如果我们想引用一个库,但是又不想让webpack打包,并且又不影响我们在程序中以CMD、AMD或者window/global全局等方式进行使用,那就可以通过配置Externals。这个功能主要是用在创建一个库的时候用的,但是也可以在我们项目开发中充分使用 Externals的方式,我们将这些不需要打包的静态资源从构建逻辑中剔除出去,而使用 CDN 的方式,去引用它们。
有时我们希望我们通过script引入的库,如用CDN的方式引入的jquery,我们在使用时,依旧用require的方式来使用,但是却不希望webpack将它又编译进文件中
<script
src="https://code.jquery.com/jquery-3.1.0.js"
integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
crossorigin="anonymous">
</script>
module.exports = {
//...
externals: {
jquery: 'jQuery'
}
};
import $ from 'jquery';
$('.my-element').animate(/* ... */);
基于externals的优化
可以详见webpack5多联邦的笔记
自动化处理等等 以及 externals的弊端
缓存
长效缓存和编译缓存
长效缓存是浏览器层面的缓存: http缓存相关知识点==> 资源有稳定的hash
Webpack通过optimization的splitChunks和runtimeChunk的配置,让编译输出的文件具有稳定的hash名称,从而让浏览器能长期有效、安全的复用缓存,达到加速页面加载的效果。
编译缓存是编译时的缓存:
Webpack通过在首次编译后把结果缓存起来,在后续编译时复用缓存,从而达到加速编译的效果。
现象:
- 代码热更新很快
- npm run star慢
- npm run build慢
原因:热更新的时候用了本地的缓存;其余情况都属于首次编译,没有缓存
一般的解决方案是:
1、预编译配置dll等技术,将不太变的第三方庫单独打包走单独的缓存
webpack5,要持久化什么,做了很好的回答:
持久化什么:Webpack运行时存在于内存中的那些缓存,不是loader的产物,更不是dll
实现:
- IdleFileCachePlugin:持久化到本地磁盘
- MemoryCachePlugin:持久化到内存
根据Webpack运行环境的不同,在dev开发时依旧使用MemoryCachePlugin,而在build时使用IdleFileCachePlugin。
Webpack5的内置缓存方案无论从性能上还是安全性上都要好于cache-loader:
- 性能上:由于所以被webpack处理的模块都会被缓存,缓存的覆盖率要高的多
- 安全上:由于cache-loader使用了基于mtime的缓存验证机制(参考),导致在CI环境中缓存经常会失效,
但是Webpack5改用了基于文件内容etag的缓存验证机制,解决了这个问题。
Webpack4上常用的缓存插件:hard-source-webpack-plugin(其实就是webpack5纳入了他)
结论:DLL退出历史舞台了
Dll
事先把常用但又构建时间长的代码提前打包好(例如 react、react-dom),取个名字叫 dll。后面再打包的时候就跳过原来的未打包代码,直接用 dll。这样一来,构建时间就会缩短,提高 webpack 打包速度。
DLL 就是个另类缓存。
DLL | 缓存 |
---|---|
1.把公共代码打包为 DLL 文件存到硬盘里 | 1.把常用文件存到硬盘/内存里 |
2.第二次打包时动态链接 DLL 文件,不重新打包 | 2.第二次加载时直接读取缓存,不重新请求 |
3.打包时间缩短 | 3.加载时间缩短 |
**手动创建并管理缓存系统原理:
**
- 第一次请求的时候,把请求后的内容存储起来
- 建立一个映射表,当后续有请求时,先根据这个映射表到看看要请求的内容有没有被缓存,有的话就加载缓存,没有就走正常请求流程(也就是所谓的缓存命中问题)
- 命中缓存后,直接从缓存中拿取内容,交给程序处理
hard-source-webpack-plugin原理
Scope Hoisting
tree shaking
目前在webpack4 我们设置mode为production的时候已经自动开启了tree-shaking。但是要想使其生效,生成的代码必须是ES6模块
happypack多进程并发
Webpack是单线程模型的,也就是说Webpack需要一个一个地处理任务,不能同时处理多个任务。 Happy Pack 就能让Webpack做到这一点,它将任务分解给多个子进程去并发执行,子进程处理完后再将结果发送给主进程。
cnpm i -D happypack
// webpack.config.js
rules: [
{
// cnpm i babel-loader @babel/core @babel/preset-env -D
test: /\.jsx?$/,
exclude: /node_modules/,
use: [
{
// 一个loader对应一个id
loader: "happypack/loader?id=busongBabel"
}
]
}
]
//在plugins中增加
plugins:[
new HappyPack({
// 用唯一的标识符id,来代表当前的HappyPack是用来处理一类特定的文件
id:'busongBabel',
// 如何处理.js文件,用法和Loader配置中一样
loaders:['babel-loader?cacheDirectory'],
threadPool: HappyPackThreadPool,
})
]