loader 本质上是导出为函数的 JavaScript 模块。当webpack解析资源时,会调用相应的 loader 去处理,然后将上一个 loader 产生的结果或者资源文件传入进去。loader 有三个入参:资源文件的内容(content)、可以被 Source Map 使用的 SourceMap 数据(map)、数据,可以是任何内容(meta)。
loader 有同步 Loaders、异步 Loaders 、Raw Loader 、Pitching Loader ,更详细的可以参考 Loader Interface。
下面写一个去除 console.log 的 loader
例如,假设你想创建一个 Loader,去除每个 JavaScript 文件的中的 console.log ,Loader 所示如下:
同步 loader 有两种写法,如果有多个处理结果,则必须调用 this.callback()
,当调用 callback() 函数时,总是返回 undefined,代码如下:
module.exports = function (content, map, meta) {
this.callback(null, someSyncOperation(content), map, meta);
return;
};
function someSyncOperation(content) {
return content.replace(/console\.log\(.*\);?/g, "");
}
如果只有一个处理结果,可以调用 this.callback()
,也可以不用,代码如下:
module.exports = function (content, map, meta) {
return content.replace(/console\.log\(.*\);?/g, "");
};
在 webpack.prod.js 中使用
{
test: /\.jsx?$/,
include: [path.resolve(__dirname, "../src")],
use: [
{
loader: "./loaders/clean-log-loader",
},
],
},
对于异步 loader,使用 this.async 来获取 callback 函数。
module.exports = function(source) {
const callback = this.async();
// 在 `setTimeout` 等异步方法中完成处理,然后通过回调函数将结果返回给 Webpack
setTimeout(() => {
callback(null, someSyncOperation(content), map, meta);
}, 1000);
};
function someSyncOperation(content) {
return content.replace(/console\.log\(.*\);?/g, "");
}
在 webpack.prod.js 中使用与同步一样。
默认情况下,资源文件会被转化为 UTF-8 字符串,然后传给 loader。通过设置 raw 为 true ,loader 可以接收原始的 Buffer 。大多数情况下都是图片或字体使用 Raw Loader,毕竟js还是想看具体内容的, 添加 module.exports.raw = true 就可以了。
module.exports = function (content, map, meta) {
return content.replace(/console\.log\(.*\);?/g, "");
};
module.exports.raw = true;
在文件中导出一个函数并添加 pitch 属性,该函数在模块被处理之前执行。 pitch 函数的输入是请求的数据,包括请求的路径、请求的上下文以及使用的其它 Loader。
module.exports = function (content, map, meta) {
return content.replace(/console\.log\(.*\);?/g, "");
};
module.exports.pitch = function(request) {
// pitch函数在模块被处理之前执行
// request 参数包括请求的路径,请求的上下文和使用的其它 Loader
};
对于以下配置,执行顺序
module.exports = {
//...
module: {
rules: [
{
//...
use: ['a-loader', 'b-loader', 'c-loader'],
},
],
},
};
纯属个人总结,不喜勿喷。