diff --git a/website/docs/en/api/javascript-api/compilation.mdx b/website/docs/en/api/javascript-api/compilation.mdx
index 493ec05f594..f837d3db905 100644
--- a/website/docs/en/api/javascript-api/compilation.mdx
+++ b/website/docs/en/api/javascript-api/compilation.mdx
@@ -14,6 +14,7 @@ import CompilerType from '../../types/compiler.mdx';
import RspackErrorType from '../../types/rspack-error.mdx';
import CompilationDependenciesType from '../../types/compilation-dependencies.mdx';
import { Collapse, CollapsePanel } from '@components/Collapse';
+import { ApiMeta } from '@components/ApiMeta';
@@ -410,6 +411,67 @@ compiler.hooks.make.tap('MyPlugin', compilation => {
+### addRuntimeModule
+
+
+
+Add a custom runtime module to the compilation.
+
+```ts
+addRuntimeModule(
+ c: Chunk, // the runtime chunk which to add the runtime module
+ m: RuntimeModule, // the runtime module instance to add
+): void;
+```
+
+The following code will add a runtime module which define `__webpack_require__.mock` to the `"main"` chunk:
+
+```js title="rspack.config.js"
+module.exports = {
+ entry: './index.js',
+ plugins: [
+ {
+ apply(compiler) {
+ const { RuntimeModule } = compiler.webpack;
+
+ class CustomRuntimeModule extends RuntimeModule {
+ constructor() {
+ super('custom');
+ }
+
+ generate(compilation) {
+ return `
+ __webpack_require__.mock = function() {
+ // ...
+ };
+ `;
+ }
+ }
+
+ compiler.hooks.thisCompilation.tap('CustomPlugin', compilation => {
+ compilation.hooks.runtimeRequirementInTree.tap(
+ 'CustomPlugin',
+ (chunk, set) => {
+ if (chunk.name === 'main') {
+ compilation.addRuntimeModule(chunk, new CustomRuntimeModule());
+ }
+ },
+ );
+ });
+ },
+ },
+ ],
+};
+```
+
+When implementing a custom runtime module class, the following methods/properties can be overridden to control the behavior of the runtime module:
+
+- Pass the `name` and `stage` parameters in the constructor to specify the module name and the insertion stage.
+- Override the `generate()` method to control the generated code of the module.
+- Override the `shouldIsolate()` method to control whether the module is wrapped in an IIFE.
+- Override the `attach()` method to modify the behavior when the module is added.
+- Modify its `fullHash` or `dependentHash` properties to control whether the module can be cached.
+
### rebuildModule
Triggers a re-build of the module.
diff --git a/website/docs/en/api/plugin-api/compilation-hooks.mdx b/website/docs/en/api/plugin-api/compilation-hooks.mdx
index d0cde2a367e..d107e54d5fa 100644
--- a/website/docs/en/api/plugin-api/compilation-hooks.mdx
+++ b/website/docs/en/api/plugin-api/compilation-hooks.mdx
@@ -9,6 +9,7 @@ import CompilerType from '../../types/compiler.mdx';
import { Collapse, CollapsePanel } from '@components/Collapse';
import Columns from '@components/Columns';
import { NoSSR } from 'rspress/runtime';
+import { ApiMeta } from '@components/ApiMeta';
# Compilation Hooks
@@ -268,12 +269,12 @@ direction LR
HookModuleRuntime --> HookAdditionalChunkRuntime(hooks.additionalChunkRuntimeRequirements)
HookAdditionalChunkRuntime --> HookChunkRuntime(hooks.runtimeRequirementInChunk)
HookChunkRuntime --> HookAdditionalTreeRuntime(hooks.additionalTreeRuntimeRequirements)
- HookAdditionalTreeRuntime --> HookTreeRuntime(hooks.runtimeRequirementInTree)
+ HookAdditionalTreeRuntime --> HookTreeRuntime(hooks.runtimeRequirementInTree)
HookTreeRuntime --> HookAfterRuntimeRequirements(hooks.afterRuntimeRequirements)
HookTreeRuntime <--> HookRuntimeModule(hooks.runtimeModule)
- class HookBeforeRuntime,HookModuleRuntime,HookAdditionalChunkRuntime,HookChunkRuntime,HookTreeRuntime,HookAfterRuntimeRequirements, flow-hook-non-support
- class HookAdditionalTreeRuntime,HookRuntimeModule flow-hook-partial-support
+ class HookBeforeRuntime,HookModuleRuntime,HookAdditionalChunkRuntime,HookChunkRuntime,HookAfterRuntimeRequirements, flow-hook-non-support
+ class HookAdditionalTreeRuntime,HookRuntimeModule,HookTreeRuntime flow-hook-partial-support
class ModuleCodeGeneration flow-process
end
@@ -554,8 +555,6 @@ Called after the tree optimization, at the beginning of the chunk modules optimi
## `additionalTreeRuntimeRequirements`
-
-
Called after the tree runtime requirements collection.
- **Type:** `SyncHook<[Chunk, Set]>`
@@ -563,20 +562,91 @@ Called after the tree runtime requirements collection.
- `Chunk`: chunk instance
- `Set`: runtime requirements
-
-
- ```ts enum RuntimeGlobals {}
- ```
-
-
+Additional builtin runtime modules can be added here by modifying the runtime requirements set.
-## `runtimeModule`
+```js title="rspack.config.js"
+module.exports = {
+ entry: './index.js',
+ plugins: [
+ {
+ apply(compiler) {
+ const { RuntimeGlobals } = compiler.webpack;
+ compiler.hooks.thisCompilation.tap('CustomPlugin', compilation => {
+ compilation.hooks.additionalTreeRuntimeRequirements.tap(
+ 'CustomPlugin',
+ (_, set) => {
+ // add a runtime module which define `__webpack_require__.h`
+ set.add(RuntimeGlobals.getFullHash);
+ },
+ );
+ });
+ },
+ },
+ ],
+};
+```
-
+```js title="index.js"
+// will print hash of this compilation
+console.log(__webpack_require__.h);
+```
+
+## `runtimeRequirementInTree`
+
+
+
+Called during adding runtime modules to the compilation.
+
+- **Type:** `SyncBailHook<[Chunk, Set]>`
+- **Arguments:**
+ - `Chunk`: chunk instance
+ - `Set`: runtime requirements
+
+Additional builtin runtime modules can be added here by modifying the runtime requirements set or calling [`compilation.addRuntimeModule`](/api/javascript-api/compilation#addruntimemodule) to add custom runtime modules.
+
+```js title="rspack.config.js"
+module.exports = {
+ entry: './index.js',
+ plugins: [
+ {
+ apply(compiler) {
+ const { RuntimeGlobals, RuntimeModule } = compiler.webpack;
+ class CustomRuntimeModule extends RuntimeModule {
+ constructor() {
+ super('custom');
+ }
+
+ generate(compilation) {
+ return `
+ __webpack_require__.mock = function(file) {
+ return ${RuntimeGlobals.publicPath} + "/subpath/" + file;
+ };
+ `;
+ }
+ }
+
+ compiler.hooks.thisCompilation.tap('CustomPlugin', compilation => {
+ compilation.hooks.runtimeRequirementInTree.tap(
+ 'CustomPlugin',
+ (chunk, set) => {
+ // add a runtime module to access public path
+ set.add(RuntimeGlobals.publicPath);
+ compilation.addRuntimeModule(chunk, new CustomRuntimeModule());
+ },
+ );
+ });
+ },
+ },
+ ],
+};
+```
+
+```js title="index.js"
+// will print "/subpath/index.js"
+console.log(__webpack_require__.mock('index.js'));
+```
+
+## `runtimeModule`
Called after a runtime module is added into the compilation.
@@ -585,6 +655,39 @@ Called after a runtime module is added into the compilation.
- `RuntimeModule`: runtime module instance
- `Chunk`: chunk instance
+Generated code of this runtime module can be modified through its `source` property.
+
+```js title="rspack.config.js"
+module.exports = {
+ plugins: [
+ {
+ apply(compiler) {
+ const { RuntimeGlobals } = compiler.webpack;
+ compiler.hooks.compilation.tap('CustomPlugin', compilation => {
+ compilation.hooks.runtimeModule.tap(
+ 'CustomPlugin',
+ (module, chunk) => {
+ if (module.name === 'public_path' && chunk.name === 'main') {
+ const originSource = module.source.source.toString('utf-8');
+ module.source.source = Buffer.from(
+ `${RuntimeGlobals.publicPath} = "/override/public/path";\n`,
+ 'utf-8',
+ );
+ }
+ },
+ );
+ });
+ },
+ },
+ ],
+};
+```
+
+```js title="index.js"
+// will print "/override/public/path"
+console.log(__webpack_require__.p);
+```
+
@@ -410,6 +411,67 @@ compiler.hooks.make.tap('MyPlugin', compilation => {
+### addRuntimeModule
+
+
+
+添加一个自定义的运行时模块。
+
+```ts
+addRuntimeModule(
+ c: Chunk, // 运行时模块所在的 Chunk
+ m: RuntimeModule, // 运行时模块的实例
+): void;
+```
+
+以下代码添加一个运行时模块,该模块定义 `__webpack_require__.mock`,并添加到 `"main"` Chunk 中:
+
+```js title="rspack.config.js"
+module.exports = {
+ entry: './index.js',
+ plugins: [
+ {
+ apply(compiler) {
+ const { RuntimeModule } = compiler.webpack;
+
+ class CustomRuntimeModule extends RuntimeModule {
+ constructor() {
+ super('custom', RuntimeModule.STAGE_NORMAL);
+ }
+
+ generate(compilation) {
+ return `
+ __webpack_require__.mock = function() {
+ // ...
+ };
+ `;
+ }
+ }
+
+ compiler.hooks.thisCompilation.tap('CustomPlugin', compilation => {
+ compilation.hooks.runtimeRequirementInTree.tap(
+ 'CustomPlugin',
+ (chunk, set) => {
+ if (chunk.name === 'main') {
+ compilation.addRuntimeModule(chunk, new CustomRuntimeModule());
+ }
+ },
+ );
+ });
+ },
+ },
+ ],
+};
+```
+
+实现自定义的运行时模块 Class 时,可覆盖如下方法/属性来控制其行为:
+
+- 在构造器中传入 `name` 和 `stage` 参数来指定模块名称和插入的阶段
+- 覆盖 `generate()` 方法以控制模块生成的代码
+- 覆盖 `shouldIsolate()` 方法以控制模块是否包裹在 IIFE 当中
+- 覆盖 `attach()` 方法以修改在模块被添加时的行为
+- 修改其 `fullHash` 或 `dependentHash` 属性以控制模块是否可被缓存
+
### rebuildModule
重新构建指定模块。
diff --git a/website/docs/zh/api/plugin-api/compilation-hooks.mdx b/website/docs/zh/api/plugin-api/compilation-hooks.mdx
index 735aeea302f..dbecd996460 100644
--- a/website/docs/zh/api/plugin-api/compilation-hooks.mdx
+++ b/website/docs/zh/api/plugin-api/compilation-hooks.mdx
@@ -9,6 +9,7 @@ import CompilerType from '../../types/compiler.mdx';
import { Collapse, CollapsePanel } from '@components/Collapse';
import Columns from '@components/Columns';
import { NoSSR } from 'rspress/runtime';
+import { ApiMeta } from '@components/ApiMeta';
# Compilation 钩子
@@ -269,12 +270,12 @@ direction LR
HookModuleRuntime --> HookAdditionalChunkRuntime(hooks.additionalChunkRuntimeRequirements)
HookAdditionalChunkRuntime --> HookChunkRuntime(hooks.runtimeRequirementInChunk)
HookChunkRuntime --> HookAdditionalTreeRuntime(hooks.additionalTreeRuntimeRequirements)
- HookAdditionalTreeRuntime --> HookTreeRuntime(hooks.runtimeRequirementInTree)
+ HookAdditionalTreeRuntime --> HookTreeRuntime(hooks.runtimeRequirementInTree)
HookTreeRuntime --> HookAfterRuntimeRequirements(hooks.afterRuntimeRequirements)
HookTreeRuntime <--> HookRuntimeModule(hooks.runtimeModule)
- class HookBeforeRuntime,HookModuleRuntime,HookAdditionalChunkRuntime,HookChunkRuntime,HookTreeRuntime,HookAfterRuntimeRequirements, flow-hook-non-support
- class HookAdditionalTreeRuntime,HookRuntimeModule flow-hook-partial-support
+ class HookBeforeRuntime,HookModuleRuntime,HookAdditionalChunkRuntime,HookChunkRuntime,HookAfterRuntimeRequirements, flow-hook-non-support
+ class HookAdditionalTreeRuntime,HookRuntimeModule,HookTreeRuntime flow-hook-partial-support
class ModuleCodeGeneration flow-process
end
@@ -555,29 +556,99 @@ type ExecuteModuleContext = {
## `additionalTreeRuntimeRequirements`
-
-
在树运行时依赖计算完成后调用。
- **类型:** `SyncHook<[Chunk, Set]>`
- **参数:**
- `Chunk`:Chunk 实例
- - `Set`:运行时依赖
+ - `Set`:运行时依赖集合
-
-
- ```ts enum RuntimeGlobals {}
- ```
-
-
+可通过修改运行时依赖集合以添加额外的内置运行时模块:
-## `runtimeModule`
+```js title="rspack.config.js"
+module.exports = {
+ entry: './index.js',
+ plugins: [
+ {
+ apply(compiler) {
+ const { RuntimeGlobals } = compiler.webpack;
+ compiler.hooks.thisCompilation.tap('CustomPlugin', compilation => {
+ compilation.hooks.additionalTreeRuntimeRequirements.tap(
+ 'CustomPlugin',
+ (_, set) => {
+ // 添加访问 compilation 哈希值的运行时模块
+ set.add(RuntimeGlobals.getFullHash);
+ },
+ );
+ });
+ },
+ },
+ ],
+};
+```
-
+```js title="index.js"
+// 将打印 compilation 的哈希值
+console.log(__webpack_require__.h);
+```
+
+## `runtimeRequirementInTree`
+
+
+
+在根据运行时依赖以添加运行时模块时调用。
+
+- **类型:** `SyncBailHook<[Chunk, Set]>`
+- **参数:**
+ - `Chunk`:Chunk 实例
+ - `Set`:运行时依赖集合
+
+可通过修改运行时依赖集合以添加额外的内置运行时模块,也可通过 [`compilation.addRuntimeModule`](/api/javascript-api/compilation#addruntimemodule) 添加自定义运行时模块:
+
+```js title="rspack.config.js"
+module.exports = {
+ entry: './index.js',
+ plugins: [
+ {
+ apply(compiler) {
+ const { RuntimeGlobals, RuntimeModule } = compiler.webpack;
+ class CustomRuntimeModule extends RuntimeModule {
+ constructor() {
+ super('custom');
+ }
+
+ generate(compilation) {
+ return `
+ __webpack_require__.mock = function(file) {
+ return ${RuntimeGlobals.publicPath} + "/subpath/" + file;
+ };
+ `;
+ }
+ }
+
+ compiler.hooks.thisCompilation.tap('CustomPlugin', compilation => {
+ compilation.hooks.runtimeRequirementInTree.tap(
+ 'CustomPlugin',
+ (chunk, set) => {
+ // 添加访问 publicPath 的运行时模块
+ set.add(RuntimeGlobals.publicPath);
+ // 添加自定义运行时模块
+ compilation.addRuntimeModule(chunk, new CustomRuntimeModule());
+ },
+ );
+ });
+ },
+ },
+ ],
+};
+```
+
+```js title="index.js"
+// 将打印 "/subpath/index.js"
+console.log(__webpack_require__.mock('index.js'));
+```
+
+## `runtimeModule`
在运行时模块被添加后调用。
@@ -586,6 +657,39 @@ type ExecuteModuleContext = {
- `RuntimeModule`:运行时模块
- `Chunk`:Chunk 实例
+可通过 `source` 字段修改该运行时模块生成的代码。
+
+```js title="rspack.config.js"
+module.exports = {
+ plugins: [
+ {
+ apply(compiler) {
+ const { RuntimeGlobals } = compiler.webpack;
+ compiler.hooks.compilation.tap('CustomPlugin', compilation => {
+ compilation.hooks.runtimeModule.tap(
+ 'CustomPlugin',
+ (module, chunk) => {
+ if (module.name === 'public_path' && chunk.name === 'main') {
+ const originSource = module.source.source.toString('utf-8');
+ module.source.source = Buffer.from(
+ `${RuntimeGlobals.publicPath} = "/override/public/path";\n`,
+ 'utf-8',
+ );
+ }
+ },
+ );
+ });
+ },
+ },
+ ],
+};
+```
+
+```js title="index.js"
+// 将打印 "/override/public/path"
+console.log(__webpack_require__.p);
+```
+