1. Loader API

所谓 loader 只是导出一个函数的 JavaScript 模块。loader runner会调用这个函数,然后把上一个 loader 产生的结果或者资源文件(resource file)传入进去。函数的this上下文将由 webpack 填充,并且loader runner带有一些有用方法,可以使 loader 改变为异步调用方式,或者获取 query 参数。

第一个 loader 的传入参数只有一个:资源文件(resource file)的内容。编译器需要得到最后一个 loader 产生的处理结果。这个处理结果应该是String或者Buffer(被转换为一个 string),代表了模块的 JavaScript 源码。另外还可以传递一个可选的 SourceMap 结果(格式为 JSON 对象)。

如果是单个处理结果,可以在同步模式中直接返回。如果有多个处理结果,则需要调用this.callback()。在异步模式中,必须调用this.async(),来指示loader runner等待异步结果,它会返回this.callback()回调函数,随后 loader 必须返回undefined并且调用该回调函数。

1.1. 示例

1.1.1. 同步 loader

sync-loader.js

module.exports = function(content) {
  return someSyncOperation(content);
};

sync-loader-with-multiple-results.js

module.exports = function(content) {
  this.callback(null, someSyncOperation(content), sourceMaps, ast);
  return; // 当调用callback()时总是返回undefined
};

1.1.2. 异步 loader

async-loader.js

module.exports = function(content) {
    var callback = this.async();
    someAsyncOperation(content, function(err, result) {
        if(err) return callback(err);
        callback(null, result);
    });
};

async-loader-with-multiple-results.js

module.exports = function(content) {
    var callback = this.async();
    someAsyncOperation(content, function(err, result, sourceMaps, ast) {
        if(err) return callback(err);
        callback(null, result, sourceMaps, ast);
    });
};

[info] 注:

loader 最初被设计为可以在同步 loader pipeline(如 Node.js ,使用enhanced-require),与异步 pipeline(如 webpack )中运行。然而在 Node.js 这样的单线程环境下进行耗时长的同步计算不是个好主意,我们建议尽可能地使您的 loader 异步化。但如果计算量很小,同步 loader 也是可以的。

1.1.3. "Raw" loader

默认情况下,资源文件会被转化为 UTF-8 字符串,然后传给 loader。通过设置raw,loader 可以接收原始的Buffer。每一个 loader 都可以用String或者Buffer的形式传递它的处理结果。编译器将会把它们在 loader 之间相互转换。

raw-loader.js

module.exports = function(content) {
    assert(content instanceof Buffer);
    return someSyncOperation(content);
    // 返回值也可以是一个 `Buffer`
    // 即使不是 raw loader 也没问题
};
module.exports.raw = true;

1.1.4. Pitching loader

loader总是从右到左地被调用,但是在一些情况下,loader 不需要关心之前处理的结果或者资源(resource),而是只关心元数据(metadata)。在 loader 被调用前(从右到左),loader 中的pitch方法会从左到右依次被调用。

如果中间某个 loader 的pitch方法返回了一个值,那么剩下的 loader 都会被跳过,转而从当前 loader 开始向左调用 loader。data可以在 pitch 和普通的 loader 调用间传递。

module.exports = function(content) {
    return someSyncOperation(content, this.data.value);
};
module.exports.pitch = function(remainingRequest, precedingRequest, data) {
    if(someCondition()) {
        // 直接返回
        return "module.exports = require(" + JSON.stringify("-!" + remainingRequest) + ");";
    }
    data.value = 42;
};

1.2. The loader context

loader context 表示在 loader 内使用this可以访问的一些方法或属性

假设我们在/abc/file.js中这样请求加载别的模块:

require("./loader1?xyz!loader2!./resource?rrr");

1.2.1. this.version

loader API 的版本号。目前是2。这对于向后兼容性有一些用处。通过这个版本号,你可以为不同版本间的破坏性变更编写不同的逻辑,或做降级处理。

1.2.2. this.context

模块所在的目录。某些场景下这可能会有用处。

在我们的例子中:这个属性为/abc,因为resource.js在这个目录中

1.2.3. this.request

被解析出来的请求字符串。

在我们的例子中:"/abc/loader1.js?xyz!/abc/node_modules/loader2/index.js!/abc/resource.js?rrr"

1.2.4. this.query

  1. 如果这个 loader 配置了options对象的话,this.query就指向这个 option 对象。
  2. 如果 loader 中没有options,而是以 query 字符串作为参数调用时,this.query就是一个以?开头的字符串。

[warning] 注: options已取代query,所以此属性废弃。使用loader-utils中的getOptions方法来提取给定 loader 的 option。

Copyright © tuzhu008 2017 all right reserved,powered by Gitbook该文件修订时间: 2017-11-20 20:43:35

results matching ""

    No results matching ""