Skip to content

Commit

Permalink
feat: support resource query in context module (#5476)
Browse files Browse the repository at this point in the history
* feat: support resource query in context module

* fix: update

---------

Co-authored-by: LingyuCoder <[email protected]>
  • Loading branch information
faga295 and LingyuCoder authored Feb 9, 2024
1 parent d436941 commit f56fff5
Show file tree
Hide file tree
Showing 10 changed files with 495 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use rspack_core::{module_raw, AsModuleDependency, ContextDependency};
use rspack_core::{module_raw, parse_resource, AsModuleDependency, ContextDependency};
use rspack_core::{normalize_context, DependencyCategory, DependencyId, DependencyTemplate};
use rspack_core::{ContextOptions, Dependency, TemplateReplaceSource};
use rspack_core::{DependencyType, ErrorSpan, TemplateContext};
Expand Down Expand Up @@ -113,13 +113,22 @@ impl DependencyTemplate for CommonJsRequireContextDependency {
source.replace(self.callee_start, self.callee_end, &expr, None);

let context = normalize_context(&self.options.request);
let query = parse_resource(&self.options.request).and_then(|data| data.query);
if !context.is_empty() {
source.insert(self.callee_end, "(", None);
source.insert(
self.args_end,
format!(".replace('{context}', './'))").as_str(),
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);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use rspack_core::{module_raw, AsModuleDependency, ContextDependency};
use rspack_core::{module_raw, parse_resource, AsModuleDependency, ContextDependency};
use rspack_core::{normalize_context, DependencyCategory, DependencyId, DependencyTemplate};
use rspack_core::{ContextOptions, Dependency, TemplateReplaceSource};
use rspack_core::{DependencyType, ErrorSpan, TemplateContext};
Expand Down Expand Up @@ -113,13 +113,22 @@ impl DependencyTemplate for ImportContextDependency {
source.replace(self.callee_start, self.callee_end, &expr, None);

let context = normalize_context(&self.options.request);
let query = parse_resource(&self.options.request).and_then(|data| data.query);
if !context.is_empty() {
source.insert(self.callee_end, "(", None);
source.insert(
self.args_end,
format!(".replace('{context}', './'))").as_str(),
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);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ use crate::dependency::RequireHeaderDependency;
use crate::dependency::{CommonJsFullRequireDependency, CommonJsRequireContextDependency};
use crate::dependency::{CommonJsRequireDependency, RequireResolveDependency};
use crate::utils::eval::{self, BasicEvaluatedExpression};
use crate::visitors::{expr_matcher, scanner_context_module, JavascriptParser};
use crate::visitors::{
expr_matcher, scanner_context_module, ContextModuleScanResult, JavascriptParser,
};
use crate::visitors::{extract_require_call_info, is_require_call_start};

pub const COMMONJS_REQUIRE: &str = "require";
Expand Down Expand Up @@ -311,7 +313,12 @@ impl JavascriptParserPlugin for CommonJsImportsParserPlugin {
&& let Some(expr) = call_expr.args.first()
&& call_expr.args.len() == 1
&& expr.spread.is_none()
&& let Some((context, reg)) = scanner_context_module(expr.expr.as_ref())
&& let Some(ContextModuleScanResult {
context,
reg,
query,
fragment,
}) = scanner_context_module(expr.expr.as_ref())
{
// `require.resolve`
parser
Expand All @@ -329,7 +336,7 @@ impl JavascriptParserPlugin for CommonJsImportsParserPlugin {
include: None,
exclude: None,
category: DependencyCategory::CommonJS,
request: context,
request: format!("{}{}{}", context, query, fragment),
namespace_object: ContextNameSpaceObject::Unset,
},
Some(call_expr.span.into()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use swc_core::ecma::atoms::Atom;

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

pub struct ImportParserPlugin;
Expand Down Expand Up @@ -150,7 +150,13 @@ impl JavascriptParserPlugin for ImportParserPlugin {
Some(true)
}
_ => {
let Some((context, reg)) = scanner_context_module(dyn_imported.expr.as_ref()) else {
let Some(ContextModuleScanResult {
context,
reg,
query,
fragment,
}) = scanner_context_module(dyn_imported.expr.as_ref())
else {
return None;
};
let magic_comment_options = try_extract_webpack_magic_comment(
Expand Down Expand Up @@ -178,7 +184,7 @@ impl JavascriptParserPlugin for ImportParserPlugin {
include: None,
exclude: None,
category: DependencyCategory::Esm,
request: context,
request: format!("{}{}{}", context, query, fragment),
namespace_object: if parser.build_meta.strict_harmony_module {
ContextNameSpaceObject::Strict
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use once_cell::sync::Lazy;
use regex::Regex;
use rspack_core::parse_resource;
use swc_core::ecma::ast::{
BinExpr, BinaryOp, CallExpr, Callee, Expr, Lit, MemberProp, TaggedTpl, Tpl,
};
Expand All @@ -9,6 +10,13 @@ enum TemplateStringKind {
Cooked,
}

pub struct ContextModuleScanResult {
pub context: String,
pub reg: String,
pub query: String,
pub fragment: String,
}

#[inline]
fn split_context_from_prefix(prefix: String) -> (String, String) {
if let Some(idx) = prefix.rfind('/') {
Expand All @@ -18,7 +26,7 @@ fn split_context_from_prefix(prefix: String) -> (String, String) {
}
}

pub fn scanner_context_module(expr: &Expr) -> Option<(String, String)> {
pub fn scanner_context_module(expr: &Expr) -> Option<ContextModuleScanResult> {
match expr {
Expr::Tpl(tpl) if !tpl.exprs.is_empty() => {
Some(scan_context_module_tpl(tpl, TemplateStringKind::Cooked))
Expand All @@ -40,7 +48,7 @@ fn quote_meta(str: String) -> String {
}

// require(`./${a}.js`)
fn scan_context_module_tpl(tpl: &Tpl, kind: TemplateStringKind) -> (String, String) {
fn scan_context_module_tpl(tpl: &Tpl, kind: TemplateStringKind) -> ContextModuleScanResult {
let prefix_raw = tpl
.quasis
.first()
Expand Down Expand Up @@ -73,16 +81,31 @@ fn scan_context_module_tpl(tpl: &Tpl, kind: TemplateStringKind) -> (String, Stri
})
.collect::<Vec<String>>()
.join("");

let (postfix, query, fragment) = match parse_resource(&postfix_raw) {
Some(data) => (
data.path.to_string_lossy().to_string(),
data.query.unwrap_or_default(),
data.fragment.unwrap_or_default(),
),
None => (postfix_raw, String::new(), String::new()),
};

let reg = format!(
"^{prefix}.*{inner_reg}{postfix_raw}$",
prefix = quote_meta(prefix),
postfix_raw = quote_meta(postfix_raw)
postfix_raw = quote_meta(postfix)
);
(context, reg)
ContextModuleScanResult {
context,
reg,
query,
fragment,
}
}

// require("./" + a + ".js")
fn scan_context_module_bin(bin: &BinExpr) -> Option<(String, String)> {
fn scan_context_module_bin(bin: &BinExpr) -> Option<ContextModuleScanResult> {
if !is_add_op_bin_expr(bin) {
return None;
}
Expand All @@ -102,13 +125,28 @@ fn scan_context_module_bin(bin: &BinExpr) -> Option<(String, String)> {
}

let (context, prefix) = split_context_from_prefix(prefix_raw);

let (postfix, query, fragment) = match parse_resource(&postfix_raw) {
Some(data) => (
data.path.to_string_lossy().to_string(),
data.query.unwrap_or_default(),
data.fragment.unwrap_or_default(),
),
None => (postfix_raw, String::new(), String::new()),
};

let reg = format!(
"^{prefix}.*{postfix_raw}$",
prefix = quote_meta(prefix),
postfix_raw = quote_meta(postfix_raw)
postfix_raw = quote_meta(postfix)
);

Some((context, reg))
Some(ContextModuleScanResult {
context,
reg,
query,
fragment,
})
}

fn find_expr_prefix_string(expr: &Expr) -> Option<String> {
Expand All @@ -133,7 +171,7 @@ fn is_add_op_bin_expr(bin: &BinExpr) -> bool {
// require("./".concat(a, ".js"))
// babel/swc will transform template literal to string concat, so we need to handle this case
// see https://github.com/webpack/webpack/pull/5679
fn scan_context_module_concat_call(expr: &CallExpr) -> Option<(String, String)> {
fn scan_context_module_concat_call(expr: &CallExpr) -> Option<ContextModuleScanResult> {
if !is_concat_call(expr) {
return None;
}
Expand All @@ -153,17 +191,30 @@ fn scan_context_module_concat_call(expr: &CallExpr) -> Option<(String, String)>
}

let (context, prefix) = split_context_from_prefix(prefix_raw);
let (postfix, query, fragment) = match parse_resource(&postfix_raw) {
Some(data) => (
data.path.to_string_lossy().to_string(),
data.query.unwrap_or_default(),
data.fragment.unwrap_or_default(),
),
None => (postfix_raw, String::new(), String::new()),
};
let reg = format!(
"^{prefix}.*{postfix_raw}$",
prefix = quote_meta(prefix),
postfix_raw = quote_meta(postfix_raw)
postfix_raw = quote_meta(postfix)
);

Some((context, reg))
Some(ContextModuleScanResult {
context,
reg,
query,
fragment,
})
}

// require(String.raw`./${a}.js`)
fn scan_context_module_tagged_tpl(tpl: &TaggedTpl) -> (String, String) {
fn scan_context_module_tagged_tpl(tpl: &TaggedTpl) -> ContextModuleScanResult {
match tpl.tag.as_member() {
Some(tag)
if tag
Expand All @@ -179,7 +230,12 @@ fn scan_context_module_tagged_tpl(tpl: &TaggedTpl) -> (String, String) {
{
scan_context_module_tpl(tpl.tpl.as_ref(), TemplateStringKind::Raw)
}
_ => (String::from("."), String::new()),
_ => ContextModuleScanResult {
context: String::from("."),
reg: String::new(),
query: String::new(),
fragment: String::new(),
},
}
}

Expand Down
Loading

1 comment on commit f56fff5

@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-02-09 d436941) Current Change
10000_development-mode + exec 1.72 s ± 27 ms 1.68 s ± 48 ms -1.80 %
10000_development-mode_hmr + exec 916 ms ± 4.8 ms 913 ms ± 21 ms -0.41 %
10000_production-mode + exec 2.73 s ± 36 ms 2.61 s ± 16 ms -4.63 %
arco-pro_development-mode + exec 2.67 s ± 41 ms 2.64 s ± 29 ms -1.23 %
arco-pro_development-mode_hmr + exec 1.06 s ± 10 ms 1.06 s ± 22 ms -0.28 %
arco-pro_production-mode + exec 4.32 s ± 50 ms 4.22 s ± 50 ms -2.41 %
threejs_development-mode_10x + exec 1.89 s ± 35 ms 1.88 s ± 19 ms -0.83 %
threejs_development-mode_10x_hmr + exec 1.13 s ± 6.7 ms 1.12 s ± 8.9 ms -0.61 %
threejs_production-mode_10x + exec 5.61 s ± 35 ms 5.59 s ± 25 ms -0.20 %

Please sign in to comment.