创见博客
Webpack Loader 中如何使用 options
七崽爱吃小饼干2026/09/20阅读 0专栏 webpack原理

背景

上一篇我们实现了 clean-log-loader,它的行为是写死的。但真实场景里,loader 往往需要可配置:注释内容、文件名、是否开启某种转换……这些都依赖 options。

本文以 insert-comment-loader(在 JS 文件开头插入注释)为例,完整讲清 Loader 如何接收、校验和使用 options。

Loader 是怎么拿到 options 的

在 Webpack 配置里,我们这样声明一个带参数的 loader:

js
{
  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),一步完成「读取 + 默认值 + 校验」:

js
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 的完整实现。它有三个设计要点:

  1. content:注释内容,允许多行。
  2. type:注释风格,block(/** ... */)或 line(// ...),默认 block。
  3. additionalProperties: false:拒绝任何未声明的字段,防止拼写错误被静默忽略。

schema 校验的价值

如果配置里把 content 写成了数字:

js
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:

js
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:

js
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 之间用 ! 分隔,? 后跟查询串:

js
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 才真正具备复用价值。

评论
0/100