CC 4.0 协议声明
本节内容派生于以下链接指向的内容 ,并遵守 CC BY 4.0 许可证的规定。
以下内容如果没有特殊声明,可以认为都是基于原内容的修改和删减后的结果。
Loader 上下文
Loader 上下文表示 loader 内部可用的属性,这些属性在 loader 中通过 this 属性进行访问。
this.addContextDependency()
function addContextDependency(directory: string): void;
添加目录作为 loader 结果的依赖,使目录中文件的任何变化可以被监听到。
例如,添加 src/static 目录作为依赖,当目录中的文件发生变化时,会触发重新构建。
loader.js
const path = require('node:path');
module.exports = function loader(source) {
this.addContextDependency(path.resolve(this.rootContext, 'src/static'));
return source;
};
this.addDependency()
function addDependency(file: string): void;
添加一个文件作为 loader 结果的依赖,使它们的任何变化可以被监听到。例如,sass-loader、less-loader 就使用了这个技巧,当导入的样式文件发生变化时就会重新编译。
loader.js
const path = require('node:path');
module.exports = function loader(source) {
this.addDependency(path.resolve(this.rootContext, 'src/styles/foo.scss'));
return source;
};
this.addMissingDependency()
function addMissingDependency(file: string): void;
添加一个当前不存在的文件作为 loader 结果的依赖,使它们的创建和任何变化可以被监听到。例如,当该路径下新建了文件时,会触发重新构建。
loader.js
const path = require('node:path');
module.exports = function loader(source) {
this.addMissingDependency(
path.resolve(this.rootContext, 'src/dynamic-file.json'),
);
return source;
};
this.async()
- 类型:
() => LoaderContextCallback
告诉 Rspack 这个 loader 将会异步被调用。返回值为 this.callback。
this.cacheable()
function cacheable(flag: boolean = true): void;
默认情况下,loader 的处理结果会被标记为可缓存。调用这个方法然后传入 false,可以关闭 loader 处理结果的缓存能力。
this.clearDependencies()
function clearDependencies(): void;
移除 loader 结果的所有依赖。
this.callback()
function callback(
err: Error | null,
content: string | Buffer,
sourceMap?: SourceMap,
meta?: any,
): void;
将 Loader 处理后的结果告诉 Rspack。
第一个参数必须是 Error 或者 null,会标记当前模块为编译失败,第二个参数是一个 string 或者 Buffer,表示模块被该 Loader 处理后的文件内容,第三个参数是一个可以该 Loader 处理后的 source map,第四个参数会被 Rspack 忽略,可以是任何东西(例如一些元数据)。
WARNING
当这个函数被调用时,你应该返回 undefined 以避免 loader 结果的歧义。
传递给 this.callback 的值会传递给下一个 loader。
sourceMap 和 meta 参数是可选的,如果没有传递,那么下一个 loader 将不会收到它们。
this.context
当前被处理的模块所在的目录路径,会随着每个被处理的模块的位置而变化。
例如,如果 loader 处理的是 /project/src/components/Button.js,那么 this.context 的值就是 /project/src/components。
loader.js
module.exports = function loader(source) {
console.log(this.context); // '/project/src/components'
return source;
};
如果被处理的是模块不是来自文件系统,例如虚拟模块,那么 this.context 的值为 null。
this.data
用于在 pitch 和 normal 阶段之间共享数据。
this.dependency()
function dependency(file: string): void;
this.addDependency() 的别名。
this.emitError()
function emitError(err: Error): void;
发出一个错误,与在 loader 中 throw 和 this.callback(err) 不同,它不会标记当前模块为编译失败,只会在 Rspack 的 Compilation 上添加一个错误,并在此次编译结束后显示在命令行中。
this.emitWarning()
function emitWarning(warning: Error): void;
发出一个警告。
this.emitFile()
function emitFile(
name: string,
content: string | Buffer,
sourceMap?: string,
assetInfo?: JsAssetInfo,
): void;
输出一个新文件。这个方法允许你在 loader 执行过程中创建新的文件。
loader.js
module.exports = function loader(source) {
// 输出一个新文件,该文件将在产物目录中输出为 `foo.js`
this.emitFile('foo.js', 'console.log("Hello, world!");');
return source;
};
loader.js
module.exports = function loader(source) {
this.emitFile(
'foo.js',
'console.log("Hello, world!");',
undefined, // no sourcemap
{
sourceFilename: this.resourcePath,
},
);
return source;
};
this.getOptions()
function getOptions(schema?: any): OptionsType;
获取 loader 的使用者传入的选项。
例如:
rspack.config.mjs
export default {
module: {
rules: [
{
test: /\.txt$/,
use: {
loader: './my-loader.js',
options: {
foo: 'bar',
},
},
},
],
},
};
在 my-loader.js 中获取传入的选项:
my-loader.js
module.exports = function myLoader(source) {
const options = this.getOptions();
console.log(options); // { foo: 'bar' }
return source;
};
在 TypeScript 中,你可以通过 LoaderContext 的泛型来设置 options 的类型。
my-loader.ts
import type { LoaderContext } from '@rspack/core';
type MyLoaderOptions = {
foo: string;
};
export default function myLoader(
this: LoaderContext<MyLoaderOptions>,
source: string,
) {
const options = this.getOptions();
console.log(options); // { foo: 'bar' }
return source;
}
TIP
参数 schema 是可选的,在 Rspack 中不会被使用。
为了提供最佳性能,Rspack 不会执行 schema 验证。如果你的 loader 需要 schema 验证,请自行调用 scheme-utils 或其他 schema 验证库。
this.getResolve()
function getResolve(options: ResolveOptions): resolve;
创建一个类似于 this.resolve 的解析函数。
this.importModule()
interface ImportModuleOptions {
/**
* 指定模块的 layer
*/
layer?: string;
/**
* 构建模块时使用的 public path
*/
publicPath?: PublicPath;
/**
* 目标 base uri
*/
baseUri?: string;
}
// 传入回调函数
function importModule<T = any>(
request: string,
options: ImportModuleOptions | undefined,
callback: (err?: null | Error, exports?: T) => any,
): void;
// 不传入回调函数时,返回 Promise
function importModule<T = any>(
request: string,
options?: ImportModuleOptions,
): Promise<T>;
在构建过程中编译和执行一个模块。这是 child compiler 的轻量级替代方案。
在没有提供回调函数时,importModule 会返回一个 Promise。
loader.js
const path = require('node:path');
module.exports = async function loader(source) {
const modulePath = path.resolve(this.rootContext, 'some-module.ts');
const moduleExports = await this.importModule(modulePath, {
// 可选参数
});
const result = someProcessing(source, moduleExports);
return result;
};
或者你可以传递一个回调函数给它。
loader.js
const path = require('node:path');
module.exports = function loader(source) {
const callback = this.async();
const modulePath = path.resolve(this.rootContext, 'some-module.ts');
this.importModule(
modulePath,
// 可选参数
undefined,
(err, moduleExports) => {
if (err) {
return callback(err);
}
const result = someProcessing(source, moduleExports);
callback(null, result);
},
);
};
this.resolve()
function resolve(
context: string,
request: string,
callback: (err: Error | null, result: string) => void,
): void;
解析一个模块标识符。
context 必须是一个目录的绝对路径。此目录用作解析的起始位置。
request 是要被解析的模块标识符。
callback 是一个处理解析路径的回调函数。
this.mode
当 Rspack 运行时读取 mode 的值,可能的值为:'production'、'development'、'none'。
loader.js
module.exports = function loader(source) {
console.log(this.mode); // 'production' or other values
return source;
};
this.target
当 Rspack 运行时读取 target 的值。
loader.js
module.exports = function loader(source) {
console.log(this.target); // 'web' or other values
return source;
};
this.resource
当前模块的路径字符串。比如 '/abc/resource.js?query#hash'。
loader.js
module.exports = function loader(source) {
console.log(this.resource); // '/abc/resource.js?query#hash'
return source;
};
this.resourcePath
当前模块的路径字符串,不包括 query 和 fragment 参数。比如 '/abc/resource.js?query#hash' 中的 '/abc/resource.js'。
loader.js
module.exports = function loader(source) {
console.log(this.resourcePath); // '/abc/resource.js'
return source;
};
this.resourceQuery
当前模块的路径字符串的 query 参数。比如 '/abc/resource.js?query#hash' 中的 '?query'。
loader.js
module.exports = function loader(source) {
console.log(this.resourceQuery); // '?query'
return source;
};
this.resourceFragment
当前模块的路径字符串的 fragment 参数。比如 '/abc/resource.js?query#hash' 中的 '#hash'。
loader.js
module.exports = function loader(source) {
console.log(this.resourceFragment); // '#hash'
return source;
};
this.rootContext
Rspack config 中通过 context 配置的基础路径。
loader.js
module.exports = function loader(source) {
console.log(this.rootContext); // /path/to/project
return source;
};
this.sourceMap
是否应该生成一个 source map。
this.getLogger()
function getLogger(name?: string): Logger;
获取此次编译过程的 logger,可通过该 logger 记录消息。