编写 webpack loader
webpack loader 是什么
loader就是一个函数,用于编译源代码内部不同类型的模块,同时输出编译后的代码,用来拓展 webpack 的解析能力。
为什么需要 loader
本身 webpack 只能处理.js,·.json文件,对于其他类型的模块代码,webpack 需要借助loader来处理源码,可以把loader直接理解为编译器,因为它主要负责将 webpack 输入的模块代码转换成另一种形式的代码输出。
loader 运行模式
loader接收以下三个参数:
content:源代码map:可以被 https://github.com/mozilla/source-map 使用的 SourceMap 数据meta:meta 数据,可以是任何内容
loader可以直接返回处理后的代码,表示该loader是以同步模式运行的
module.exports = function(content, map, meta) {
let result = '';
// 一些处理
return result;
};
当loader内部具有异步处理时,需要对结果使用callback函数进行包装,callback依次接收四个参数:
error:第一个参数是错误信息Error或者nullresult:第二个参数则是处理过后的代码source map:第三个参数是 source mapmeta:第四个参数,会被 webpack 忽略,可以是任何类型的参数
module.exports = function(content, map, meta) {
// 获取 callback 函数
var callback = this.async();
someAsyncOperation(content, function(err, result) {
if (err) {
return callback(err);
}
callback(null, result, map, meta);
});
};
loader 的链式调用
module.rules.use这个数组传递的多个loader按照数组索引的顺序从后往前执行,第一个执行的loader会获取模块源代码作为参数,然后其执行结果会传递给下一个执行的loader,最后一个loader执行期望返回JS代码和sourcemap;比较常见的就是less的处理流程
module: {
rules: [
test: /\.less$/,
use: [
"style-loader",
"css-loader",
"less-loader"
]
]
}
辅助工具
loader-utils
常用于获取在webpack配置项中传递给loader的参数配置,返回的参数配置项是一个只读的对象
// 在loader内部使用
const loaderUtils = require('loader-utils');
const options = loaderUtils.getOptions(this);
// 通过queryString指定的配置项,例如loader?some¶ms
const params = loaderUtils.parseQuery(this.resourceQuery);
schema-utils
schema-utils可以对loader获取的配置参数进行校验,从schema-utils中获取的validate方法接收三个参数:
schema:用于定义options配置项的类型和校验不通过时的描述,也就是校验规则options:即外部传递进来的配置项configuration:最后一个参数用于补充对于schema的描述信息
import { getOptions } from 'loader-utils';
import { validate } from 'schema-utils';
// 校验规则
const schema = {
type: 'object',
properties: {
name: {
type: 'string',
},
query: {
type: 'number',
},
},
additionalProperties: false,
};
function loader(src, map) {
const options = getOptions(this);
validate(schema, options, {
name: 'Loader Name',
baseDataPath: 'options',
});
// Code...
return `function() {xxx}`;
}
export default loader;
编写 loader 的注意事项
- 功能单一原则:一个
loader应该只处理一种类型的源代码 - 禁止写绝对路径