核心工作流程

Webpack 作为一个强大的模块打包工具,其核心工作流程可以看作是一部精心编排的交响乐,而 Loader 和 Plugin则是其中的两大核心乐器。

整个流程始于一个或多个入口(Entry)文件。Webpack从入口出发,递归地解析代码中的 importrequire 语句,构建出一张包含所有模块及其相互关系的依赖图(Dependency Graph)。

loader

在这个构建依赖图的过程中,Loader 扮演了翻译官的角色。Webpack 原生只理解 JavaScriptJSON 文件。当它遇到如.scss、.tsx、.png 等非 JavaScript 类型的文件时,就会查找匹配的 LoaderLoader 的职责就是将这些文件转换成 Webpack 能够理解和处理的有效模块。例如,babel-loaderES6+ 语法转译为 ES5css-loader 解析 CSS 文件。Loader 的作用域是单个文件,它在模块加载的环节执行。

plugin

当所有模块都被 Loader 成功“翻译”后,Plugin 便登上了舞台。Plugin 是架构师,它不直接操作单个文件,而是深入到 Webpack 编译的整个生命周期中。通过监听 Webpack广播出的事件钩子,Plugin 可以在打包过程的特定时刻执行广泛的任务,从而实现对打包结果的自定义和优化。比如,Htmlwebpackplugin 可以在打包结束后自动生成个 HTML 文件并注入打包好的脚本, TerserwebpackPlugin 则负责在最终输出前对代码进行压缩。

简而言之,Loader 负责内容的转换,Plugin 负责流程的扩展。前者是输入到输出的管道,后者是整个构建过程的控制器。

如何提升 webpack 的构造性能

1. speed-measure-webpack-plugin

优化你的 webpack 构建速度的第一步是要知道你应该把注意力集中在哪里,在这里推荐一个插件:speed-measure-webpack-plugin,这个插件可以测量你的 webpack 构建速度。

install

1
npm install --save-dev speed-measure-webpack-plugin

or

1
yarn add -D speed-measure-webpack-plugin

用法

1
2
3
const webpackConfig = {
plugins: [new MyPlugin(), new MyOtherPlugin()],
};

to

1
2
3
4
5
6
7
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");

const smp = new SpeedMeasurePlugin();

const webpackConfig = smp.wrap({
plugins: [new MyPlugin(), new MyOtherPlugin()],
});

2. 更快的 loader:swc

在 webpack 中耗时最久的当属负责 AST 转换的 loader。我们可以使用速度更快的swc

1
2
3
4
5
6
7
8
9
10
11
12
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
// Use `.swcrc` to configure swc
loader: "swc-loader",
},
},
];
}
如何配置 swc

SWC can be configured with an .swcrc file.

this is Compilation

如果你是使用的 babel,swc 官方网站拥有提供从 babel 迁移到 swc 的指南

3. 持久化缓存:cache

webpack5 内置了关于缓存的插件,可以通过配置来开启,它将ModuleChunkModuleChunk等信息序列化到磁盘中,二次构建避免重复编译计算,编译速度得到很大的提升

1
2
3
4
5
{
cache: {
type: "filesystem";
}
}

当开启了持久化缓存功能,最耗时的 AST 解析将能够从磁盘的缓存中获取,再次编译时无需再次进行解析 AST。