webpack基础进阶和原理剖析

webpack 官方中文文档

webpack 配置中的 loader 和 plugin 的区别

在 Webpack 中,loaderplugin 是实现构建能力的核心机制,但它们的作用和工作方式有本质区别:

一、Loader(加载器):处理非 JS 模块的“翻译官”

Webpack 本质上只能识别 JavaScript 和 JSON 文件,**loader 的核心作用是将非 JS 模块(如 CSS、图片、TS 等)转换为 Webpack 可处理的模块
**,从而纳入构建流程。

1. 工作原理

  • 执行时机:在 Webpack 解析代码的过程中(模块打包阶段),当遇到非 JS 模块时触发。
  • 执行顺序:从右到左(或从下到上)链式调用。例如:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 先执行 sass-loader 处理 SASS,再用 css-loader 处理 CSS,最后用 style-loader 注入到 DOM
    module: {
    rules: [
    {
    test: /\.s[ac]ss$/i,
    use: ["style-loader", "css-loader", "sass-loader"],
    },
    ];
    }
  • 输入输出:接收源文件内容作为参数,返回处理后的内容(通常是 JS 代码)。

2. 常见场景

  • 语言转换babel-loader 将 ES6+ 转换为 ES5;ts-loader 将 TypeScript 转换为 JS。
  • 样式处理css-loader 解析 CSS 中的 @importurl()style-loader 将 CSS 注入到页面 <style> 标签;
    sass-loader 编译 SASS/SCSS 为 CSS。
  • 资源处理file-loader 处理图片、字体等资源并输出到指定目录;url-loader 在文件体积较小时将资源转为 Base64 嵌入代码。

二、Plugin(插件):扩展构建流程的“功能增强器”

Plugin 用于扩展 Webpack 的功能,可以介入构建的整个生命周期(从初始化到输出产物),实现 loader
无法完成的复杂操作(如打包优化、环境变量注入、资源管理等)。

1. 工作原理

  • 基于钩子机制:Webpack 在构建过程中会触发一系列生命周期钩子(如 entryOptioncompileemit 等),plugin
    通过注册这些钩子,在特定时机执行自定义逻辑。
  • 灵活性高:可以修改输出资源、调整构建流程、生成额外文件等。

2. 常见场景

  • 优化输出TerserPlugin 压缩 JS 代码;MiniCssExtractPlugin 将 CSS 提取为单独文件(替代 style-loader)。
  • 环境配置DefinePlugin 注入全局环境变量(如 process.env.NODE_ENV)。
  • 性能分析BundleAnalyzerPlugin 可视化打包产物,分析体积过大的原因。
  • 资源处理CopyWebpackPlugin 复制静态资源到输出目录;HtmlWebpackPlugin 自动生成 HTML 并引入打包后的资源。

三、核心区别

维度 Loader Plugin
作用对象 针对模块文件(如 CSS、TS) 针对整个构建流程
功能范围 仅处理文件转换(输入 → 输出内容) 可扩展任意构建功能(优化、注入、生成等)
用法 module.rules 中配置 plugins 数组中实例化
执行时机 模块解析阶段 整个生命周期(从初始化到输出)

常用的 plugin

插件名称 主要作用 适用场景
‌HtmlWebpackPlugin‌ 自动生成 HTML 文件,并自动注入打包后的 JS/CSS 链接 解决手动修改 HTML 中 script src 路径的问题
‌CleanWebpackPlugin‌ 在每次构建前清空输出目录(如 dist/) 避免旧版本文件残留导致混淆
‌MiniCssExtractPlugin‌ 将 CSS 从 JS bundle 中抽离为独立的 .css 文件 生产环境优化,利用浏览器并行加载 CSS
‌DefinePlugin‌ 定义编译时的全局常量(如 process.env.NODE_ENV)区分环境 开发/生产环境代码逻辑分支判断
‌CompressionWebpackPlugin‌ 生成资源的压缩版本(如 .js.gz) 配合服务器 Content-Encoding 提升加载速度
‌HotModuleReplacementPlugin‌ 启用模块热替换(HMR) 开发阶段无需刷新页面即可更新模块

四、总结

  • Loader 解决“Webpack 不能识别非 JS 模块”的问题,专注于文件内容的转换。
  • Plugin 解决“扩展 Webpack 功能”的问题,通过钩子机制介入构建全流程,实现更复杂的需求。

两者相辅相成:Loader 负责“翻译”各类资源,Plugin 负责“增强”构建过程,共同构成了 Webpack 灵活强大的构建能力。

自定义 loader

写一个 uppercase-loader,实现将文件内容转换为大写

loader 本质是函数,做编译的增强

1
2
3
4
// /loaders/uppercase-loader.js
export default function uppercaseLoader(source) {
return source.toUpperCase();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// webpack.config.dev.js
export default {
output: {
path: path.resolve(__dirname, "dist"),
filename: "main.js",
},
entry: "./src/index.js",
module: {
rules: [
{
test: /\.js$/,
use: ["./loaders/uppercase-loader.js"],
},
],
},
};

自定义 plugin

Plugin 的本质就是一个拥有 apply 方法的类(或对象),做构建的增强

核心概念

  1. Compiler 对象 ‌:代表 Webpack 完整的配置环境,只在启动时创建一次。它包含了所有配置选项、Loader、Plugin 等信息。
  2. Compilation 对象 ‌:代表一次具体的构建过程。当文件发生变化触发重新编译时,会创建新的 Compilation 对象 it 包含当前编译的模块、chunk、资源等状态。
  3. Hooks(钩子)‌:Webpack 在构建生命周期的不同阶段广播事件。Plugin 通过监听这些钩子,在特定时刻执行逻辑。

常用生命周期钩子

  1. compile: 编译开始时触发。
  2. make: 开始构建模块依赖图。
  3. emit: 生成资源到输出目录之前触发(此时可以修改最终输出的内容)。
  4. afterEmit: 资源输出完成后触发。
  5. done: 编译完成时触发。
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
// 产物统计
// /plugins/AssetsMapPlugin.js

export default class AssetsMapPlugin {
constructor(options) {}
apply(compiler) {
// compiler 是 webpack 实例,通过 compiler 可以访问到 webpack 所有的配置和插件
compiler.hooks.initialize.tap("AssetsMapPlugin", (compilation) => {
// compilation 是当前打包的上下文,通过 compilation 可以访问到当前打包的所有资源
console.log(compilation.assets);
});
compiler.hooks.run.tapAsync("AssetsMapPlugin", (compilation, next) => {
// compilation 是当前打包的上下文,通过 compilation 可以访问到当前打包的所有资源
console.log(compilation.assets);
let fileList = "";
for (const fileName in compilation.assets) {
fileList += fileName + "\n";
}
compilation.assets["file-list.md"] = {
source: () => fileList,
size: () => fileList.length,
};
next(); // 必须调用 next 才能继续打包,权限交给下一个插件
});
}
}
1
2
3
4
5
// webpack.config.dev.js

export default {
plugins: [new AssetsMapPlugin()],
};

会输出一个 file-list.md 文件,内容是当前打包的所有资源文件名

webpack 原理核心

  1. compiler
  2. compilation
  3. module
  4. chunk
  5. dependency
  6. resolver
  7. loader
  8. plugin

webpack基础进阶和原理剖析
https://zouhualu.github.io/20240509/webpack基础进阶和原理剖析/
作者
花鹿
发布于
2024年5月9日
许可协议