什么是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);
})
}