背景
上一篇我们实现了 clean-log-loader,它的行为是写死的。但真实场景里,loader 往往需要可配置:注释内容、文件名、是否开启某种转换……这些都依赖 options。
本文以 insert-comment-loader(在 JS 文件开头插入注释)为例,完整讲清 Loader 如何接收、校验和使用 options。
Loader 是怎么拿到 options 的
在 Webpack 配置里,我们这样声明一个带参数的 loader:
{
test: /\.js$/i,
exclude: /node_modules/,
use: [
{
loader: path.resolve(__dirname, 'loaders/insert-comment-loader.js'),
options: {
content: 'Generated by webpack-demo\nDo not edit directly.',
},
},
path.resolve(__dirname, 'loaders/clean-log-loader.js'),
],
}
关键点:options 对象会被 Webpack 注入到 loader 函数的 this 上。Loader 内部通过 this.getOptions() 取回它。
官方推荐:this.getOptions()
Webpack 5 提供了 this.getOptions(schema),一步完成「读取 + 默认值 + 校验」:
const schema = {
type: 'object',
properties: {
content: { type: 'string' },
type: { enum: ['block', 'line'] },
},
additionalProperties: false,
};
module.exports = function insertCommentLoader(source) {
const { content = '', type = 'block' } = this.getOptions(schema) || {};
if (!content) {
return source;
}
const lines = content.split('\n');
if (type === 'line') {
const comment = lines.map((line) => `// ${line}`).join('\n');
return `${comment}\n${source}`;
}
const body = lines.map((line) => ` * ${line}`).join('\n');
const comment = `/**\n${body}\n */`;
return `${comment}\n${source}`;
};
这就是 loaders/insert-comment-loader.js 的完整实现。它有三个设计要点:
content:注释内容,允许多行。type:注释风格,block(/** ... */)或line(// ...),默认block。additionalProperties: false:拒绝任何未声明的字段,防止拼写错误被静默忽略。
schema 校验的价值
如果配置里把 content 写成了数字:
options: { content: 123 }
Webpack 会在构建时直接报错,而不是产出一份奇怪的代码:
Invalid options object. Insert Comment Loader has been initialized using an options object that does not match the API schema.
- options.content should be a string
这就是 schema 的意义:把错误提前到构建期,并给出可读的提示。
如果你还需要更友好的默认值行为,可以给 schema 补充 default:
const schema = {
type: 'object',
properties: {
content: { type: 'string', default: '' },
type: { enum: ['block', 'line'], default: 'block' },
},
additionalProperties: false,
};
此时 this.getOptions(schema) 会自动补全缺省字段,函数里就不必再写 = 'block'。
注意:schema 采用 JSON Schema 规范,
type可以是'boolean'、'number'、'array'、'object'等。
老写法与内联写法
this.query
Webpack 4 及更早版本没有 getOptions,需要自己读 this.query:
module.exports = function (source) {
const options = typeof this.query === 'string'
? JSON.parse(this.query.slice(1))
: this.query;
// ...
};
Webpack 5 仍兼容,但官方已不推荐,建议统一改用 this.getOptions。
内联传参
也可以在 import 语句里临时传 options,loader 之间用 ! 分隔,? 后跟查询串:
import data from '!!./loaders/insert-comment-loader.js?{"content":"inline","type":"line"}!./utils.js';
内联写法适合调试,生产项目仍建议集中写在 webpack.config.js。
小结
- Loader 通过
this.getOptions(schema)获取配置,Webpack 5 推荐用 schema 做校验。 - 合理使用
default和enum,让配置自解释、错误早暴露。 additionalProperties: false能拦住拼写错误。- 记住
use数组右到左执行,options 属于链上的某一段。
掌握了 options,你的 loader 才真正具备复用价值。