Webpack构建性能优化指南
Posted Sahadev_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Webpack构建性能优化指南相关的知识,希望对你有一定的参考价值。
本指南翻译自webpack官方性能指南文档:https://webpack.js.org/guides/build-performance/
构建性能
本指南涵盖了对增进构建或编译性能的一些有效的提示。
General
以下提示对开发环境或者生产环境都有效。
Stay Up to Date
保持最新的webpack版本。我们总是在改进webpack的性能。目前最新的webpack版本为:v4.41.4
使用最新的Node.js也可以提升性能。同样的,保持npm或者yarn这样的包管理器的版本也同样可以提升性能。新版本拥有更高效的模块树与更快的解析速度。
Loaders
对需要的模块采用对应Loader,例如:
module.exports =
//...
module:
rules: [
test: /\\.js$/,
include: path.resolve(__dirname, 'src'),
loader: 'babel-loader',
,
],
,
;
以上示例通过include属性圈定了babel-loader的作用范围,如果不使用该属性,则babel-loader将会对所有的js文件作业。
Bootstrap
每一个额外的Loader或者插件都会消耗一定的启动时间,尝试使用尽可能少的工具。
Resolving
以下几点可以提升解析速度:
- 降低resolve.modules、resolve.extensions、resolve.mainFiles、resolve.descriptionFiles这些选项中item的数量,因为它们会导致更频繁的IO。
- 如果不使用symlinks(例如npm link或yarn link),那么将resolve.symlinks设为false。
- 如果使用了自定义的插件,则将resolve.cacheWithContext设置为false。
Dlls
使用DllPlugin插件将不常变更的代码进行单独编译。尽管这会增加构建的复杂度,但会提高应用的编译速度。
Smaller = Faster
降低被编译文件的体积同样可以提升构建性能。想办法使chunk更小。
- 使用体积更小/熟练更少的库。
- 在多页应用中使用SplitChunksPlugin插件。
- 在多页应用中的async模式下使用SplitChunksPlugin插件。
- 移除未被使用的代码。
- 只编译当前你正在开发的代码。
Worker Pool
thread-loader可将开销昂贵的loader转移至线程池执行。不过不能使用太多的线程,这对node.js运行时来说引发过载。另外也要降低线程与主进程模块之间的信息传输,因为IPC是昂贵的。
Persistent cache
通过cache-loader开启持续缓存的能力。
Custom plugins/loaders
对于自定义的插件与loader,请自行分析优化性能。
Progress plugin
移除ProgressPlugin可能会缩短少许的构建时间。但是要记住,这并不会带来可观的构建速度优化,所以在移除该插件之前要平衡好取舍。
Development
以下优化手段在开发环境是尤其有效的。
Incremental Builds
使用webpack的watch模式,别使用其它工具来监听文件的变化再来调用webpack。webpack内建的watch模式会保留时间戳的信息并将该信息给到编译器以使缓存失效。
在一些设置中,监听是靠轮询来完成的。随着监听文件数量的增多,这会增加大量CPU的计算量。在这种情况下,可以通过watchOptions.poll来增加轮询间隔。
Compile in Memory
以下工具通过内存编译以及内存伺服的方式提升了性能,可以尝试使用:
- webpack-dev-server
- webpack-hot-middleware
- webpack-dev-middleware
stats.toJson speed
webpack4默认情况下会通过stats.toJson()输出大量数据。除非在增量步骤中是必须的,否则避免检索stats对象。webpack-dev-server在v3.1.3之后的版本针对于这一问题做了大量的性能方面的优化。
Devtool
不同的devtool设置所引起的性能是不同的,要有这个意识。
- "eval"拥有最好的性能,不过它不会保留源代码。
- "cheap-source-map"带来的性能损耗还可以,它会有一些性能损耗。
- "eval-source-map"用来增量构建。
在大多数情况下,cheap-module-eval-source-map是最适中的方案。
Avoid Production Specific Tooling
确保工具、插件、loader只是用于生产环境而不是开发环境,否则会带来不需要的资源开销。例如,在开发环境下通常不需要对代码做混淆与压缩,比如使用TerserPlugin来实现这个能力,开发环境下是不需要的。下面这些工具在开发环境下一般都是需要被摘出来的:
- TerserPlugin
- ExtractTextPlugin
- [hash]/[chunkhash]
- AggressiveSplittingPlugin
- ModuleConcatenationPlugin
Minimal Entry Chunk
WebPack仅向文件系统发送更新的chunks。对于一些配置选项,(例如:HMR,[name]/[chunkhash]inOutput.chunkfilename,[hash])除更改的chunks外,入口chunk是无效的。
使入口chunk保持小的体量才能使更新的成本更低。下面的代码块会抽取一个包含仅仅是在运行时包含其它子块的chunk:
new CommonsChunkPlugin(
name: 'manifest',
minChunks: Infinity,
);
Avoid Extra Optimization Steps
webpack会进行额外的逻辑运算工作来优化输出代码的体量与加载性能。下面优化选项对于小型的项目代码来说是有效的,不过对于大型项目来说那就不太适用了:
module.exports =
// ...
optimization:
removeAvailableModules: false,
removeEmptyChunks: false,
splitChunks: false,
,
;
Output Without Path Info
webpack有能力在输出的Bundle中携带路径信息。然而,在有上千个组件的项目中会导致垃圾收集器的压力。可使用以下选项将这个功能关闭:
module.exports =
// ...
output:
pathinfo: false,
,
;
Node.js Versions 8.9.10-9.11.1
在Node.js 8.9.10 ~ 9.11.1的版本区间内,Map和Set的实现在性能方面表现很差,所以这影响到了webpack的编译时间。在这之前与之后的版本都没有受到影响,所以要避免使用这个版本内的Node.js。
#Production
以下优化选项尤其适用于生产环境
Multiple Compilations
当使用多重编译时,下面这些工具可能会帮到你:
- parallel-webpack 可以在线程池中完成编译。
- cache-loader 缓存可在多次编译中共享。
Source Maps
SourceMap是非常昂贵的,你真的需要它吗?
一些工具的问题
下面这些工具含有一些问题,这些问题会导致性能上有一些影响:
Babel
- 降低preset/plugin的数量。
TypeScript
- 在单独的进程中使用fork-ts-checker-webpack-plugin用于类型检查。
- 配置loader跳过类型检查。
- 在happyPackMode: true或transpileOnly: true中使用ts-loader。
Sass
- node-sass有一个Bug,这个bug会阻断Node.js线程池中的线程。当通过thread-loader使用它时,请将workerParallelJobs设置为2。
以上是关于Webpack构建性能优化指南的主要内容,如果未能解决你的问题,请参考以下文章