Skip to content

Commit cb00e50

Browse files
authored
feat: port normal module replacement plugin to builtin plugin (#11362)
1 parent 7cf35cf commit cb00e50

25 files changed

+424
-409
lines changed

Cargo.lock

Lines changed: 16 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,6 @@ rspack_paths = { version = "=0.4.11", path = "crates/r
176176
rspack_plugin_asset = { version = "=0.4.11", path = "crates/rspack_plugin_asset", default-features = false }
177177
rspack_plugin_banner = { version = "=0.4.11", path = "crates/rspack_plugin_banner", default-features = false }
178178
rspack_plugin_circular_dependencies = { version = "=0.4.11", path = "crates/rspack_plugin_circular_dependencies", default-features = false }
179-
rspack_plugin_context_replacement = { version = "=0.4.11", path = "crates/rspack_plugin_context_replacement", default-features = false }
180179
rspack_plugin_copy = { version = "=0.4.11", path = "crates/rspack_plugin_copy", default-features = false }
181180
rspack_plugin_css = { version = "=0.4.11", path = "crates/rspack_plugin_css", default-features = false }
182181
rspack_plugin_css_chunking = { version = "=0.4.11", path = "crates/rspack_plugin_css_chunking", default-features = false }
@@ -199,6 +198,7 @@ rspack_plugin_limit_chunk_count = { version = "=0.4.11", path = "crates/r
199198
rspack_plugin_merge_duplicate_chunks = { version = "=0.4.11", path = "crates/rspack_plugin_merge_duplicate_chunks", default-features = false }
200199
rspack_plugin_mf = { version = "=0.4.11", path = "crates/rspack_plugin_mf", default-features = false }
201200
rspack_plugin_module_info_header = { version = "=0.4.11", path = "crates/rspack_plugin_module_info_header", default-features = false }
201+
rspack_plugin_module_replacement = { version = "=0.4.11", path = "crates/rspack_plugin_module_replacement", default-features = false }
202202
rspack_plugin_no_emit_on_errors = { version = "=0.4.11", path = "crates/rspack_plugin_no_emit_on_errors", default-features = false }
203203
rspack_plugin_progress = { version = "=0.4.11", path = "crates/rspack_plugin_progress", default-features = false }
204204
rspack_plugin_real_content_hash = { version = "=0.4.11", path = "crates/rspack_plugin_real_content_hash", default-features = false }

crates/node_binding/napi-binding.d.ts

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,7 @@ export declare enum BuiltinPluginName {
567567
RuntimeChunkPlugin = 'RuntimeChunkPlugin',
568568
SizeLimitsPlugin = 'SizeLimitsPlugin',
569569
NoEmitOnErrorsPlugin = 'NoEmitOnErrorsPlugin',
570+
NormalModuleReplacementPlugin = 'NormalModuleReplacementPlugin',
570571
ContextReplacementPlugin = 'ContextReplacementPlugin',
571572
DllEntryPlugin = 'DllEntryPlugin',
572573
DllReferenceAgencyPlugin = 'DllReferenceAgencyPlugin',
@@ -598,13 +599,6 @@ export interface ContextInfo {
598599
issuerLayer?: string
599600
}
600601

601-
export interface CssChunkingPluginOptions {
602-
strict?: boolean
603-
minSize?: number
604-
maxSize?: number
605-
exclude?: RegExp
606-
}
607-
608602
export declare enum EnforceExtension {
609603
Auto = 0,
610604
Enabled = 1,
@@ -704,13 +698,6 @@ export interface JsBeforeEmitData {
704698
uid?: number
705699
}
706700

707-
export interface JsBeforeResolveArgs {
708-
request: string
709-
context: string
710-
issuer: string
711-
issuerLayer?: string
712-
}
713-
714701
export interface JsBuildMeta {
715702
strictEsmModule: boolean
716703
hasTopLevelAwait: boolean
@@ -864,13 +851,6 @@ export interface JsExecuteModuleResult {
864851
error?: string
865852
}
866853

867-
export interface JsFactorizeArgs {
868-
request: string
869-
context: string
870-
issuer: string
871-
issuerLayer?: string
872-
}
873-
874854
export interface JsFactoryMeta {
875855
sideEffectFree?: boolean
876856
}
@@ -1022,11 +1002,14 @@ export interface JsPathDataChunkLike {
10221002
id?: string
10231003
}
10241004

1025-
export interface JsResolveArgs {
1005+
export interface JsResolveData {
10261006
request: string
10271007
context: string
1028-
issuer: string
1029-
issuerLayer?: string
1008+
contextInfo: ContextInfo
1009+
fileDependencies: Array<string>
1010+
contextDependencies: Array<string>
1011+
missingDependencies: Array<string>
1012+
createData?: JsCreateData
10301013
}
10311014

10321015
export interface JsResolveForSchemeArgs {
@@ -2006,6 +1989,13 @@ export interface RawCssAutoParserOptions {
20061989
url?: boolean
20071990
}
20081991

1992+
export interface RawCssChunkingPluginOptions {
1993+
strict?: boolean
1994+
minSize?: number
1995+
maxSize?: number
1996+
exclude?: RegExp
1997+
}
1998+
20091999
export interface RawCssExtractPluginOption {
20102000
filename: JsFilename
20112001
chunkFilename: JsFilename
@@ -2516,6 +2506,11 @@ export interface RawNonStandard {
25162506
deepSelectorCombinator: boolean
25172507
}
25182508

2509+
export interface RawNormalModuleReplacementPluginOptions {
2510+
resourceRegExp: RegExp
2511+
newResource: string | ((data: JsResolveData) => JsResolveData)
2512+
}
2513+
25192514
export interface RawOccurrenceChunkIdsPluginOptions {
25202515
prioritiseInitial?: boolean
25212516
}
@@ -2946,11 +2941,11 @@ export interface RegisterJsTaps {
29462941
registerCompilationAfterProcessAssetsTaps: (stages: Array<number>) => Array<{ function: ((arg: JsCompilation) => void); stage: number; }>
29472942
registerCompilationSealTaps: (stages: Array<number>) => Array<{ function: (() => void); stage: number; }>
29482943
registerCompilationAfterSealTaps: (stages: Array<number>) => Array<{ function: (() => Promise<void>); stage: number; }>
2949-
registerNormalModuleFactoryBeforeResolveTaps: (stages: Array<number>) => Array<{ function: ((arg: JsBeforeResolveArgs) => Promise<[boolean | undefined, JsBeforeResolveArgs]>); stage: number; }>
2950-
registerNormalModuleFactoryFactorizeTaps: (stages: Array<number>) => Array<{ function: ((arg: JsFactorizeArgs) => Promise<JsFactorizeArgs>); stage: number; }>
2951-
registerNormalModuleFactoryResolveTaps: (stages: Array<number>) => Array<{ function: ((arg: JsResolveArgs) => Promise<JsResolveArgs>); stage: number; }>
2944+
registerNormalModuleFactoryBeforeResolveTaps: (stages: Array<number>) => Array<{ function: ((arg: JsResolveData) => Promise<[boolean | undefined, JsResolveData]>); stage: number; }>
2945+
registerNormalModuleFactoryFactorizeTaps: (stages: Array<number>) => Array<{ function: ((arg: JsResolveData) => Promise<JsResolveData>); stage: number; }>
2946+
registerNormalModuleFactoryResolveTaps: (stages: Array<number>) => Array<{ function: ((arg: JsResolveData) => Promise<JsResolveData>); stage: number; }>
29522947
registerNormalModuleFactoryResolveForSchemeTaps: (stages: Array<number>) => Array<{ function: ((arg: JsResolveForSchemeArgs) => Promise<[boolean | undefined, JsResolveForSchemeArgs]>); stage: number; }>
2953-
registerNormalModuleFactoryAfterResolveTaps: (stages: Array<number>) => Array<{ function: ((arg: string) => Promise<[boolean | undefined, JsCreateData | undefined]>); stage: number; }>
2948+
registerNormalModuleFactoryAfterResolveTaps: (stages: Array<number>) => Array<{ function: ((arg: JsResolveData) => Promise<[boolean | undefined, JsResolveData]>); stage: number; }>
29542949
registerNormalModuleFactoryCreateModuleTaps: (stages: Array<number>) => Array<{ function: ((arg: JsNormalModuleFactoryCreateModuleArgs) => Promise<void>); stage: number; }>
29552950
registerContextModuleFactoryBeforeResolveTaps: (stages: Array<number>) => Array<{ function: ((arg: false | JsContextModuleFactoryBeforeResolveData) => Promise<false | JsContextModuleFactoryBeforeResolveData>); stage: number; }>
29562951
registerContextModuleFactoryAfterResolveTaps: (stages: Array<number>) => Array<{ function: ((arg: false | JsContextModuleFactoryAfterResolveData) => Promise<false | JsContextModuleFactoryAfterResolveData>); stage: number; }>

crates/rspack_binding_api/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ rspack_napi_macros = { workspace = true }
7373
rspack_plugin_asset = { workspace = true }
7474
rspack_plugin_banner = { workspace = true }
7575
rspack_plugin_circular_dependencies = { workspace = true }
76-
rspack_plugin_context_replacement = { workspace = true }
7776
rspack_plugin_copy = { workspace = true }
7877
rspack_plugin_css = { workspace = true }
7978
rspack_plugin_css_chunking = { workspace = true }
@@ -94,6 +93,7 @@ rspack_plugin_limit_chunk_count = { workspace = true }
9493
rspack_plugin_merge_duplicate_chunks = { workspace = true }
9594
rspack_plugin_mf = { workspace = true }
9695
rspack_plugin_module_info_header = { workspace = true }
96+
rspack_plugin_module_replacement = { workspace = true }
9797
rspack_plugin_no_emit_on_errors = { workspace = true }
9898
rspack_plugin_progress = { workspace = true }
9999
rspack_plugin_real_content_hash = { workspace = true }

crates/rspack_binding_api/src/normal_module_factory.rs

Lines changed: 113 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
use napi::{
2+
Env,
3+
bindgen_prelude::{Object, ToNapiValue},
4+
};
15
use napi_derive::napi;
2-
use rspack_core::NormalModuleCreateData;
6+
use rspack_core::{ModuleFactoryCreateData, NormalModuleCreateData, ResourceData, parse_resource};
37
use serde::Serialize;
48

59
use crate::resource_data::JsResourceData;
@@ -12,37 +16,32 @@ pub struct JsResolveForSchemeArgs {
1216

1317
pub type JsResolveForSchemeOutput = (Option<bool>, JsResourceData);
1418

19+
#[derive(Debug, Clone, Serialize)]
20+
#[serde(rename_all = "camelCase")]
1521
#[napi(object)]
16-
pub struct JsBeforeResolveArgs {
17-
pub request: String,
18-
pub context: String,
19-
pub issuer: String,
20-
pub issuer_layer: Option<String>,
21-
}
22-
23-
pub type JsBeforeResolveOutput = (Option<bool>, JsBeforeResolveArgs);
24-
25-
#[napi(object)]
26-
pub struct JsFactorizeArgs {
27-
pub request: String,
28-
pub context: String,
22+
pub struct ContextInfo {
2923
pub issuer: String,
3024
pub issuer_layer: Option<String>,
3125
}
3226

33-
pub type JsFactorizeOutput = JsFactorizeArgs;
34-
35-
#[napi(object)]
36-
pub struct JsResolveArgs {
37-
pub request: String,
38-
pub context: String,
39-
pub issuer: String,
40-
pub issuer_layer: Option<String>,
27+
impl ToNapiValue for &ContextInfo {
28+
unsafe fn to_napi_value(
29+
env: napi::sys::napi_env,
30+
val: Self,
31+
) -> napi::Result<napi::sys::napi_value> {
32+
unsafe {
33+
let env_wrapper = Env::from(env);
34+
let mut obj = Object::new(&env_wrapper)?;
35+
obj.set("issuer", &val.issuer)?;
36+
if let Some(issuer_layer) = &val.issuer_layer {
37+
obj.set("issuerLayer", issuer_layer)?;
38+
}
39+
ToNapiValue::to_napi_value(env, obj)
40+
}
41+
}
4142
}
4243

43-
pub type JsResolveOutput = JsResolveArgs;
44-
45-
#[derive(Serialize)]
44+
#[derive(Debug, Serialize)]
4645
#[serde(rename_all = "camelCase")]
4746
#[napi(object)]
4847
pub struct JsCreateData {
@@ -51,20 +50,104 @@ pub struct JsCreateData {
5150
pub resource: String,
5251
}
5352

54-
#[derive(Serialize)]
53+
impl From<&NormalModuleCreateData> for JsCreateData {
54+
fn from(value: &NormalModuleCreateData) -> Self {
55+
Self {
56+
request: value.request.to_owned(),
57+
user_request: value.user_request.to_owned(),
58+
resource: value.resource_resolve_data.resource.to_owned(),
59+
}
60+
}
61+
}
62+
63+
impl JsCreateData {
64+
pub fn update_nmf_data(self, create_data: &mut NormalModuleCreateData) {
65+
fn update_resource_data(old_resource_data: &mut ResourceData, new_resource: String) {
66+
if old_resource_data.resource_path.is_some()
67+
&& let Some(parsed) = parse_resource(&new_resource)
68+
{
69+
old_resource_data.set_path(parsed.path);
70+
old_resource_data.set_query_optional(parsed.query);
71+
old_resource_data.set_fragment_optional(parsed.fragment);
72+
}
73+
old_resource_data.set_resource(new_resource);
74+
}
75+
76+
create_data.request = self.request;
77+
create_data.user_request = self.user_request;
78+
if create_data.resource_resolve_data.resource != self.resource {
79+
update_resource_data(&mut create_data.resource_resolve_data, self.resource);
80+
}
81+
}
82+
}
83+
84+
#[derive(Debug, Serialize)]
5585
#[serde(rename_all = "camelCase")]
56-
pub struct JsAfterResolveData {
86+
#[napi(object)]
87+
pub struct JsResolveData {
5788
pub request: String,
5889
pub context: String,
59-
pub issuer: String,
60-
pub issuer_layer: Option<String>,
90+
pub context_info: ContextInfo,
6191
pub file_dependencies: Vec<String>,
6292
pub context_dependencies: Vec<String>,
6393
pub missing_dependencies: Vec<String>,
6494
pub create_data: Option<JsCreateData>,
6595
}
6696

67-
pub type JsAfterResolveOutput = (Option<bool>, Option<JsCreateData>);
97+
impl JsResolveData {
98+
pub fn from_nmf_data(
99+
data: &ModuleFactoryCreateData,
100+
create_data: Option<&NormalModuleCreateData>,
101+
) -> Self {
102+
JsResolveData {
103+
request: data.request.to_string(),
104+
context: data.context.to_string(),
105+
context_info: ContextInfo {
106+
issuer: data
107+
.issuer
108+
.as_ref()
109+
.map(|issuer| issuer.to_string())
110+
.unwrap_or_default(),
111+
issuer_layer: data.issuer_layer.clone(),
112+
},
113+
file_dependencies: data
114+
.file_dependencies
115+
.iter()
116+
.map(|item| item.to_string_lossy().into_owned())
117+
.collect::<Vec<_>>(),
118+
context_dependencies: data
119+
.context_dependencies
120+
.iter()
121+
.map(|item| item.to_string_lossy().into_owned())
122+
.collect::<Vec<_>>(),
123+
missing_dependencies: data
124+
.missing_dependencies
125+
.iter()
126+
.map(|item| item.to_string_lossy().into_owned())
127+
.collect::<Vec<_>>(),
128+
create_data: create_data.map(|create_data| JsCreateData {
129+
request: create_data.request.to_owned(),
130+
user_request: create_data.user_request.to_owned(),
131+
resource: create_data.resource_resolve_data.resource.to_owned(),
132+
}),
133+
}
134+
}
135+
136+
pub fn update_nmf_data(
137+
self,
138+
data: &mut ModuleFactoryCreateData,
139+
create_data: Option<&mut NormalModuleCreateData>,
140+
) {
141+
// only supports update request for now
142+
data.request = self.request;
143+
data.context = self.context.into();
144+
if let Some(new_data) = self.create_data
145+
&& let Some(create_data) = create_data
146+
{
147+
new_data.update_nmf_data(create_data);
148+
}
149+
}
150+
}
68151

69152
#[napi(object)]
70153
pub struct JsNormalModuleFactoryCreateModuleArgs {
@@ -74,13 +157,3 @@ pub struct JsNormalModuleFactoryCreateModuleArgs {
74157
pub context: String,
75158
pub match_resource: Option<String>,
76159
}
77-
78-
impl From<&NormalModuleCreateData> for JsCreateData {
79-
fn from(value: &NormalModuleCreateData) -> Self {
80-
Self {
81-
request: value.request.to_owned(),
82-
user_request: value.user_request.to_owned(),
83-
resource: value.resource_resolve_data.resource.to_owned(),
84-
}
85-
}
86-
}

0 commit comments

Comments
 (0)