【webpack】如何优化webpack配置

相关文章

如何优化webpack配置


一、优化方式

使用exclude、include配置来转译更少的文件

exclude 和 include 配置项可以帮助你更精确地控制哪些文件需要被 loader 处理,从而避免处理不必要的文件,提高构建性能。这些配置项通常在 webpack 的 loader 配置中使用,例如在 module.rules 中。

  • exclude:用于排除不需要处理的文件或目录。你可以使用正则表达式或函数来指定需要排除的文件路径。

  • include:用于指定需要处理的文件或目录。与 exclude 相反,只有被包含在 include 中的文件才会被 loader 处理。

下面是一个示例配置,演示了如何在使用 Babel Loader 时利用 exclude 和 include 来转译更少的文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module.exports = {
module: {
rules: [
{
test: /\.js$/, // 匹配所有以 .js 结尾的文件
exclude: /node_modules/, // 排除 node_modules 目录下的文件
include: /src/, // 只处理 src 目录下的文件
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
}
};

在这个配置中,只有 src 目录下的 JavaScript 文件会被 Babel Loader 处理,而排除了 node_modules 目录下的文件。这样可以避免处理第三方库和其他不需要转译的文件,提高构建性能和效率。

通过合理配置 exclude 和 include,你可以更精确地控制哪些文件需要被 loader 处理,从而优化构建过程。

使用cache-loader缓存编译结果

cache-loader 是一个 webpack loader,它可以缓存 loader 的执行结果,以提高构建性能。它将处理过的模块及其转换结果存储在本地文件系统中,当下次构建时,如果输入文件的内容没有发生变化,则可以直接从缓存中读取结果,而不必重新执行 loader。

使用 cache-loader 很简单,只需要在 webpack 配置中将其添加到 loader 链中即可。以下是一个示例配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
module.exports = {
module: {
rules: [
{
test: /\.js$/, // 匹配所有以 .js 结尾的文件
use: [
{
loader: 'cache-loader', // 添加 cache-loader
options: {
cacheDirectory: path.resolve('.cache') // 指定缓存目录
}
},
'babel-loader' // 普通 loader
]
}
]
}
};

在这个配置中,cache-loader 被添加到了 babel-loader 的前面。这样,当构建过程中遇到需要被 babel-loader 处理的模块时,cache-loader 会先尝试从缓存中读取结果,如果有缓存则直接返回,否则再执行 babel-loader。

cache-loader 的 cacheDirectory 选项用于指定缓存目录的路径,默认是将缓存存储在项目根目录下的 .cache 目录中。你可以根据需要自定义缓存目录的路径。

使用happypack多核构建,把任务分给多个子进程并发执行

happypack 是一个 webpack 插件,它可以将 loader 的执行过程从 webpack 主进程中分离出来,分配给多个子进程并行执行,以加速构建过程。这样可以充分利用多核 CPU 的计算能力,提高构建性能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const HappyPack = require('happypack');

module.exports = {
module: {
rules: [
{
test: /\.js$/, // 匹配所有以 .js 结尾的文件
use: 'happypack/loader?id=js' // 使用 happypack 处理 JavaScript 文件
}
]
},
plugins: [
new HappyPack({
id: 'js', // 唯一标识符,用于指定 loader
loaders: ['babel-loader'], // 指定要使用的 loader
threads: 4 // 指定并发执行的子进程数量
})
]
};

在这个配置中,我们创建了一个 happypack 实例,并指定了一个唯一标识符 js。然后在 webpack 配置的 module.rules 中,使用 happypack/loader 替代原本的 loader 配置,并通过 id 参数指定要使用的 happypack 实例。

threads 参数用于指定并发执行的子进程数量,你可以根据 CPU 核心数和系统资源情况来调整这个值。

使用thread-loader把loader放置在单独的worker池中进行

thread-loader 是一个 webpack loader,它将其他 loader 放置在单独的 worker 池中进行处理,以提高构建性能。这意味着它会将 loader 的执行过程从 webpack 主进程中分离出来,分配给 worker 池中的多个 worker 并行执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
module.exports = {
module: {
rules: [
{
test: /\.js$/, // 匹配所有以 .js 结尾的文件
use: [
{
loader: 'thread-loader', // 添加 thread-loader
options: {
// 指定 worker 池的数量,默认为 os.cpus().length
workers: 4
}
},
'babel-loader' // 普通 loader
]
}
]
}
};

在这个配置中,我们将 thread-loader 添加到了 babel-loader 的前面。这样,当构建过程中遇到需要被 babel-loader 处理的模块时,thread-loader 会将处理过程放置在 worker 池中的一个 worker 中执行,而不是在 webpack 主进程中执行。

workers 参数用于指定 worker 池的数量,默认为 CPU 核心数。你可以根据系统资源情况来调整这个值,以充分利用系统资源。

使用HardSourceWebpackPlugin提供中间缓存,节省二次编译构建时间

HardSourceWebpackPlugin 是一个 webpack 插件,它提供了中间缓存的功能,可以在多次构建之间存储文件系统中的模块缓存,从而加速二次及后续的构建过程。它可以减少重新编译的时间,特别是对于大型项目和频繁构建的场景,效果更加显著。

1
2
3
4
5
6
7
8
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');

module.exports = {
// 其他配置...
plugins: [
new HardSourceWebpackPlugin()
]
};

在这个配置中,我们简单地将 HardSourceWebpackPlugin 实例添加到了 webpack 配置的插件列表中。这样,在每次构建过程中,HardSourceWebpackPlugin 会检查文件系统中是否存在缓存,如果存在缓存则直接使用,否则会重新构建模块并将结果存储到缓存中。

DllPlugin和DLLReferencePlugin实现拆分bundles

DllPlugin 和 DllReferencePlugin 是 webpack 提供的两个插件,用于实现拆分 bundles,将不会频繁更新的第三方库(如 React、React-DOM 等)单独打包。

  • DllPlugin:
    • DllPlugin 用于将第三方库打包成一个单独的动态链接库(DLL)。
    • 在 webpack 配置中,首先配置 DllPlugin,将第三方库打包成一个独立的 bundle 文件。
    • 这个 bundle 文件中包含了第三方库的代码,以及一个用于映射模块路径的 JSON 文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// webpack.config.dll.js

const path = require('path');
const webpack = require('webpack');

module.exports = {
mode: 'production',
entry: {
vendor: ['react', 'react-dom']
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].dll.js',
library: '[name]'
},
plugins: [
new webpack.DllPlugin({
name: '[name]',
path: path.resolve(__dirname, 'dist/[name].manifest.json')
})
]
};
  • DllReferencePlugin:
    • DllReferencePlugin 用于在 webpack 配置中引用之前打包好的 DLL 文件。
    • 在主项目的 webpack 配置中,配置 DllReferencePlugin,告诉 webpack 去引用之前打包好的 DLL 文件。
    • 这样就可以将第三方库的代码与自定义代码分开打包,提高构建效率。
1
2
3
4
5
6
7
8
9
10
11
12
13
// webpack.config.js

const path = require('path');
const webpack = require('webpack');

module.exports = {
// 其他配置...
plugins: [
new webpack.DllReferencePlugin({
manifest: require('./dist/vendor.manifest.json')
})
]
};

通过使用 DllPlugin 和 DllReferencePlugin,可以将不会频繁更新的第三方库单独打包成一个 DLL 文件,以提高构建效率。这对于大型项目和频繁构建的场景特别有用,因为第三方库往往是稳定的,不需要每次都重新打包。

使用optimization.splitChunks抽离公共代码

在webpack中,可以使用optimization.splitChunks来抽离公共代码。这个配置项可以帮助你配置webpack如何分割代码块并抽离出重复的模块,以便在多个bundle之间共享这些模块。以下是一个简单的示例webpack配置,演示了如何使用optimization.splitChunks:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const path = require('path');

module.exports = {
entry: {
main: './src/index.js',
vendor: './src/vendor.js' // 假设这是包含第三方库的入口文件
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
optimization: {
splitChunks: {
cacheGroups: {
commons: {
name: 'commons',
chunks: 'initial',
minChunks: 2 // 重复模块最少被引用的次数
},
vendor: {
test: /node_modules/,
name: 'vendor',
chunks: 'initial',
enforce: true
}
}
}
}
};

在这个示例中,optimization.splitChunks配置了两个缓存组(cacheGroups)。第一个缓存组是commons,用于抽离重复引用的模块,minChunks选项指定了重复模块最少被引用的次数。第二个缓存组是vendor,它匹配所有来自node_modules文件夹的模块,并将它们打包到名为vendor的bundle中。

二、扩展知识

happypack 和 thread-loader 有什么区别

  • 工作原理:

    • HappyPack:通过将任务分发到多个子进程来并行处理webpack的构建任务,例如加载和转译模块。每个子进程都有自己的独立的Node.js实例,可以充分利用多核处理器的性能。
    • thread-loader:与webpack的loader阶段集成,它将每个文件的处理任务分配给Worker池中的线程。每个线程都是共享的,可以在多个loader之间重用,以减少线程的创建和销毁开销。
  • 配置方式:

    • HappyPack:需要在webpack配置中添加HappyPack插件,并为每个需要并行处理的loader创建一个HappyPack实例。配置相对独立于webpack的loader配置。
    • thread-loader:作为webpack loader的一个包装器,通过将thread-loader添加到loader链中,从而在loader配置中直接使用。它是一种更轻量级的解决方案,不需要额外的插件。
  • 使用场景:

    • HappyPack:适用于项目中存在大量的耗时loader任务,特别是对于大型项目或者有大量JavaScript文件的项目。
    • thread-loader:更适合于小型到中型项目,或者是想要快速简单地提高构建速度的项目,因为它不需要引入额外的插件和配置。
  • 社区支持和维护:

    • HappyPack:在一定时间内受到了较好的社区支持和维护,但是自2019年起项目进入了维护模式,更新不如之前频繁。
    • thread-loader:目前仍然在积极维护和更新中,并且得到了webpack社区的广泛认可和采用。

cache-loader 和 HardSourceWebpackPlugin 有什么区别

  • 工作原理:

    • HardSourceWebpackPlugin:它通过将模块缓存到硬盘上,来加速webpack的构建速度。在webpack重新构建时,它会尝试重用已经缓存的模块,避免重新解析和编译,从而提高构建效率。
    • cache-loader:它是一个webpack loader,用于缓存loader的执行结果,以避免重复执行同样的loader。它将中间结果缓存到内存或者硬盘中,从而在后续构建中可以直接使用缓存结果,而不需要重新执行loader。
  • 缓存策略:

    • HardSourceWebpackPlugin:它的缓存策略更为全面,可以缓存模块的解析、转换、编译等过程,并且支持跨webpack实例共享缓存。
    • cache-loader:主要用于缓存单个loader的执行结果,通常用于缓存比较耗时的loader,例如babel-loader或者ts-loader。
  • 配置方式:

    • HardSourceWebpackPlugin:作为一个webpack插件,需要在webpack配置中添加相应的插件实例,并进行相应的配置。
    • cache-loader:作为一个普通的webpack loader,只需在webpack配置中将其添加到loader链中即可。
  • 适用场景:

    • HardSourceWebpackPlugin:适用于大型项目或者需要频繁构建的项目,尤其是在缓存大量的中间结果可以提高构建效率的情况下。
    • cache-loader:主要适用于缓存比较耗时的loader任务,可以针对性地优化某些loader的性能。
  • 支持情况:

    • HardSourceWebpackPlugin:虽然在一定程度上可以提高构建性能,但在某些情况下可能会遇到一些兼容性或者稳定性问题。
    • cache-loader:作为一个轻量级的解决方案,通常情况下稳定性较好,且易于集成到现有的webpack配置中。

喜欢这篇文章?打赏一下支持一下作者吧!
【webpack】如何优化webpack配置
https://www.cccccl.com/20231106/webpack/如何优化webpack配置/
作者
Jeffrey
发布于
2023年11月6日
许可协议