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.js
module.exports = {
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 记录消息。