Skip to content

Commit

Permalink
refactor: import context dependency param evaluate (#6321)
Browse files Browse the repository at this point in the history
  • Loading branch information
ahabhgk authored Apr 23, 2024
1 parent 000f3b3 commit b6fe628
Show file tree
Hide file tree
Showing 18 changed files with 399 additions and 279 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use rspack_core::{module_raw, parse_resource, AsModuleDependency, ContextDependency};
use rspack_core::{normalize_context, DependencyCategory, DependencyId, DependencyTemplate};
use rspack_core::{module_raw, AsModuleDependency, ContextDependency};
use rspack_core::{ContextOptions, Dependency, TemplateReplaceSource};
use rspack_core::{DependencyCategory, DependencyId, DependencyTemplate};
use rspack_core::{DependencyType, ErrorSpan, TemplateContext};

use super::create_resource_identifier_for_context_dependency;
Expand Down Expand Up @@ -113,34 +113,10 @@ impl DependencyTemplate for ImportContextDependency {
return;
}

source.replace(self.callee_start, self.callee_end, &expr, None);

if !self.replaces.is_empty() {
for (content, start, end) in &self.replaces {
source.replace(*start, *end, content, None);
}
} else {
let context = normalize_context(&self.options.context);
let query = parse_resource(&self.options.request).and_then(|data| data.query);
if !context.is_empty() || query.is_some() {
source.insert(self.callee_end, "(", None);
if !context.is_empty() {
source.insert(
self.args_end,
format!(".replace('{context}', './')").as_str(),
None,
);
}
if let Some(query) = query {
source.insert(
self.args_end,
format!(".replace('{query}', '')").as_str(),
None,
);
}
source.insert(self.args_end, ")", None);
}
for (content, start, end) in &self.replaces {
source.replace(*start, *end - 1, content, None);
}
source.replace(self.callee_start, self.callee_end, &expr, None);
}

fn dependency_id(&self) -> Option<DependencyId> {
Expand Down
312 changes: 121 additions & 191 deletions crates/rspack_plugin_javascript/src/parser_plugin/import_parser_plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ use rspack_core::{
use rspack_core::{ChunkGroupOptions, ContextMode};
use rspack_core::{ContextNameSpaceObject, ContextOptions, DependencyCategory, SpanExt};
use swc_core::common::Spanned;
use swc_core::ecma::ast::{CallExpr, Callee, Expr, Lit};
use swc_core::ecma::atoms::Atom;
use swc_core::ecma::ast::{CallExpr, Callee};

use super::JavascriptParserPlugin;
use crate::dependency::{ImportContextDependency, ImportDependency, ImportEagerDependency};
use crate::visitors::{parse_order_string, scanner_context_module, ContextModuleScanResult};
use crate::visitors::{create_context_dependency, parse_order_string, ContextModuleScanResult};
use crate::webpack_comment::try_extract_webpack_magic_comment;

pub struct ImportParserPlugin;
Expand Down Expand Up @@ -45,203 +44,134 @@ impl JavascriptParserPlugin for ImportParserPlugin {
.map(|o| o.dynamic_import_prefetch)
.and_then(|o| o.get_order());

match dyn_imported.expr.as_ref() {
Expr::Lit(Lit::Str(imported)) => {
let magic_comment_options = try_extract_webpack_magic_comment(
parser.source_file,
&parser.comments,
node.span,
imported.span,
&mut parser.warning_diagnostics,
);
if magic_comment_options
.get_webpack_ignore()
.unwrap_or_default()
{
return None;
}
let mode = magic_comment_options
.get_webpack_mode()
.map(|x| DynamicImportMode::from(x.as_str()));
let chunk_name = magic_comment_options
.get_webpack_chunk_name()
.map(|x| x.to_owned());
let chunk_prefetch = magic_comment_options
.get_webpack_prefetch()
.and_then(|x| parse_order_string(x.as_str()));
let chunk_preload = magic_comment_options
.get_webpack_preload()
.and_then(|x| parse_order_string(x.as_str()));
let span = ErrorSpan::from(node.span);
if matches!(
mode.unwrap_or(dynamic_import_mode),
DynamicImportMode::Eager
) {
let dep = ImportEagerDependency::new(
node.span.real_lo(),
node.span.real_hi(),
imported.value.clone(),
Some(span),
// TODO scan dynamic import referenced exports
None,
);
parser.dependencies.push(Box::new(dep));
return Some(true);
}
let dep = Box::new(ImportDependency::new(
let magic_comment_options = try_extract_webpack_magic_comment(
parser.source_file,
&parser.comments,
node.span,
dyn_imported.expr.span(),
&mut parser.warning_diagnostics,
);
if magic_comment_options
.get_webpack_ignore()
.unwrap_or_default()
{
return None;
}

let mode = magic_comment_options
.get_webpack_mode()
.map(|x| DynamicImportMode::from(x.as_str()));
let chunk_name = magic_comment_options
.get_webpack_chunk_name()
.map(|x| x.to_owned());
let chunk_prefetch = magic_comment_options
.get_webpack_prefetch()
.and_then(|x| parse_order_string(x.as_str()));
let chunk_preload = magic_comment_options
.get_webpack_preload()
.and_then(|x| parse_order_string(x.as_str()));

let param = parser.evaluate_expression(dyn_imported.expr.as_ref());

if param.is_string() {
let span = ErrorSpan::from(node.span);
if matches!(
mode.unwrap_or(dynamic_import_mode),
DynamicImportMode::Eager
) {
let dep = ImportEagerDependency::new(
node.span.real_lo(),
node.span.real_hi(),
imported.value.clone(),
param.string().as_str().into(),
Some(span),
// TODO scan dynamic import referenced exports
None,
));
let mut block = AsyncDependenciesBlock::new(
*parser.module_identifier,
Some(DependencyLocation::new(span.start, span.end)),
None,
vec![dep],
);
block.set_group_options(GroupOptions::ChunkGroup(ChunkGroupOptions::new(
chunk_name,
chunk_preload.or(dynamic_import_preload),
chunk_prefetch.or(dynamic_import_prefetch),
)));
parser.blocks.push(block);
Some(true)
parser.dependencies.push(Box::new(dep));
return Some(true);
}
Expr::Tpl(tpl) if tpl.quasis.len() == 1 => {
let magic_comment_options = try_extract_webpack_magic_comment(
parser.source_file,
&parser.comments,
node.span,
tpl.span,
&mut parser.warning_diagnostics,
);
let mode = magic_comment_options
.get_webpack_mode()
.map(|x| DynamicImportMode::from(x.as_str()));
let chunk_name = magic_comment_options
.get_webpack_chunk_name()
.map(|x| x.to_owned());
let chunk_prefetch = magic_comment_options
.get_webpack_prefetch()
.and_then(|x| parse_order_string(x.as_str()));
let chunk_preload = magic_comment_options
.get_webpack_preload()
.and_then(|x| parse_order_string(x.as_str()));
let request = Atom::from(
tpl
.quasis
.first()
.expect("should have one quasis")
.raw
.to_string(),
);
let span = ErrorSpan::from(node.span);
if matches!(
mode.unwrap_or(dynamic_import_mode),
DynamicImportMode::Eager
) {
let dep = ImportEagerDependency::new(
node.span.real_lo(),
node.span.real_hi(),
request,
Some(span),
// TODO scan dynamic import referenced exports
None,
);
parser.dependencies.push(Box::new(dep));
return Some(true);
}
let dep = Box::new(ImportDependency::new(
node.span.real_lo(),
let dep = Box::new(ImportDependency::new(
node.span.real_lo(),
node.span.real_hi(),
param.string().as_str().into(),
Some(span),
// TODO scan dynamic import referenced exports
None,
));
let mut block = AsyncDependenciesBlock::new(
*parser.module_identifier,
Some(DependencyLocation::new(span.start, span.end)),
None,
vec![dep],
);
block.set_group_options(GroupOptions::ChunkGroup(ChunkGroupOptions::new(
chunk_name,
chunk_preload.or(dynamic_import_preload),
chunk_prefetch.or(dynamic_import_prefetch),
)));
parser.blocks.push(block);
Some(true)
} else {
let ContextModuleScanResult {
context,
reg,
query,
fragment,
replaces,
} = create_context_dependency(&param);
let magic_comment_options = try_extract_webpack_magic_comment(
parser.source_file,
&parser.comments,
node.span,
dyn_imported.span(),
&mut parser.warning_diagnostics,
);
let _mode = magic_comment_options
.get_webpack_mode()
.map(|x| DynamicImportMode::from(x.as_str()));
let chunk_name = magic_comment_options
.get_webpack_chunk_name()
.map(|x| x.to_owned());
let chunk_prefetch = magic_comment_options
.get_webpack_prefetch()
.and_then(|x| parse_order_string(x.as_str()));
let chunk_preload = magic_comment_options
.get_webpack_preload()
.and_then(|x| parse_order_string(x.as_str()));
parser
.dependencies
.push(Box::new(ImportContextDependency::new(
import_call.span.real_lo(),
import_call.span.real_hi(),
node.span.real_hi(),
request,
Some(span),
None,
));
let mut block = AsyncDependenciesBlock::new(
*parser.module_identifier,
Some(DependencyLocation::new(span.start, span.end)),
None,
vec![dep],
);
block.set_group_options(GroupOptions::ChunkGroup(ChunkGroupOptions::new(
chunk_name,
chunk_preload.or(dynamic_import_preload),
chunk_prefetch.or(dynamic_import_prefetch),
)));
parser.blocks.push(block);
// FIXME: align `parser.walk_expression` to webpack, which put into `context_dependency_helper`
parser.walk_template_expression(tpl);
Some(true)
}
_ => {
let Some(ContextModuleScanResult {
context,
reg,
query,
fragment,
replaces,
}) = scanner_context_module(dyn_imported.expr.as_ref())
else {
return None;
};
let magic_comment_options = try_extract_webpack_magic_comment(
parser.source_file,
&parser.comments,
node.span,
dyn_imported.span(),
&mut parser.warning_diagnostics,
);
let _mode = magic_comment_options
.get_webpack_mode()
.map(|x| DynamicImportMode::from(x.as_str()));
let chunk_name = magic_comment_options
.get_webpack_chunk_name()
.map(|x| x.to_owned());
let chunk_prefetch = magic_comment_options
.get_webpack_prefetch()
.and_then(|x| parse_order_string(x.as_str()));
let chunk_preload = magic_comment_options
.get_webpack_preload()
.and_then(|x| parse_order_string(x.as_str()));
parser
.dependencies
.push(Box::new(ImportContextDependency::new(
import_call.span.real_lo(),
import_call.span.real_hi(),
node.span.real_hi(),
ContextOptions {
mode: ContextMode::Lazy,
recursive: true,
reg_exp: context_reg_exp(&reg, ""),
include: None,
exclude: None,
category: DependencyCategory::Esm,
request: format!("{}{}{}", context.clone(), query, fragment),
context,
namespace_object: if parser.build_meta.strict_harmony_module {
ContextNameSpaceObject::Strict
} else {
ContextNameSpaceObject::Bool(true)
},
group_options: Some(GroupOptions::ChunkGroup(ChunkGroupOptions::new(
chunk_name,
chunk_preload.or(dynamic_import_preload),
chunk_prefetch.or(dynamic_import_prefetch),
))),
start: node.span().real_lo(),
end: node.span().real_hi(),
ContextOptions {
mode: ContextMode::Lazy,
recursive: true,
reg_exp: context_reg_exp(&reg, ""),
include: None,
exclude: None,
category: DependencyCategory::Esm,
request: format!("{}{}{}", context.clone(), query, fragment),
context,
namespace_object: if parser.build_meta.strict_harmony_module {
ContextNameSpaceObject::Strict
} else {
ContextNameSpaceObject::Bool(true)
},
replaces,
Some(node.span.into()),
)));
// FIXME: align `parser.walk_expression` to webpack, which put into `context_dependency_helper`
parser.walk_expression(&dyn_imported.expr);
Some(true)
}
group_options: Some(GroupOptions::ChunkGroup(ChunkGroupOptions::new(
chunk_name,
chunk_preload.or(dynamic_import_preload),
chunk_prefetch.or(dynamic_import_prefetch),
))),
start: node.span().real_lo(),
end: node.span().real_hi(),
},
replaces,
Some(node.span.into()),
)));
// FIXME: align `parser.walk_expression` to webpack, which put into `context_dependency_helper`
parser.walk_expression(&dyn_imported.expr);
Some(true)
}
}
}
Loading

2 comments on commit b6fe628

@rspack-bot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Ran ecosystem CI: Open

suite result
modernjs, self-hosted, Linux, ci ❌ failure
_selftest, ubuntu-latest ✅ success
nx, ubuntu-latest ✅ success
rspress, ubuntu-latest ✅ success
rsbuild, ubuntu-latest ✅ success
compat, ubuntu-latest ✅ success
examples, ubuntu-latest ✅ success

@rspack-bot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Benchmark detail: Open

Name Base (2024-04-23 81c41c8) Current Change
10000_development-mode + exec 2.69 s ± 45 ms 2.7 s ± 34 ms +0.39 %
10000_development-mode_hmr + exec 682 ms ± 2.6 ms 698 ms ± 4.6 ms +2.28 %
10000_production-mode + exec 2.5 s ± 29 ms 2.57 s ± 23 ms +2.63 %
arco-pro_development-mode + exec 2.51 s ± 77 ms 2.46 s ± 72 ms -2.16 %
arco-pro_development-mode_hmr + exec 430 ms ± 2 ms 429 ms ± 2.6 ms -0.08 %
arco-pro_development-mode_hmr_intercept-plugin + exec 441 ms ± 4.3 ms 441 ms ± 3.9 ms -0.04 %
arco-pro_development-mode_intercept-plugin + exec 3.21 s ± 65 ms 3.29 s ± 116 ms +2.67 %
arco-pro_production-mode + exec 3.95 s ± 87 ms 4.03 s ± 84 ms +2.14 %
arco-pro_production-mode_intercept-plugin + exec 4.69 s ± 55 ms 4.85 s ± 108 ms +3.42 %
threejs_development-mode_10x + exec 2.06 s ± 20 ms 2.08 s ± 42 ms +0.70 %
threejs_development-mode_10x_hmr + exec 748 ms ± 8.2 ms 749 ms ± 13 ms +0.19 %
threejs_production-mode_10x + exec 5.15 s ± 49 ms 5.26 s ± 42 ms +2.02 %

Please sign in to comment.