From 1dc3f29b9f22de4a9f62492a931685ffe75c54ed Mon Sep 17 00:00:00 2001 From: sorrycc Date: Fri, 12 Jul 2024 17:51:54 +0800 Subject: [PATCH] fix: support dynamic import with template string --- crates/mako/src/build/transform.rs | 2 + .../import_template_to_string_literal.rs | 40 +++++++++++++++++++ crates/mako/src/visitors/mod.rs | 1 + .../expect.js | 8 ++++ .../foo.js | 1 + .../index.js | 1 + .../mako.config.json | 11 +++++ 7 files changed, 64 insertions(+) create mode 100644 crates/mako/src/visitors/import_template_to_string_literal.rs create mode 100644 e2e/fixtures/javascript.dynamic-import.template-string/expect.js create mode 100644 e2e/fixtures/javascript.dynamic-import.template-string/foo.js create mode 100644 e2e/fixtures/javascript.dynamic-import.template-string/index.js create mode 100644 e2e/fixtures/javascript.dynamic-import.template-string/mako.config.json diff --git a/crates/mako/src/build/transform.rs b/crates/mako/src/build/transform.rs index 8c5948e94..b9eae25da 100644 --- a/crates/mako/src/build/transform.rs +++ b/crates/mako/src/build/transform.rs @@ -33,6 +33,7 @@ use crate::visitors::dynamic_import_to_require::DynamicImportToRequire; use crate::visitors::env_replacer::{build_env_map, EnvReplacer}; use crate::visitors::fix_helper_inject_position::FixHelperInjectPosition; use crate::visitors::fix_symbol_conflict::FixSymbolConflict; +use crate::visitors::import_template_to_string_literal::ImportTemplateToStringLiteral; use crate::visitors::new_url_assets::NewUrlAssets; use crate::visitors::provide::Provide; use crate::visitors::react::react; @@ -141,6 +142,7 @@ impl Transform { })); // TODO: move ContextModuleVisitor out of plugin visitors.push(Box::new(ContextModuleVisitor { unresolved_mark })); + visitors.push(Box::new(ImportTemplateToStringLiteral {})); // DynamicImportToRequire must be after ContextModuleVisitor // since ContextModuleVisitor will add extra dynamic imports if context.config.dynamic_import_to_require { diff --git a/crates/mako/src/visitors/import_template_to_string_literal.rs b/crates/mako/src/visitors/import_template_to_string_literal.rs new file mode 100644 index 000000000..785ee0d24 --- /dev/null +++ b/crates/mako/src/visitors/import_template_to_string_literal.rs @@ -0,0 +1,40 @@ +use swc_core::ecma::ast::{CallExpr, Callee, Expr, Lit}; +use swc_core::ecma::visit::VisitMut; + +pub struct ImportTemplateToStringLiteral {} + +impl VisitMut for ImportTemplateToStringLiteral { + fn visit_mut_call_expr(&mut self, n: &mut CallExpr) { + if matches!(n.callee, Callee::Import(_)) && n.args.len() == 1 { + if let box Expr::Tpl(tpl) = &n.args[0].expr { + if tpl.exprs.is_empty() && tpl.quasis.len() == 1 { + let s: String = tpl.quasis[0].raw.clone().to_string(); + n.args[0].expr = Expr::Lit(Lit::Str(s.into())).into(); + } + } + } + } +} + +#[cfg(test)] +mod tests { + use swc_core::common::GLOBALS; + use swc_core::ecma::visit::VisitMutWith; + + use crate::ast::tests::TestUtils; + + #[test] + fn test_normal() { + assert_eq!(run(r#"import(`a`)"#), r#"import("a");"#); + } + + fn run(js_code: &str) -> String { + let mut test_utils = TestUtils::gen_js_ast(js_code); + let ast = test_utils.ast.js_mut(); + GLOBALS.set(&test_utils.context.meta.script.globals, || { + let mut visitor = super::ImportTemplateToStringLiteral {}; + ast.ast.visit_mut_with(&mut visitor); + }); + test_utils.js_ast_to_code() + } +} diff --git a/crates/mako/src/visitors/mod.rs b/crates/mako/src/visitors/mod.rs index ded9cecef..042a4233f 100644 --- a/crates/mako/src/visitors/mod.rs +++ b/crates/mako/src/visitors/mod.rs @@ -13,6 +13,7 @@ pub(crate) mod dynamic_import_to_require; pub(crate) mod env_replacer; pub(crate) mod fix_helper_inject_position; pub(crate) mod fix_symbol_conflict; +pub(crate) mod import_template_to_string_literal; pub(crate) mod mako_require; pub(crate) mod meta_url_replacer; pub(crate) mod new_url_assets; diff --git a/e2e/fixtures/javascript.dynamic-import.template-string/expect.js b/e2e/fixtures/javascript.dynamic-import.template-string/expect.js new file mode 100644 index 000000000..a1400c2de --- /dev/null +++ b/e2e/fixtures/javascript.dynamic-import.template-string/expect.js @@ -0,0 +1,8 @@ +const { + parseBuildResult, +} = require("../../../scripts/test-utils"); +const assert = require("assert"); +const { files } = parseBuildResult(__dirname); +const content = files["index.js"]; + +assert(content.includes(`"foo.js": "foo_js-async.js"`), "template string replace works"); diff --git a/e2e/fixtures/javascript.dynamic-import.template-string/foo.js b/e2e/fixtures/javascript.dynamic-import.template-string/foo.js new file mode 100644 index 000000000..81afa3157 --- /dev/null +++ b/e2e/fixtures/javascript.dynamic-import.template-string/foo.js @@ -0,0 +1 @@ +console.log('foo'); diff --git a/e2e/fixtures/javascript.dynamic-import.template-string/index.js b/e2e/fixtures/javascript.dynamic-import.template-string/index.js new file mode 100644 index 000000000..d35d94d10 --- /dev/null +++ b/e2e/fixtures/javascript.dynamic-import.template-string/index.js @@ -0,0 +1 @@ +import(`./foo`) diff --git a/e2e/fixtures/javascript.dynamic-import.template-string/mako.config.json b/e2e/fixtures/javascript.dynamic-import.template-string/mako.config.json new file mode 100644 index 000000000..04f89f349 --- /dev/null +++ b/e2e/fixtures/javascript.dynamic-import.template-string/mako.config.json @@ -0,0 +1,11 @@ +{ + "entry": { + "index": "./index.js" + }, + "optimization": { + "skipModules": false, + "concatenateModules": false + }, + "platform": "node", + "chunkLoadingGlobal": "dynamic_import_async_module" +}