本指南包含一些提高构建/编译性能的实用技巧。
无论您是在开发环境还是生产环境运行构建脚本,以下最佳实践都应有所帮助。
使用最新版本的 webpack。我们一直在进行性能改进。最新推荐的 webpack 版本是
保持 Node.js 最新也有助于提高性能。除此之外,保持您的包管理器(例如 npm
或 yarn
)最新也有助于提升性能。新版本会创建更高效的模块树并提高解析速度。
将加载器应用于最少数量的必要模块。而不是
module.exports = {
//...
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
},
],
},
};
使用 include
字段只将加载器应用于那些实际需要通过它进行转换的模块
const path = require('path');
module.exports = {
//...
module: {
rules: [
{
test: /\.js$/,
include: path.resolve(__dirname, 'src'),
loader: 'babel-loader',
},
],
},
};
每个额外的加载器/插件都有一个启动时间。尽量少使用工具。
以下步骤可以提高解析速度
resolve.modules
、resolve.extensions
、resolve.mainFiles
、resolve.descriptionFiles
中的项数,因为它们会增加文件系统调用次数。npm link
或 yarn link
),请设置 resolve.symlinks: false
。resolve.cacheWithContext: false
。使用 DllPlugin
将不常更改的代码移动到单独的编译中。这将提高应用程序的编译速度,尽管它确实增加了构建过程的复杂性。
减小编译的总大小以提高构建性能。尽量保持块小。
SplitChunksPlugin
。async
模式使用 SplitChunksPlugin
。thread-loader
可用于将昂贵的加载器分载到工作线程池。
在 webpack 配置中使用 cache
选项。在 package.json
的 "postinstall"
脚本中清除缓存目录。
对它们进行性能分析,以避免在此处引入性能问题。
通过从 webpack 配置中移除 ProgressPlugin
,可以缩短构建时间。请记住,ProgressPlugin
对于快速构建可能也提供不了太多价值,因此请确保您正在利用使用它的好处。
以下步骤在开发环境中特别有用。
使用 webpack 的观察模式。不要使用其他工具来观察您的文件并调用 webpack。内置的观察模式将跟踪时间戳并将此信息传递给编译,以进行缓存失效。
在某些设置中,观察模式会回退到轮询模式。当有许多文件被观察时,这会导致大量的 CPU 负载。在这种情况下,您可以使用 watchOptions.poll
增加轮询间隔。
以下实用程序通过在内存中编译和提供资源而不是写入磁盘来提高性能
webpack-dev-server
webpack-hot-middleware
webpack-dev-middleware
Webpack 4 默认会通过其 stats.toJson()
输出大量数据。除非在增量步骤中必要,否则请避免检索 stats
对象的某些部分。v3.1.3 之后的 webpack-dev-server
包含一个实质性的性能修复,以最小化每个增量构建步骤从 stats
对象中检索的数据量。
请注意不同 devtool
设置之间的性能差异。
"eval"
具有最佳性能,但对转译后的代码没有帮助。cheap-source-map
变体性能更高。eval-source-map
变体。某些实用程序、插件和加载器仅在构建生产环境时才有意义。例如,在开发过程中使用 TerserPlugin
压缩和混淆代码通常没有意义。这些工具通常应在开发环境中排除
TerserPlugin
[fullhash]
/[chunkhash]
/[contenthash]
AggressiveSplittingPlugin
AggressiveMergingPlugin
ModuleConcatenationPlugin
Webpack 只会向文件系统发出更新的块。对于某些配置选项(HMR、output.chunkFilename
中的 [name]
/[chunkhash]
/[contenthash]
、[fullhash]
),除了已更改的块之外,入口块也会失效。
通过保持入口块小来确保其发出开销低。以下配置为运行时代码创建了一个额外的块,因此生成开销很低
module.exports = {
// ...
optimization: {
runtimeChunk: true,
},
};
Webpack 会进行额外的算法工作,以优化输出的大小和加载性能。这些优化对于较小的代码库性能良好,但对于较大的代码库可能会付出高昂的代价
module.exports = {
// ...
optimization: {
removeAvailableModules: false,
removeEmptyChunks: false,
splitChunks: false,
},
};
Webpack 能够在输出包中生成路径信息。然而,这会给捆绑数千个模块的项目带来垃圾回收压力。在 options.output.pathinfo
设置中关闭此功能
module.exports = {
// ...
output: {
pathinfo: false,
},
};
Node.js 版本 8.9.10 - 9.11.1 中的 ES2015 Map
和 Set
实现存在性能退化。Webpack 大量使用这些数据结构,因此此退化会影响编译时间。
更早和更晚的 Node.js 版本不受影响。
为了在使用 ts-loader
时提高构建时间,请使用 transpileOnly
加载器选项。此选项本身会关闭类型检查。要重新获得类型检查,请使用 ForkTsCheckerWebpackPlugin
。这通过将 TypeScript 类型检查和 ESLint linting 移至单独的进程来加速它们。
module.exports = {
// ...
test: /\.tsx?$/,
use: [
{
loader: 'ts-loader',
options: {
transpileOnly: true,
},
},
],
};
以下步骤在生产环境中特别有用。
Source maps 开销非常大。您真的需要它们吗?
以下工具存在某些可能降低构建性能的问题
fork-ts-checker-webpack-plugin
在单独的进程中进行类型检查。happyPackMode: true
/ transpileOnly: true
模式下使用 ts-loader
。node-sass
有一个 bug,会阻塞 Node.js 线程池中的线程。当与 thread-loader
一起使用时,请设置 workerParallelJobs: 2
。