加载程序 API | Loader API
所谓 loader 只是一个导出为函数的 JavaScript 模块。loader runner 会调用这个函数,然后把上一个 loader 产生的结果或者资源文件(resource file)传入进去。函数的 this
上下文将由 webpack 填充,并且 loader runner 具有一些有用方法,可以使 loader 改变为异步调用方式,或者获取 query 参数。
第一个 loader 的传入参数只有一个:资源文件(resource file)的内容。compiler 需要得到最后一个 loader 产生的处理结果。这个处理结果应该是 String
或者 Buffer
(被转换为一个 string),代表了模块的 JavaScript 源码。另外还可以传递一个可选的 SourceMap 结果(格式为 JSON 对象)。
如果是单个处理结果,可以在同步模式中直接返回。如果有多个处理结果,则必须调用 this.callback()
。在异步模式中,必须调用 this.async()
,来指示 loader runner 等待异步结果,它会返回 this.callback()
回调函数,随后 loader 必须返回 undefined
并且调用该回调函数。
例子
同步加载程序
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; // always return undefined when calling callback()
};
异步加载程序
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);
});
};
T> loader 最初被设计为可以在同步 loader pipeline(如 Node.js ,使用 enhanced-require),与异步 pipeline(如 webpack )中运行。然而在 Node.js 这样的单线程环境下进行耗时长的同步计算不是个好主意,我们建议尽可能地使你的 loader 异步化。但如果计算量很小,同步 loader 也是可以的。
“原始”加载程序
默认情况下,资源文件会被转化为 UTF-8 字符串,然后传给 loader。通过设置 raw
,loader 可以接收原始的 Buffer
。每一个 loader 都可以用 String
或者 Buffer
的形式传递它的处理结果。Complier 将会把它们在 loader 之间相互转换。
raw-loader.js
module.exports = function(content) {
assert(content instanceof Buffer);
return someSyncOperation(content);
// return value can be a `Buffer` too
// This is also allowed if loader is not "raw"
};
module.exports.raw = true;
越过 loader(Pitching loader)
loader 总是__从右到左地被调用。有些情况下,loader 只关心 request 后面的__元数据(metadata),并且忽略前一个 loader 的结果。在实际(从右到左)执行 loader 之前,会先__从左到右__调用 loader 上的 pitch
方法。对于以下 use
配置:
如果加载程序在该pitch
方法中传递结果,则该过程将转向并跳过剩余的加载程序,继续调用更多的左加载程序。data
可以在音调和正常呼叫之间传递。
module.exports = function(content) {
return someSyncOperation(content, this.data.value);
};
module.exports.pitch = function(remainingRequest, precedingRequest, data) {
if(someCondition()) {
// fast exit
return "module.exports = require(" + JSON.stringify("-!" + remainingRequest) + ");";
}
data.value = 42;
};
加载器上下文
加载器上下文表示分配给该this
属性的加载器内可用的属性。
给出以下示例,需要调用:In /abc/file.js
:
require("./loader1?xyz!loader2!./resource?rrr");
this.version
Loader API版本。目前2
。这对提供向后兼容性很有用。使用该版本,您可以指定用于重大更改的自定义逻辑或回退。
this.context
模块的目录。可以用作解决其他问题的上下文。
在这个例子中:/abc
因为resource.js
在这个目录下
this.request
已解析的请求字符串。
在这个例子中: "/abc/loader1.js?xyz!/abc/node_modules/loader2/index.js!/abc/resource.js?rrr"
this.query
1. 如果这个 loader 配置了 options
对象的话,this.query
就指向这个 option 对象。
2. 如果 loader 中没有 options
,而是以 query 字符串作为参数调用时,this.query
就是一个以 ?
开头的字符串。
options
已取代 query
,所以此属性废弃。使用 loader-utils
中的 getOptions
方法来提取给定 loader 的 option。
this.callback
可以同步或异步调用以返回多个结果的函数。预期的参数是:
this.callback(
err: Error | null,
content: string | Buffer,
sourceMap?: SourceMap,
abstractSyntaxTree?: AST
);
- 第一个参数必须是
Error
或null
- 第二个参数a
string
或aBuffer
。
- 可选:第三个参数必须是可由该模块解析的 source map。
- 可选:第四个选项,会被 webpack 忽略,可以是任何东西(例如一些元数据)。
如果这个函数被调用,你应该返回undefined以避免不明确的加载结果。
this.async
告诉 loader-runner 这个 loader 将会异步地回调。返回 this.callback
。
this.data
在 pitch 阶段和正常阶段之间共享的 data 对象。
this.cacheable
一个设置可缓存标志的函数:
cacheable(flag = true: boolean)
默认情况下,loader 的处理结果会被标记为可缓存。调用这个方法然后传入 false
,可以关闭 loader 的缓存。
一个可缓存的 loader 在输入和相关依赖没有变化时,必须返回相同的结果。这意味着 loader 除了 this.addDependency
里指定的以外,不应该有其它任何外部依赖。
this.loaders
所有 loader 组成的数组。它在 pitch 阶段的时候是可以写入的。
loaders = [{request: string, path: string, query: string, module: function}]
在这个例子中:
[
{
request: "/abc/loader1.js?xyz",
path: "/abc/loader1.js",
query: "?xyz",
module: [Function]
},
{
request: "/abc/node_modules/loader2/index.js",
path: "/abc/node_modules/loader2/index.js",
query: "",
module: [Function]
}
]
this.loaderIndex
当前加载器的loaders数组中的索引。
在这个例子中:在loader1中0
,在loader2中:1
this.resource
request 中的资源部分,包括 query 参数。
在这个例子中: "/abc/resource.js?rrr"
this.resourcePath
资源文件。
在这个例子中: "/abc/resource.js"
this.resourceQuery
资源的 query 参数。
在这个例子中: "?rrr"
this.target
编译的目标。从配置选项中传递过来的。
示例值:"web"
,"node"
this.webpack
这个布尔值在被webpack编译时设置为true。
loader 最初被设计为可以同时当 Babel transform 用。如果你编写了一个 loader 可以同时兼容二者,那么可以使用这个属性了解是否存在可用的 loaderContext 和 webpack 特性。
this.sourceMap
应该生成一个 source map。因为生成 source map 可能会非常耗时,你应该确认 source map 确实有必要请求。
this.emitWarning
emitWarning(message: string)
发出警告。
this.emitError
emitError(message: string)
发出错误。
this.loadModule
loadModule(request: string, callback: function(err, source, sourceMap, module))
解析给定的 request 到一个模块,应用所有配置的 loader ,并且在回调函数中传入生成的 source 、sourceMap 和 模块实例(通常是 NormalModule
的一个实例)。如果你需要获取其他模块的源代码来生成结果的话,你可以使用这个函数。
this.resolve
resolve(context: string, request: string, callback: function(err, result: string))
像 require 表达式一样解析一个 request 。
this.addDependency
addDependency(file: string)
dependency(file: string) // shortcut
加入一个文件作为产生 loader 结果的依赖,使它们的任何变化可以被监听到。例如,html-loader
就使用了这个技巧,当它发现 src
和 src-set
属性时,就会把这些属性上的 url 加入到被解析的 html 文件的依赖中。
this.addContextDependency
addContextDependency(directory: string)
添加一个目录作为加载器结果的依赖关系。
this.clearDependencies
clearDependencies()
删除加载器结果的所有依赖关系。即使是最初的依赖和其他装载机的这些。考虑使用pitch
。
this.emitFile
emitFile(name: string, content: Buffer|string, sourceMap: {...})
发出一个文件。这是特定于webpack的。
this.fs
访问compilation
的inputFileSystem
财产。
弃用的上下文属性
由于我们正计划将它们从上下文中移除,因此非常不鼓励使用这些属性。他们仍然列在这里作为文件目的。
this.exec
exec(code: string, filename: string)
像模块一样执行一些代码片段。如果需要,请参阅此评论以获取替换方法。
this.resolveSync
resolveSync(context: string, request: string) -> string
解决请求表达式这样的请求。
this.value
将值传递给下一个加载器。如果你知道你的结果导出是否作为模块执行,在这里设置这个值(作为唯一的元素数组)。
this.inputValue
从最后一个加载器传入。如果您要将输入参数作为模块执行,请考虑读取此变量以获取快捷方式(用于性能)。
this.options
传递给编译器的选项。
this.debug
布尔标志。它在调试模式下被设置。
this.minimize
结果应该最小化。
this._compilation
Hacky访问webpack的编译对象。
this._compiler
Hacky访问webpack的编译器对象。
this._module
Hacky访问正在加载的Module对象。
本文档系腾讯云开发者社区成员共同维护,如有问题请联系 cloudcommunity@tencent.com