Skip to content

Commit 5ee65b4

Browse files
hamlimhardfist
andauthored
feat: add beforeModuleIds hook (#12809)
feat: add beforeModuleIds hook Co-authored-by: hardfist <yangjianzju@gmail.com>
1 parent d9e9d2e commit 5ee65b4

File tree

14 files changed

+335
-60
lines changed

14 files changed

+335
-60
lines changed

crates/node_binding/napi-binding.d.ts

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,14 @@ export interface JsBeforeEmitData {
717717
uid?: number
718718
}
719719

720+
export interface JsBeforeModuleIdsArg {
721+
modules: Array<JsModuleForIds>
722+
}
723+
724+
export interface JsBeforeModuleIdsResult {
725+
assignments: Record<string, string>
726+
}
727+
720728
export interface JsBuildMeta {
721729
strictEsmModule?: boolean
722730
hasTopLevelAwait?: boolean
@@ -980,6 +988,10 @@ export interface JsModuleDescriptor {
980988
id?: string | number | null
981989
}
982990

991+
export interface JsModuleForIds {
992+
identifier: string
993+
}
994+
983995
export interface JsNormalModuleFactoryCreateModuleArgs {
984996
dependencyType: string
985997
rawRequest: string
@@ -2966,39 +2978,40 @@ export declare enum RegisterJsTapKind {
29662978
CompilationAfterOptimizeModules = 14,
29672979
CompilationOptimizeTree = 15,
29682980
CompilationOptimizeChunkModules = 16,
2969-
CompilationAdditionalTreeRuntimeRequirements = 17,
2970-
CompilationRuntimeRequirementInTree = 18,
2971-
CompilationRuntimeModule = 19,
2972-
CompilationChunkHash = 20,
2973-
CompilationChunkAsset = 21,
2974-
CompilationProcessAssets = 22,
2975-
CompilationAfterProcessAssets = 23,
2976-
CompilationSeal = 24,
2977-
CompilationAfterSeal = 25,
2978-
NormalModuleFactoryBeforeResolve = 26,
2979-
NormalModuleFactoryFactorize = 27,
2980-
NormalModuleFactoryResolve = 28,
2981-
NormalModuleFactoryAfterResolve = 29,
2982-
NormalModuleFactoryCreateModule = 30,
2983-
NormalModuleFactoryResolveForScheme = 31,
2984-
ContextModuleFactoryBeforeResolve = 32,
2985-
ContextModuleFactoryAfterResolve = 33,
2986-
JavascriptModulesChunkHash = 34,
2987-
HtmlPluginBeforeAssetTagGeneration = 35,
2988-
HtmlPluginAlterAssetTags = 36,
2989-
HtmlPluginAlterAssetTagGroups = 37,
2990-
HtmlPluginAfterTemplateExecution = 38,
2991-
HtmlPluginBeforeEmit = 39,
2992-
HtmlPluginAfterEmit = 40,
2993-
RuntimePluginCreateScript = 41,
2994-
RuntimePluginCreateLink = 42,
2995-
RuntimePluginLinkPreload = 43,
2996-
RuntimePluginLinkPrefetch = 44,
2997-
RsdoctorPluginModuleGraph = 45,
2998-
RsdoctorPluginChunkGraph = 46,
2999-
RsdoctorPluginModuleIds = 47,
3000-
RsdoctorPluginModuleSources = 48,
3001-
RsdoctorPluginAssets = 49
2981+
CompilationBeforeModuleIds = 17,
2982+
CompilationAdditionalTreeRuntimeRequirements = 18,
2983+
CompilationRuntimeRequirementInTree = 19,
2984+
CompilationRuntimeModule = 20,
2985+
CompilationChunkHash = 21,
2986+
CompilationChunkAsset = 22,
2987+
CompilationProcessAssets = 23,
2988+
CompilationAfterProcessAssets = 24,
2989+
CompilationSeal = 25,
2990+
CompilationAfterSeal = 26,
2991+
NormalModuleFactoryBeforeResolve = 27,
2992+
NormalModuleFactoryFactorize = 28,
2993+
NormalModuleFactoryResolve = 29,
2994+
NormalModuleFactoryAfterResolve = 30,
2995+
NormalModuleFactoryCreateModule = 31,
2996+
NormalModuleFactoryResolveForScheme = 32,
2997+
ContextModuleFactoryBeforeResolve = 33,
2998+
ContextModuleFactoryAfterResolve = 34,
2999+
JavascriptModulesChunkHash = 35,
3000+
HtmlPluginBeforeAssetTagGeneration = 36,
3001+
HtmlPluginAlterAssetTags = 37,
3002+
HtmlPluginAlterAssetTagGroups = 38,
3003+
HtmlPluginAfterTemplateExecution = 39,
3004+
HtmlPluginBeforeEmit = 40,
3005+
HtmlPluginAfterEmit = 41,
3006+
RuntimePluginCreateScript = 42,
3007+
RuntimePluginCreateLink = 43,
3008+
RuntimePluginLinkPreload = 44,
3009+
RuntimePluginLinkPrefetch = 45,
3010+
RsdoctorPluginModuleGraph = 46,
3011+
RsdoctorPluginChunkGraph = 47,
3012+
RsdoctorPluginModuleIds = 48,
3013+
RsdoctorPluginModuleSources = 49,
3014+
RsdoctorPluginAssets = 50
30023015
}
30033016

30043017
export interface RegisterJsTaps {
@@ -3022,6 +3035,7 @@ export interface RegisterJsTaps {
30223035
registerCompilationAfterOptimizeModulesTaps: (stages: Array<number>) => Array<{ function: (() => void); stage: number; }>
30233036
registerCompilationOptimizeTreeTaps: (stages: Array<number>) => Array<{ function: (() => Promise<void>); stage: number; }>
30243037
registerCompilationOptimizeChunkModulesTaps: (stages: Array<number>) => Array<{ function: (() => Promise<boolean | undefined>); stage: number; }>
3038+
registerCompilationBeforeModuleIdsTaps: (stages: Array<number>) => Array<{ function: ((arg: JsBeforeModuleIdsArg) => JsBeforeModuleIdsResult); stage: number; }>
30253039
registerCompilationChunkHashTaps: (stages: Array<number>) => Array<{ function: ((arg: Chunk) => Buffer); stage: number; }>
30263040
registerCompilationChunkAssetTaps: (stages: Array<number>) => Array<{ function: ((arg: JsChunkAssetArgs) => void); stage: number; }>
30273041
registerCompilationProcessAssetsTaps: (stages: Array<number>) => Array<{ function: ((arg: JsCompilation) => Promise<void>); stage: number; }>

crates/rspack_binding_api/src/plugins/interceptor.rs

Lines changed: 87 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::{
2+
collections::HashMap,
23
hash::Hash,
34
ptr::NonNull,
45
sync::{Arc, RwLock},
@@ -13,32 +14,32 @@ use napi::{
1314
use rspack_collections::{IdentifierMap, IdentifierSet};
1415
use rspack_core::{
1516
AfterResolveResult, AssetEmittedInfo, AsyncModulesArtifact, BeforeResolveResult, BindingCell,
16-
BoxModule, ChunkUkey, Compilation, CompilationAdditionalTreeRuntimeRequirements,
17+
BoxModule, ChunkGraph, ChunkUkey, Compilation, CompilationAdditionalTreeRuntimeRequirements,
1718
CompilationAdditionalTreeRuntimeRequirementsHook, CompilationAfterOptimizeModules,
1819
CompilationAfterOptimizeModulesHook, CompilationAfterProcessAssets,
1920
CompilationAfterProcessAssetsHook, CompilationAfterSeal, CompilationAfterSealHook,
20-
CompilationBuildModule, CompilationBuildModuleHook, CompilationChunkAsset,
21-
CompilationChunkAssetHook, CompilationChunkHash, CompilationChunkHashHook,
22-
CompilationExecuteModule, CompilationExecuteModuleHook, CompilationFinishModules,
23-
CompilationFinishModulesHook, CompilationId, CompilationOptimizeChunkModules,
24-
CompilationOptimizeChunkModulesHook, CompilationOptimizeModules, CompilationOptimizeModulesHook,
25-
CompilationOptimizeTree, CompilationOptimizeTreeHook, CompilationParams,
26-
CompilationProcessAssets, CompilationProcessAssetsHook, CompilationRuntimeModule,
27-
CompilationRuntimeModuleHook, CompilationRuntimeRequirementInTree,
28-
CompilationRuntimeRequirementInTreeHook, CompilationSeal, CompilationSealHook,
29-
CompilationStillValidModule, CompilationStillValidModuleHook, CompilationSucceedModule,
30-
CompilationSucceedModuleHook, CompilerAfterEmit, CompilerAfterEmitHook, CompilerAssetEmitted,
31-
CompilerAssetEmittedHook, CompilerCompilation, CompilerCompilationHook, CompilerEmit,
32-
CompilerEmitHook, CompilerFinishMake, CompilerFinishMakeHook, CompilerId, CompilerMake,
33-
CompilerMakeHook, CompilerShouldEmit, CompilerShouldEmitHook, CompilerThisCompilation,
34-
CompilerThisCompilationHook, ContextModuleFactoryAfterResolve,
21+
CompilationBeforeModuleIds, CompilationBeforeModuleIdsHook, CompilationBuildModule,
22+
CompilationBuildModuleHook, CompilationChunkAsset, CompilationChunkAssetHook,
23+
CompilationChunkHash, CompilationChunkHashHook, CompilationExecuteModule,
24+
CompilationExecuteModuleHook, CompilationFinishModules, CompilationFinishModulesHook,
25+
CompilationId, CompilationOptimizeChunkModules, CompilationOptimizeChunkModulesHook,
26+
CompilationOptimizeModules, CompilationOptimizeModulesHook, CompilationOptimizeTree,
27+
CompilationOptimizeTreeHook, CompilationParams, CompilationProcessAssets,
28+
CompilationProcessAssetsHook, CompilationRuntimeModule, CompilationRuntimeModuleHook,
29+
CompilationRuntimeRequirementInTree, CompilationRuntimeRequirementInTreeHook, CompilationSeal,
30+
CompilationSealHook, CompilationStillValidModule, CompilationStillValidModuleHook,
31+
CompilationSucceedModule, CompilationSucceedModuleHook, CompilerAfterEmit, CompilerAfterEmitHook,
32+
CompilerAssetEmitted, CompilerAssetEmittedHook, CompilerCompilation, CompilerCompilationHook,
33+
CompilerEmit, CompilerEmitHook, CompilerFinishMake, CompilerFinishMakeHook, CompilerId,
34+
CompilerMake, CompilerMakeHook, CompilerShouldEmit, CompilerShouldEmitHook,
35+
CompilerThisCompilation, CompilerThisCompilationHook, ContextModuleFactoryAfterResolve,
3536
ContextModuleFactoryAfterResolveHook, ContextModuleFactoryBeforeResolve,
3637
ContextModuleFactoryBeforeResolveHook, ExecuteModuleId, Module, ModuleFactoryCreateData,
37-
ModuleIdentifier, NormalModuleCreateData, NormalModuleFactoryAfterResolve,
38-
NormalModuleFactoryAfterResolveHook, NormalModuleFactoryBeforeResolve,
39-
NormalModuleFactoryBeforeResolveHook, NormalModuleFactoryCreateModule,
40-
NormalModuleFactoryCreateModuleHook, NormalModuleFactoryFactorize,
41-
NormalModuleFactoryFactorizeHook, NormalModuleFactoryResolve,
38+
ModuleId, ModuleIdentifier, ModuleIdsArtifact, NormalModuleCreateData,
39+
NormalModuleFactoryAfterResolve, NormalModuleFactoryAfterResolveHook,
40+
NormalModuleFactoryBeforeResolve, NormalModuleFactoryBeforeResolveHook,
41+
NormalModuleFactoryCreateModule, NormalModuleFactoryCreateModuleHook,
42+
NormalModuleFactoryFactorize, NormalModuleFactoryFactorizeHook, NormalModuleFactoryResolve,
4243
NormalModuleFactoryResolveForScheme, NormalModuleFactoryResolveForSchemeHook,
4344
NormalModuleFactoryResolveHook, NormalModuleFactoryResolveResult, ResourceData, RuntimeGlobals,
4445
RuntimeModule, Scheme, build_module_graph::BuildModuleGraphArtifact, parse_resource,
@@ -101,6 +102,34 @@ use crate::{
101102
source::JsSourceToJs,
102103
};
103104

105+
#[napi(object)]
106+
pub struct JsModuleForIds {
107+
pub identifier: String,
108+
}
109+
110+
#[napi(object)]
111+
pub struct JsBeforeModuleIdsArg {
112+
pub modules: Vec<JsModuleForIds>,
113+
}
114+
115+
impl JsBeforeModuleIdsArg {
116+
pub fn new(_compilation: &Compilation, modules: &IdentifierSet) -> Self {
117+
Self {
118+
modules: modules
119+
.iter()
120+
.map(|id| JsModuleForIds {
121+
identifier: id.to_string(),
122+
})
123+
.collect(),
124+
}
125+
}
126+
}
127+
128+
#[napi(object)]
129+
pub struct JsBeforeModuleIdsResult {
130+
pub assignments: HashMap<String, String>,
131+
}
132+
104133
#[napi(object)]
105134
pub struct JsTap<'f> {
106135
#[napi(ts_type = "(...args: any[]) => any")]
@@ -343,6 +372,7 @@ pub enum RegisterJsTapKind {
343372
CompilationAfterOptimizeModules,
344373
CompilationOptimizeTree,
345374
CompilationOptimizeChunkModules,
375+
CompilationBeforeModuleIds,
346376
CompilationAdditionalTreeRuntimeRequirements,
347377
CompilationRuntimeRequirementInTree,
348378
CompilationRuntimeModule,
@@ -479,6 +509,11 @@ pub struct RegisterJsTaps {
479509
ts_type = "(stages: Array<number>) => Array<{ function: (() => Promise<boolean | undefined>); stage: number; }>"
480510
)]
481511
pub register_compilation_optimize_chunk_modules_taps: RegisterFunction<(), Promise<Option<bool>>>,
512+
#[napi(
513+
ts_type = "(stages: Array<number>) => Array<{ function: ((arg: JsBeforeModuleIdsArg) => JsBeforeModuleIdsResult); stage: number; }>"
514+
)]
515+
pub register_compilation_before_module_ids_taps:
516+
RegisterFunction<JsBeforeModuleIdsArg, JsBeforeModuleIdsResult>,
482517
#[napi(
483518
ts_type = "(stages: Array<number>) => Array<{ function: ((arg: Chunk) => Buffer); stage: number; }>"
484519
)]
@@ -750,6 +785,13 @@ define_register!(
750785
kind = RegisterJsTapKind::CompilationOptimizeChunkModules,
751786
skip = true,
752787
);
788+
define_register!(
789+
RegisterCompilationBeforeModuleIdsTaps,
790+
tap = CompilationBeforeModuleIdsTap<JsBeforeModuleIdsArg, JsBeforeModuleIdsResult> @ CompilationBeforeModuleIdsHook,
791+
cache = false,
792+
kind = RegisterJsTapKind::CompilationBeforeModuleIds,
793+
skip = true,
794+
);
753795
define_register!(
754796
RegisterCompilationAdditionalTreeRuntimeRequirementsTaps,
755797
tap = CompilationAdditionalTreeRuntimeRequirementsTap<JsAdditionalTreeRuntimeRequirementsArg, Option<JsAdditionalTreeRuntimeRequirementsResult>> @ CompilationAdditionalTreeRuntimeRequirementsHook,
@@ -1275,6 +1317,30 @@ impl CompilationOptimizeChunkModules for CompilationOptimizeChunkModulesTap {
12751317
}
12761318
}
12771319

1320+
#[async_trait]
1321+
impl CompilationBeforeModuleIds for CompilationBeforeModuleIdsTap {
1322+
async fn run(
1323+
&self,
1324+
compilation: &Compilation,
1325+
modules: &IdentifierSet,
1326+
module_ids: &mut ModuleIdsArtifact,
1327+
) -> rspack_error::Result<()> {
1328+
let arg = JsBeforeModuleIdsArg::new(compilation, modules);
1329+
let result: JsBeforeModuleIdsResult = self.function.call_with_sync(arg).await?;
1330+
1331+
for (identifier_str, id) in result.assignments {
1332+
let identifier = ModuleIdentifier::from(identifier_str.as_str());
1333+
ChunkGraph::set_module_id(module_ids, identifier, ModuleId::from(id));
1334+
}
1335+
1336+
Ok(())
1337+
}
1338+
1339+
fn stage(&self) -> i32 {
1340+
self.stage
1341+
}
1342+
}
1343+
12781344
#[async_trait]
12791345
impl CompilationAdditionalTreeRuntimeRequirements
12801346
for CompilationAdditionalTreeRuntimeRequirementsTap

crates/rspack_binding_api/src/plugins/js_hooks_plugin.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub struct JsHooksAdapterPlugin {
3535
register_compilation_after_optimize_modules_taps: RegisterCompilationAfterOptimizeModulesTaps,
3636
register_compilation_optimize_tree_taps: RegisterCompilationOptimizeTreeTaps,
3737
register_compilation_optimize_chunk_modules_taps: RegisterCompilationOptimizeChunkModulesTaps,
38+
register_compilation_before_module_ids_taps: RegisterCompilationBeforeModuleIdsTaps,
3839
register_compilation_additional_tree_runtime_requirements_taps:
3940
RegisterCompilationAdditionalTreeRuntimeRequirementsTaps,
4041
register_compilation_runtime_requirement_in_tree_taps:
@@ -158,6 +159,10 @@ impl Plugin for JsHooksAdapterPlugin {
158159
.register_compilation_optimize_chunk_modules_taps
159160
.clone(),
160161
);
162+
ctx
163+
.compilation_hooks
164+
.before_module_ids
165+
.intercept(self.register_compilation_before_module_ids_taps.clone());
161166
ctx
162167
.compilation_hooks
163168
.additional_tree_runtime_requirements
@@ -291,6 +296,9 @@ impl Plugin for JsHooksAdapterPlugin {
291296
self
292297
.register_compilation_optimize_chunk_modules_taps
293298
.clear_cache();
299+
self
300+
.register_compilation_before_module_ids_taps
301+
.clear_cache();
294302
self
295303
.register_compilation_additional_tree_runtime_requirements_taps
296304
.clear_cache();
@@ -542,6 +550,10 @@ impl JsHooksAdapterPlugin {
542550
register_js_taps.register_compilation_optimize_chunk_modules_taps,
543551
non_skippable_registers.clone(),
544552
),
553+
register_compilation_before_module_ids_taps: RegisterCompilationBeforeModuleIdsTaps::new(
554+
register_js_taps.register_compilation_before_module_ids_taps,
555+
non_skippable_registers.clone(),
556+
),
545557
register_compilation_additional_tree_runtime_requirements_taps:
546558
RegisterCompilationAdditionalTreeRuntimeRequirementsTaps::new(
547559
register_js_taps.register_compilation_additional_tree_runtime_requirements_taps,

crates/rspack_core/src/compilation/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ define_hook!(CompilationAfterOptimizeModules: Series(compilation: &Compilation))
105105
define_hook!(CompilationOptimizeChunks: SeriesBail(compilation: &mut Compilation) -> bool);
106106
define_hook!(CompilationOptimizeTree: Series(compilation: &Compilation));
107107
define_hook!(CompilationOptimizeChunkModules: SeriesBail(compilation: &mut Compilation) -> bool);
108+
define_hook!(CompilationBeforeModuleIds: Series(compilation: &Compilation, modules: &IdentifierSet, module_ids: &mut ModuleIdsArtifact));
108109
define_hook!(CompilationModuleIds: Series(compilation: &Compilation, module_ids: &mut ModuleIdsArtifact, diagnostics: &mut Vec<Diagnostic>));
109110
define_hook!(CompilationChunkIds: Series(compilation: &Compilation, chunk_by_ukey: &mut ChunkByUkey, named_chunk_ids_artifact: &mut ChunkNamedIdArtifact, diagnostics: &mut Vec<Diagnostic>));
110111
define_hook!(CompilationRuntimeModule: Series(compilation: &Compilation, module: &ModuleIdentifier, chunk: &ChunkUkey, runtime_modules: &mut IdentifierMap<Box<dyn RuntimeModule>>));
@@ -142,6 +143,7 @@ pub struct CompilationHooks {
142143
pub optimize_chunks: CompilationOptimizeChunksHook,
143144
pub optimize_tree: CompilationOptimizeTreeHook,
144145
pub optimize_chunk_modules: CompilationOptimizeChunkModulesHook,
146+
pub before_module_ids: CompilationBeforeModuleIdsHook,
145147
pub module_ids: CompilationModuleIdsHook,
146148
pub chunk_ids: CompilationChunkIdsHook,
147149
pub runtime_module: CompilationRuntimeModuleHook,

crates/rspack_core/src/compilation/module_ids/mod.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,29 @@ use async_trait::async_trait;
33
use super::*;
44
use crate::{cache::Cache, compilation::pass::PassExt};
55

6+
/// Collects module identifiers that need ID assignment.
7+
/// A module needs an ID if:
8+
/// - It doesn't already have one assigned
9+
/// - It needs an ID (need_id() returns true)
10+
/// - It's part of at least one chunk
11+
fn get_modules_needing_ids(
12+
compilation: &Compilation,
13+
module_ids_artifact: &ModuleIdsArtifact,
14+
) -> IdentifierSet {
15+
let chunk_graph = &compilation.chunk_graph;
16+
compilation
17+
.get_module_graph()
18+
.modules()
19+
.values()
20+
.filter(|m| {
21+
m.need_id()
22+
&& ChunkGraph::get_module_id(module_ids_artifact, m.identifier()).is_none()
23+
&& chunk_graph.get_number_of_module_chunks(m.identifier()) != 0
24+
})
25+
.map(|m| m.identifier())
26+
.collect()
27+
}
28+
629
pub struct ModuleIdsPass;
730

831
#[async_trait]
@@ -24,6 +47,23 @@ impl PassExt for ModuleIdsPass {
2447
compilation.module_ids_artifact.clear();
2548
}
2649

50+
let mut module_ids_artifact = mem::take(&mut compilation.module_ids_artifact);
51+
52+
// Call beforeModuleIds hook - allows plugins to assign custom IDs
53+
let modules_needing_ids = get_modules_needing_ids(compilation, &module_ids_artifact);
54+
compilation
55+
.plugin_driver
56+
.clone()
57+
.compilation_hooks
58+
.before_module_ids
59+
.call(compilation, &modules_needing_ids, &mut module_ids_artifact)
60+
.await
61+
.map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.beforeModuleIds"))?;
62+
63+
// Put artifact back so moduleIds plugins can see custom IDs from beforeModuleIds
64+
// when they call get_used_module_ids_and_modules
65+
compilation.module_ids_artifact = module_ids_artifact;
66+
2767
let mut diagnostics = vec![];
2868
let mut module_ids_artifact = mem::take(&mut compilation.module_ids_artifact);
2969
compilation

crates/rspack_ids/src/deterministic_module_ids_plugin.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rspack_hook::{plugin, plugin_hook};
99

1010
use crate::id_helpers::{
1111
assign_deterministic_ids, compare_modules_by_pre_order_index_or_identifier, get_full_module_name,
12-
get_used_module_ids_and_modules,
12+
get_used_module_ids_and_modules_with_artifact,
1313
};
1414

1515
#[plugin]
@@ -34,7 +34,8 @@ async fn module_ids(
3434
module_ids.clear();
3535
}
3636

37-
let (mut used_ids, modules) = get_used_module_ids_and_modules(compilation, None);
37+
let (mut used_ids, modules) =
38+
get_used_module_ids_and_modules_with_artifact(compilation, module_ids, None);
3839

3940
let mut module_ids_map = std::mem::take(module_ids);
4041
let context = compilation.options.context.as_ref();

0 commit comments

Comments
 (0)