文章目录
一 关于loader
1、理解
loader其实就是一个函数,它可以通过接受一些参数,处理特定文件后暴露出去
module.exports = function loader1(content) {
console.log("hello loader");
return content;
};
接收的参数
content 源文件的内容
map SourceMap 数据
meta 数据,可以是任何内容
2、分类
1、同步loader
module.exports = function (content, map, meta) {
// 传递map,让source-map不中断
// 传递meta,让下一个loader接收到其他参数
this.callback(null, content, map, meta);
return; // 当调用 callback() 函数时,总是返回 undefined
};
2、异步loader
module.exports = function (content, map, meta) {
const callback = this.async();
// 进行异步操作
setTimeout(() => {
callback(null, result, map, meta);
}, 1000);
};
3、raw loader
默认情况下,资源文件会被转化为 UTF-8 字符串,然后传给 loader。 通过设置 raw 为 true,loader 可以接收原始的 Buffer。
module.exports = function (content) {
// content是一个Buffer数据
return content;
};
module.exports.raw = true; // 开启 Raw Loader
4、pitch loader
webpack 会先从左到右执行 loader 链中的每个 loader 上的 pitch 方法(如果有),然后再从右到左执行 loader 链中的每个 loader 上的普通 loader 方法。
在这个过程中如果任何 pitch 有返回值,则 loader 链被阻断。webpack 会跳过后面所有的的 pitch 和 loader,直接进入上一个 loader 。
module.exports = function (content) {
return content;
};
module.exports.pitch = function (remainingRequest, precedingRequest, data) {
console.log("do somethings");
};
更多loaderAPI参考:webpack官方文档
二、自己实现一些loader
一、clean-log-loader
用于生产环境构建项目去除代码中的console.log()
module.exports = function(content) {
return content.replace(/console\.log\(.*\);?/g, "")
}
二、babel-loader
需要借助babel的一些预设和工具,参考babel官网
js
const babel = require("@babel/core")
const schema = require("./schema.json")
module.exports = function(content) {
const options = this.getOptions(schema);
// 使用异步loader
const callback = this.async();
// 使用babel对js代码进行编译
babel.transform(content, options, function(err, result) {
callback(err, result.code);
});
}
schema标准
{
"type": "object",
"properties": {
"presets": {
"type": "array"
}
},
"additionalProperties": true
}
三、style-loader
js
const styleLoader = () => {}
/**
* 因为直接在style-loader里面接收到的是css-loader传递过来的内容,是一段js代码
* 而我们需要的是css-loader那一段js代码执行完成之后暴露出来的样式文件,所以这里使用pitch
* @param {*} remainingRequest
* @returns
*/
styleLoader.pitch = function(remainingRequest) {
// 获得css-loader处理结果的路径
/*
* remainingRequest是一个绝对路径,需要转换为相对于当前上下文的相对路径
*/
/**
* remainingRequest:
* F:\webpack-loader\webpack-loader-1\node_modules\css-loader\dist\cjs.js!F:\webpack-loader\webpack-loader-1\src\styles\index.css
*
* relativeRequest:
* ../../node_modules/css-loader/dist/cjs.js!./index.css
*/
const relativeRequest =
remainingRequest
.split('!')
.map((part) => this.utils.contextify(this.context, part))
.join('!');
/**
* 创建script语句并暴露出去,提供给构建工具,在打包时执行
*/
const scripts = `
import style from "!!${relativeRequest}"
const styleEl = document.createElement('style')
styleEl.innerHTML = style
document.head.appendChild(styleEl)
`;
// style-loader是第一个loader, 由于return导致熔断,所以其他loader不执行了(不管是normal还是pitch)
return scripts;
}
module.exports = styleLoader