Loader相关优化
Loader的功能是转换Webpack不能识别的模块,转换过程就是一个读写操作,是比较耗时的,所以在这里介绍一下相关Loader的优化。
OneOf
Webpack中的Loader默认是会被每一个需要处理的文件都过一遍的,就像Switch语法中没有Breack一样,文件会被所有的Loader检测一遍,该操作就会导致构建的缓慢。
可以使用oneOf来改变这种检测机制,oneOf的作用就相当于breack。使用oneOf对Loader的配置做出整体优化,就会使得文件被对应的Loader处理后,就会跳出后面的检测,从而提升构建速度。如下所示:
module: {
rules: [
oneOf: {
}
]
}
babel-loader的优化
之前介绍过Webpack中如何使用Babel,我们可以很简单的得出本实战中Babel-loade的优化,如下所示:
{
loader: 'babel-loader',
options: {
cacheDirectory: true,
presets: [
[
'@babel/preset-env',
{
"useBuiltIns": "usage",
"corejs": 3
}
]
],
plugins: [
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-transform-runtime"
]
}
}
缓存优化
浏览器可以通过缓存来加速页面的加载,Webpack中也可以使用缓存来加速构建。合理利用缓存是Webpack项目优化的重要手段,本章节将介绍几种常见的优化手段。
输出文件名称的规定
一次正常的Webpack构建会输出许多文件,其中输出文件的名称是可以由开发者来规定的。比如我们实战项目中输出的build.js文件,其名称是我们在output.filename中设置的,但是这种固定写死的方式是不推荐的。其原因是当我们修改项目源码后构建出来的文件名称还是build.js,那么客户端访问网页的时候,由于浏览器的缓存,很有可能加载的还是之前的内容,无法呈现最新的内容。
output中涉及到文件名称规定的选项是filename和chunkFilename,对它们的配置推荐如下:
output: {
filename: 'main.[contentHash:5].js',
path: path.resolve(__dirname, '../dist'),
chunkFilename: 'async/async-[name]-[contentHash:5].js'
}
其中的重要点就是contentHash,表示文件的输出名称,依赖源码的内容,内容发生改变,名称才会发生改变。
之前学习output的时候,我们知道还可以使用hash和chunkhash来对输出文件命名,为什么在这里不使用hash和chunkhash?其原因是因为hash是依赖Compilation对象生成的,compilation是根据构建过程包含的所有文件产生的,如果项目中有任何一个文件修改了,打包时都会生成一个新的Compilation对象,就会造成hash改变。而同一Chunk下的文件发生了变化,无论是否有依赖关系,chunkhash都会改变。例如我们只修改了Css文件那么输出文件名称也会发生改变。
同理对由Mini-css-extract-plugin常见生成的css文件名称可以做如下配置:
new MiniCssExtractPlugin({
filename: 'css/[name].[contentHash:5].css',
chunkFilename: '[id].css',
})
如此以来,单独修改Css并不会对生成的javaScript文件名称造成影响,修改JavaScript同理。
Loader相关的缓存
有些Loader在处理文件的时候,会产生大量额外的文件,比如Babel-loader,这个时候可以使用Cache-loader将Babel-loader的处理结果缓存到内存中。如下所示:
use: [
'cache-loader',
'babel-loader',
]
并不是什么Loader都和可以Cache-laode相结合,保存和读取这些缓存文件会有一些时间开销,所以请只对性能开销较大的Loader使用此loader。
对于Babel-loader还可以开启该loader自带的缓存功能,如下所示:
{
loader: 'babel-loader',
options: {
cacheDirectory: true,
}
}
还有些其他Loader或者插件也带有缓存功能,具体的使用还需结合具体场景。
固定ChunkId
Webpack输出的文件是一个一个Chunk构成的,Chunk就是代码快,每一个Chunk都有着对应的id,称之为ChunkId。
新增或减少Chunk,都会影响chunkId,而一旦ChunkId改变那么contentHash就会发生改变,从而缓存失效。
可以使用webpack.NamedChunksPlugin插件来固定ChunkId,配置如下:
plugins: [
new webpack.NamedChunksPlugin()
]
提取runtime文件
如果你查阅过Webpack的官网,你会发现Webpack中经常会提及到runtime,那么runtime究竟是什么东西?
其实runtime就是在模块交互时,连接模块所需的加载和解析逻辑,包括浏览器中的已加载模块的连接,以及懒加载模块的执行逻辑的代码块。
当模块有依赖关系的时候,加载模块会使用runtime去加载被加载模块,当被加载模块内容发生改变的时候,加载模块中的runtime代码就会发生改变,导致加载模块和被加载模块的之间缓存失效。由于runtime文件很小,可以抽离出来直接内嵌到html中(怎么内嵌可以百度)。如下所示:
module.exports = {
optimization: {
runtimeChunk: {
name: entrypoint => `runtimechunk~${entrypoint.name}`
}
}
};
|