Skip to content

Commit 7b9117f

Browse files
authored
feat: port "module-import" external type (#7479)
1 parent e6c8b93 commit 7b9117f

File tree

12 files changed

+358
-86
lines changed

12 files changed

+358
-86
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/rspack_core/src/external_module.rs

Lines changed: 103 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,29 @@ pub struct ExternalModule {
129129
factory_meta: Option<FactoryMeta>,
130130
build_info: Option<BuildInfo>,
131131
build_meta: Option<BuildMeta>,
132+
dependency_meta: DependencyMeta,
133+
}
134+
135+
#[derive(Debug)]
136+
pub enum ExternalTypeEnum {
137+
Import,
138+
Module,
139+
}
140+
141+
pub type MetaExternalType = Option<ExternalTypeEnum>;
142+
143+
#[derive(Debug)]
144+
pub struct DependencyMeta {
145+
pub external_type: MetaExternalType,
132146
}
133147

134148
impl ExternalModule {
135-
pub fn new(request: ExternalRequest, external_type: ExternalType, user_request: String) -> Self {
149+
pub fn new(
150+
request: ExternalRequest,
151+
external_type: ExternalType,
152+
user_request: String,
153+
dependency_meta: DependencyMeta,
154+
) -> Self {
136155
Self {
137156
dependencies: Vec::new(),
138157
blocks: Vec::new(),
@@ -147,6 +166,7 @@ impl ExternalModule {
147166
build_info: None,
148167
build_meta: None,
149168
source_map_kind: SourceMapKind::empty(),
169+
dependency_meta,
150170
}
151171
}
152172

@@ -170,6 +190,7 @@ impl ExternalModule {
170190
) -> Result<(BoxSource, ChunkInitFragments, RuntimeGlobals)> {
171191
let mut chunk_init_fragments: ChunkInitFragments = Default::default();
172192
let mut runtime_requirements: RuntimeGlobals = Default::default();
193+
173194
let source = match self.external_type.as_str() {
174195
"this" if let Some(request) = request => format!(
175196
"{} = (function() {{ return {}; }}());",
@@ -234,52 +255,62 @@ impl ExternalModule {
234255
to_identifier(id)
235256
)
236257
}
237-
"import" if let Some(request) = request => format!(
238-
"{} = {};",
239-
get_namespace_object_export(concatenation_scope),
240-
get_source_for_import(request, compilation)
241-
),
258+
"module" | "import" | "module-import" if let Some(request) = request => {
259+
match self.get_module_import_type(external_type) {
260+
"import" => {
261+
format!(
262+
"{} = {};",
263+
get_namespace_object_export(concatenation_scope),
264+
get_source_for_import(request, compilation)
265+
)
266+
}
267+
"module" => {
268+
if compilation.options.output.module {
269+
let id = to_identifier(&request.primary);
270+
chunk_init_fragments.push(
271+
NormalInitFragment::new(
272+
format!(
273+
"import * as __WEBPACK_EXTERNAL_MODULE_{}__ from {};\n",
274+
id.clone(),
275+
json_stringify(request.primary())
276+
),
277+
InitFragmentStage::StageHarmonyImports,
278+
0,
279+
InitFragmentKey::ExternalModule(request.primary().into()),
280+
None,
281+
)
282+
.boxed(),
283+
);
284+
runtime_requirements.insert(RuntimeGlobals::DEFINE_PROPERTY_GETTERS);
285+
format!(
286+
r#"
287+
var x = y => {{ var x = {{}}; {}(x, y); return x; }}
288+
var y = x => () => x
289+
{} = __WEBPACK_EXTERNAL_MODULE_{}__;
290+
"#,
291+
RuntimeGlobals::DEFINE_PROPERTY_GETTERS,
292+
get_namespace_object_export(concatenation_scope),
293+
id.clone()
294+
)
295+
} else {
296+
format!(
297+
"{} = {};",
298+
get_namespace_object_export(concatenation_scope),
299+
get_source_for_import(request, compilation)
300+
)
301+
}
302+
}
303+
r#type => panic!(
304+
"Unhandled external type: {} in \"module-import\" type",
305+
r#type
306+
),
307+
}
308+
}
242309
"var" | "promise" | "const" | "let" | "assign" if let Some(request) = request => format!(
243310
"{} = {};",
244311
get_namespace_object_export(concatenation_scope),
245312
get_source_for_default_case(false, request)
246313
),
247-
"module" if let Some(request) = request => {
248-
if compilation.options.output.module {
249-
let id = to_identifier(&request.primary);
250-
chunk_init_fragments.push(
251-
NormalInitFragment::new(
252-
format!(
253-
"import * as __WEBPACK_EXTERNAL_MODULE_{}__ from {};\n",
254-
id.clone(),
255-
json_stringify(request.primary())
256-
),
257-
InitFragmentStage::StageHarmonyImports,
258-
0,
259-
InitFragmentKey::ExternalModule(request.primary().into()),
260-
None,
261-
)
262-
.boxed(),
263-
);
264-
runtime_requirements.insert(RuntimeGlobals::DEFINE_PROPERTY_GETTERS);
265-
format!(
266-
r#"
267-
var x = y => {{ var x = {{}}; {}(x, y); return x; }}
268-
var y = x => () => x
269-
{} = __WEBPACK_EXTERNAL_MODULE_{}__;
270-
"#,
271-
RuntimeGlobals::DEFINE_PROPERTY_GETTERS,
272-
get_namespace_object_export(concatenation_scope),
273-
id.clone()
274-
)
275-
} else {
276-
format!(
277-
"{} = {};",
278-
get_namespace_object_export(concatenation_scope),
279-
get_source_for_import(request, compilation)
280-
)
281-
}
282-
}
283314
"script" if let Some(request) = request => {
284315
let url_and_global = extract_url_and_global(request.primary())?;
285316
runtime_requirements.insert(RuntimeGlobals::LOAD_SCRIPT);
@@ -316,6 +347,24 @@ if(typeof {global} !== "undefined") return resolve();
316347
runtime_requirements,
317348
))
318349
}
350+
351+
fn get_module_import_type<'a>(&self, external_type: &'a ExternalType) -> &'a str {
352+
match external_type.as_str() {
353+
"module-import" => {
354+
let external_type = self
355+
.dependency_meta
356+
.external_type
357+
.as_ref()
358+
.expect("should get \"module\" or \"import\" external type from dependency");
359+
360+
match external_type {
361+
ExternalTypeEnum::Import => "import",
362+
ExternalTypeEnum::Module => "module",
363+
}
364+
}
365+
import_or_module => import_or_module,
366+
}
367+
}
319368
}
320369

321370
impl Identifiable for ExternalModule {
@@ -412,6 +461,7 @@ impl Module for ExternalModule {
412461
) -> Result<BuildResult> {
413462
let mut hasher = RspackHash::from(&build_context.compiler_options.output);
414463
self.update_hash(&mut hasher);
464+
let (_, external_type) = self.get_request_and_external_type();
415465

416466
let build_info = BuildInfo {
417467
hash: Some(hasher.digest(&build_context.compiler_options.output.hash_digest)),
@@ -431,12 +481,18 @@ impl Module for ExternalModule {
431481
match self.external_type.as_str() {
432482
"this" => build_result.build_info.strict = false,
433483
"system" => build_result.build_meta.exports_type = BuildMetaExportsType::Namespace,
434-
"module" => build_result.build_meta.exports_type = BuildMetaExportsType::Namespace,
435484
"script" | "promise" => build_result.build_meta.has_top_level_await = true,
436-
"import" => {
437-
build_result.build_meta.has_top_level_await = true;
438-
build_result.build_meta.exports_type = BuildMetaExportsType::Namespace;
439-
}
485+
"module" | "import" | "module-import" => match self.get_module_import_type(external_type) {
486+
"module" => build_result.build_meta.exports_type = BuildMetaExportsType::Namespace,
487+
"import" => {
488+
build_result.build_meta.has_top_level_await = true;
489+
build_result.build_meta.exports_type = BuildMetaExportsType::Namespace;
490+
}
491+
r#type => panic!(
492+
"Unhandled external type: {} in \"module-import\" type",
493+
r#type
494+
),
495+
},
440496
_ => build_result.build_meta.exports_type = BuildMetaExportsType::Dynamic,
441497
}
442498
build_result

crates/rspack_plugin_externals/Cargo.toml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ version = "0.1.0"
88
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
99

1010
[dependencies]
11-
regex = { workspace = true }
12-
rspack_core = { path = "../rspack_core" }
13-
rspack_error = { path = "../rspack_error" }
14-
rspack_hook = { path = "../rspack_hook" }
15-
rspack_regex = { path = "../rspack_regex" }
16-
tracing = { workspace = true }
11+
regex = { workspace = true }
12+
rspack_core = { path = "../rspack_core" }
13+
rspack_error = { path = "../rspack_error" }
14+
rspack_hook = { path = "../rspack_hook" }
15+
rspack_plugin_javascript = { path = "../rspack_plugin_javascript" }
16+
rspack_regex = { path = "../rspack_regex" }
17+
tracing = { workspace = true }
1718

1819
[package.metadata.cargo-shear]
1920
ignored = ["tracing"]

crates/rspack_plugin_externals/src/plugin.rs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ use std::sync::LazyLock;
33

44
use regex::Regex;
55
use rspack_core::{
6-
ApplyContext, BoxModule, CompilerOptions, ContextInfo, ExternalItem, ExternalItemFnCtx,
7-
ExternalItemValue, ExternalModule, ExternalRequest, ExternalRequestValue, ExternalType,
8-
ModuleDependency, ModuleExt, ModuleFactoryCreateData, NormalModuleFactoryFactorize, Plugin,
9-
PluginContext,
6+
ApplyContext, BoxModule, CompilerOptions, ContextInfo, DependencyMeta, ExternalItem,
7+
ExternalItemFnCtx, ExternalItemValue, ExternalModule, ExternalRequest, ExternalRequestValue,
8+
ExternalType, ExternalTypeEnum, ModuleDependency, ModuleExt, ModuleFactoryCreateData,
9+
NormalModuleFactoryFactorize, Plugin, PluginContext,
1010
};
1111
use rspack_error::Result;
1212
use rspack_hook::{plugin, plugin_hook};
13+
use rspack_plugin_javascript::dependency::{HarmonyImportSideEffectDependency, ImportDependency};
1314

1415
static UNSPECIFIED_EXTERNAL_TYPE_REGEXP: LazyLock<Regex> =
1516
LazyLock::new(|| Regex::new(r"^[a-z0-9-]+ ").expect("Invalid regex"));
@@ -101,10 +102,31 @@ impl ExternalsPlugin {
101102
None
102103
}
103104

105+
let dependency_meta: DependencyMeta = DependencyMeta {
106+
external_type: {
107+
if dependency
108+
.as_any()
109+
.downcast_ref::<ImportDependency>()
110+
.is_some()
111+
{
112+
Some(ExternalTypeEnum::Import)
113+
} else if dependency
114+
.as_any()
115+
.downcast_ref::<HarmonyImportSideEffectDependency>()
116+
.is_some()
117+
{
118+
Some(ExternalTypeEnum::Module)
119+
} else {
120+
None
121+
}
122+
},
123+
};
124+
104125
Some(ExternalModule::new(
105126
external_module_config,
106127
r#type.unwrap_or(external_module_type),
107128
dependency.request().to_owned(),
129+
dependency_meta,
108130
))
109131
}
110132
}

packages/rspack-test-tools/tests/defaultsCases/experiments/output-module.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ module.exports = {
1111
+ "outputModule": true,
1212
@@ ... @@
1313
- "externalsType": "var",
14-
+ "externalsType": "module",
14+
+ "externalsType": "module-import",
1515
@@ ... @@
1616
- "dynamicImport": undefined,
1717
- "dynamicImportInWorker": undefined,

0 commit comments

Comments
 (0)