2.Webpack:loader 和 plugin

# 2.Webpack:loader 和 plugin

# 什么是 loader

  • loader 用于对模块的源代码进行转换,在 import 或"加载"模块时预处理文件
  • 因为 webpack 只认识 js,所以需要 loader 对其他文件进行预处理
  • 比如将 css 文件中的
.a font-size 20px;
1

转为

document.getElementById("style").innerHTML = ".a { font-size: 20px }";
1

# 什么是 plugin

  • plugin赋予 webpack 各种灵活的功能,例如打包优化、资源管理、环境变量注入等,它们会运行在 webpack 的不同阶段(钩子 / 生命周期),贯穿了webpack整个编译周期

图片

# 常见的 loader 和 plugin

在页面开发过程中,我们经常性加载除了js文件以外的内容,这时候我们就需要配置响应的loader进行加载

常见的loader如下:

  • style-loader: 将 css 添加到 DOM 的内联样式标签 style 里
  • css-loader :允许将 css 文件通过 require 的方式引入,并返回 css 代码
  • less-loader: 处理 less
  • postcss-loader: 用 postcss 来处理 CSS,处理 CSS3 属性前缀,
  • file-loader: 分发文件到 output 目录并返回相对路径
  • url-loader: 和 file-loader 类似,但是当文件小于设定的 limit 时可以返回一个 Data Url
  • html-minify-loader: 压缩 HTML
  • babel-loader :用 babel 来转换 ES6 文件到 ES
  • i18n-loader: 国际化
  • cache-loader: 可以在一些性能开销较大的 Loader 之前添加,目的是将结果缓存到磁盘里

常见的 plugin:

  • define-plugin:定义环境变量
  • webpack-bundle-analyzer: 可视化 Webpack 输出文件的体积 (业务组件、依赖第三方模块)
  • mini-css-extract-plugin: 分离样式文件,CSS 提取为独立文件,支持按需加载 (替代 extract-text-webpack-plugin)
  • webpack-dashboard:可以更友好的展示相关打包信息。
  • webpack-merge:提取公共配置,减少重复配置代码
  • speed-measure-webpack-plugin:简称 SMP,分析出 Webpack 打包过程中 Loader 和 Plugin 的耗时,有助于找到构建过程中的性能瓶颈。
  • size-plugin:监控资源体积变化,尽早发现问题
  • HotModuleReplacementPlugin:模块热替换
  • 目的在于解决loader 无法实现的其他事

# Loader 和 Plugin 的区别

  • Loader 本质就是一个函数,在该函数中对接收到的内容进行转换,返回转换后的结果。 因为 Webpack 只认识 JavaScript,所以 Loader 就成了翻译官。
    • 对于loader,实质是一个转换器,将 A 文件进行编译形成 B 文件,操作的是文件,比如将A.scss或A.less转变为B.css,单纯的文件转换过程
  • 在Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过Webpack提供的 API改变输出结果

# 自定义 loader

# 同步 loader

function test1(content, sourceMap, meta) {
  // 1.
  // return content
  // 2.error, content, SourceMap, 是否是AST语法树
  // this.callback(null,content,sourceMap,abstractSyntaxTree)
  // return
}
1
2
3
4
5
6
7

# 异步 loader

module.exports = function (source) {
  // 调用 this.async() API,告诉 webpack本次转换是异步的,loader 会在 callback 中返回结果
  const callback = this.async();
  // 使用 setTimeout 模拟异步过程
  setTimeout(() => {
    const content = source.replace("hello", "哈哈");
    // 通过 callback 返回执行异步后的结果
    callback(null, content);
  }, 3000);
};
1
2
3
4
5
6
7
8
9
10

# 实战自定义 loader

  1. mini 版 style-loader
module.exports = function (source) {
  return `const styleTag = document.createElement('style');
        styleTag.innerHTML = ${source};
        document.head.appendChild(styleTag);
    `;
};
1
2
3
4
5
6
  1. mini 版 css-loader
module.exports = function (source) {
  return JSON.stringify(source);
};
1
2
3

# 自定义 plugin

# plugin 能做,loader 不能做的事情

  1. 代码压缩、文件拆分、Tree Shaking、清理旧文件、生成统计报告、

# loader 能做,plugin 不能做的事情

# babel-loader:ES6 转 ES5

这是一个文件级别的操作,需要在每个.js 文件被加载时进行。Plugin 在这种情况下无法工作,因为它们操作的是整个编译过程,而不是单个文件。

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env"],
          },
        },
      },
    ],
  },
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# plugin 和 loader 都能做的事情

# 执行顺序

  • loader:从右到左,从下到上,先于 plugin 执行
  • plugin:在 loader 之后,并且是事件驱动的
Last Updated: 9/25/2026, 2:08:32 PM