Skip to content

什么是Loader 官方文档

Loader的本质就是一个导出的函数模块,Webpack内部的Loader runner会遍历所有Loader,并调用每个Loader的函数。Loader函数中的this会被Webpack通过call的方式填充

Loader示例

js
/**
 *
 * @param {string|Buffer} content 源文件的内容
 * @param {object} [map] 可以被 https://github.com/mozilla/source-map 使用的 SourceMap 数据
 * @param {any} [meta] meta 数据,可以是任何内容
 */
function webpackLoader(content, map, meta) {
  // 你的 webpack loader 代码
}

Loader的分类

  • pre 前置Loader
  • normal 普通Loader
  • inline 行内Loader
  • post 后置Loader

其中 pre 和 post loader可以通过对rules进行配置,而 normal 和 inline loader只能通过使用loader属性进行配置,在rule中配置enfrce字段可以制定loader种类.

Loader的执行顺序

所有一个接一个地进入的 loader,都有两个阶段:

Pitching 阶段: loader 上的 pitch 方法,按照 后置(post)、行内(inline)、普通(normal)、前置(pre) 的顺序调用。更多详细信息,请查看 Pitching Loader。

Normal 阶段: loader 上的 常规方法,按照 前置(pre)、普通(normal)、行内(inline)、后置(post) 的顺序调用。模块源码的转换, 发生在这个阶段。

所有普通 loader 可以通过在请求中加上 ! 前缀来忽略(覆盖)。

所有普通和前置 loader 可以通过在请求中加上 -! 前缀来忽略(覆盖)。

所有普通,后置和前置 loader 可以通过在请求中加上 !! 前缀来忽略(覆盖)。

js
// 禁用普通 loaders
import { a } from '!./file1.js';

// 禁用前置和普通 loaders
import { b } from '-!./file2.js';

// 禁用所有的 laoders
import { c } from '!!./file3.js';

不应使用内联 loader 和 ! 前缀,因为它是非标准的。它们可能会被 loader 生成代码使用。

同步Loader

无论是 return 还是 this.callback 都可以同步地返回转换后的 content 值:

js
module.exports = function (content, map, meta) {
  return someSyncOperation(content);
};

this.callback 方法则更灵活,因为它允许传递多个参数,而不仅仅是 content。

js
module.exports = function (content, map, meta) {
  this.callback(null, someSyncOperation(content), map, meta);
  return; // 当调用 callback() 函数时,总是返回 undefined
};

异步Loader

对于异步 loader,使用 this.async 来获取 callback 函数:

js
module.exports = function (content, map, meta) {
  const callback = this.async();
  someAsyncOperation(content, function (err, result, sourceMaps, meta) {
    callback(err, result, sourceMaps, meta);
  })
}