From 41431ad20bf6c39d60a32b0de625ef4d04dacd3e Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Fri, 17 Dec 2021 16:00:36 +0100 Subject: [PATCH 1/2] drop dynamic import with `ssr: false` on server-side --- .../next-swc/crates/core/src/next_dynamic.rs | 38 +++++++++++++++++-- .../next-swc/crates/core/tests/fixture.rs | 14 +++++++ .../duplicated-imports/output-server.js | 12 ++++++ .../member-with-same-name/output-server.js | 8 ++++ .../next-dynamic/no-options/output-server.js | 6 +++ .../next-dynamic/with-options/input.js | 5 +++ .../next-dynamic/with-options/output-dev.js | 9 +++++ .../next-dynamic/with-options/output-prod.js | 9 +++++ .../with-options/output-server.js | 16 ++++++++ .../wrapped-import/output-server.js | 11 ++++++ 10 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 packages/next-swc/crates/core/tests/fixture/next-dynamic/duplicated-imports/output-server.js create mode 100644 packages/next-swc/crates/core/tests/fixture/next-dynamic/member-with-same-name/output-server.js create mode 100644 packages/next-swc/crates/core/tests/fixture/next-dynamic/no-options/output-server.js create mode 100644 packages/next-swc/crates/core/tests/fixture/next-dynamic/with-options/output-server.js create mode 100644 packages/next-swc/crates/core/tests/fixture/next-dynamic/wrapped-import/output-server.js diff --git a/packages/next-swc/crates/core/src/next_dynamic.rs b/packages/next-swc/crates/core/src/next_dynamic.rs index dd67b916e13b..387391e9005f 100644 --- a/packages/next-swc/crates/core/src/next_dynamic.rs +++ b/packages/next-swc/crates/core/src/next_dynamic.rs @@ -4,9 +4,9 @@ use pathdiff::diff_paths; use swc_atoms::js_word; use swc_common::{FileName, DUMMY_SP}; use swc_ecmascript::ast::{ - ArrayLit, ArrowExpr, BinExpr, BinaryOp, BlockStmtOrExpr, CallExpr, Expr, ExprOrSpread, - ExprOrSuper, Ident, ImportDecl, ImportSpecifier, KeyValueProp, Lit, MemberExpr, ObjectLit, - Prop, PropName, PropOrSpread, Str, StrKind, + ArrayLit, ArrowExpr, BinExpr, BinaryOp, BlockStmtOrExpr, Bool, CallExpr, Expr, ExprOrSpread, + ExprOrSuper, Ident, ImportDecl, ImportSpecifier, KeyValueProp, Lit, MemberExpr, Null, + ObjectLit, Prop, PropName, PropOrSpread, Str, StrKind, }; use swc_ecmascript::utils::{ ident::{Id, IdentLike}, @@ -236,16 +236,48 @@ impl Fold for NextDynamicPatcher { value: generated, })))]; + let mut has_ssr_false = false; + if expr.args.len() == 2 { if let Expr::Object(ObjectLit { props: options_props, .. }) = &*expr.args[1].expr { + for prop in options_props.iter() { + if let Some(KeyValueProp { key, value }) = + prop.clone().prop().and_then(|p| p.key_value()) + { + if key.ident().and_then(|i| (Some(i.sym.eq("ssr".into())))) + == Some(true) + { + if let Some(Bool { value, span: _ }) = + value.lit().and_then(|l| { + if let Lit::Bool(value) = l { + Some(value) + } else { + None + } + }) + { + if value == false { + has_ssr_false = true + } + } + } + } + } props.extend(options_props.iter().cloned()); } } + if has_ssr_false && self.is_server { + expr.args[0] = ExprOrSpread { + spread: None, + expr: Box::new(Expr::Lit(Lit::Null(Null { span: DUMMY_SP }))), + } + } + let second_arg = ExprOrSpread { spread: None, expr: Box::new(Expr::Object(ObjectLit { diff --git a/packages/next-swc/crates/core/tests/fixture.rs b/packages/next-swc/crates/core/tests/fixture.rs index e43e4a48a9cf..f575c26c3d8c 100644 --- a/packages/next-swc/crates/core/tests/fixture.rs +++ b/packages/next-swc/crates/core/tests/fixture.rs @@ -34,6 +34,7 @@ fn amp_attributes_fixture(input: PathBuf) { fn next_dynamic_fixture(input: PathBuf) { let output_dev = input.parent().unwrap().join("output-dev.js"); let output_prod = input.parent().unwrap().join("output-prod.js"); + let output_server = input.parent().unwrap().join("output-server.js"); test_fixture( syntax(), &|_tr| { @@ -60,6 +61,19 @@ fn next_dynamic_fixture(input: PathBuf) { &input, &output_prod, ); + test_fixture( + syntax(), + &|_tr| { + next_dynamic( + false, + true, + FileName::Real(PathBuf::from("/some-project/src/some-file.js")), + Some("/some-project/src".into()), + ) + }, + &input, + &output_server, + ); } #[fixture("tests/fixture/ssg/**/input.js")] diff --git a/packages/next-swc/crates/core/tests/fixture/next-dynamic/duplicated-imports/output-server.js b/packages/next-swc/crates/core/tests/fixture/next-dynamic/duplicated-imports/output-server.js new file mode 100644 index 000000000000..871bf8fb3896 --- /dev/null +++ b/packages/next-swc/crates/core/tests/fixture/next-dynamic/duplicated-imports/output-server.js @@ -0,0 +1,12 @@ +import dynamic1 from 'next/dynamic' +import dynamic2 from 'next/dynamic' +const DynamicComponent1 = dynamic1(() => import('../components/hello1'), { + loadableGenerated: { + modules: ['some-file.js -> ' + '../components/hello1'], + }, +}) +const DynamicComponent2 = dynamic2(() => import('../components/hello2'), { + loadableGenerated: { + modules: ['some-file.js -> ' + '../components/hello2'], + }, +}) diff --git a/packages/next-swc/crates/core/tests/fixture/next-dynamic/member-with-same-name/output-server.js b/packages/next-swc/crates/core/tests/fixture/next-dynamic/member-with-same-name/output-server.js new file mode 100644 index 000000000000..c3f5016f39f3 --- /dev/null +++ b/packages/next-swc/crates/core/tests/fixture/next-dynamic/member-with-same-name/output-server.js @@ -0,0 +1,8 @@ +import dynamic from 'next/dynamic' +import somethingElse from 'something-else' +const DynamicComponent = dynamic(() => import('../components/hello'), { + loadableGenerated: { + modules: ['some-file.js -> ' + '../components/hello'], + }, +}) +somethingElse.dynamic('should not be transformed') diff --git a/packages/next-swc/crates/core/tests/fixture/next-dynamic/no-options/output-server.js b/packages/next-swc/crates/core/tests/fixture/next-dynamic/no-options/output-server.js new file mode 100644 index 000000000000..21763e18aa10 --- /dev/null +++ b/packages/next-swc/crates/core/tests/fixture/next-dynamic/no-options/output-server.js @@ -0,0 +1,6 @@ +import dynamic from 'next/dynamic' +const DynamicComponent = dynamic(() => import('../components/hello'), { + loadableGenerated: { + modules: ['some-file.js -> ' + '../components/hello'], + }, +}) diff --git a/packages/next-swc/crates/core/tests/fixture/next-dynamic/with-options/input.js b/packages/next-swc/crates/core/tests/fixture/next-dynamic/with-options/input.js index 91987b1357d3..82cb14f53566 100644 --- a/packages/next-swc/crates/core/tests/fixture/next-dynamic/with-options/input.js +++ b/packages/next-swc/crates/core/tests/fixture/next-dynamic/with-options/input.js @@ -4,3 +4,8 @@ const DynamicComponentWithCustomLoading = dynamic( () => import('../components/hello'), { loading: () =>

...

} ) + +const DynamicClientOnlyComponent = dynamic( + () => import('../components/hello'), + { ssr: false } +) diff --git a/packages/next-swc/crates/core/tests/fixture/next-dynamic/with-options/output-dev.js b/packages/next-swc/crates/core/tests/fixture/next-dynamic/with-options/output-dev.js index 7c9d62d7225a..e8ef64cab52e 100644 --- a/packages/next-swc/crates/core/tests/fixture/next-dynamic/with-options/output-dev.js +++ b/packages/next-swc/crates/core/tests/fixture/next-dynamic/with-options/output-dev.js @@ -8,3 +8,12 @@ const DynamicComponentWithCustomLoading = dynamic(()=>import("../components/hell }, loading: ()=>

...

}); +const DynamicClientOnlyComponent = dynamic(()=>import("../components/hello") +, { + loadableGenerated: { + modules: [ + "some-file.js -> " + "../components/hello" + ] + }, + ssr: false +}); \ No newline at end of file diff --git a/packages/next-swc/crates/core/tests/fixture/next-dynamic/with-options/output-prod.js b/packages/next-swc/crates/core/tests/fixture/next-dynamic/with-options/output-prod.js index cee511f2ded6..f5350433fd80 100644 --- a/packages/next-swc/crates/core/tests/fixture/next-dynamic/with-options/output-prod.js +++ b/packages/next-swc/crates/core/tests/fixture/next-dynamic/with-options/output-prod.js @@ -8,3 +8,12 @@ const DynamicComponentWithCustomLoading = dynamic(()=>import("../components/hell }, loading: ()=>

...

}); +const DynamicClientOnlyComponent = dynamic(()=>import("../components/hello") +, { + loadableGenerated: { + webpack: ()=>[ + require.resolveWeak("../components/hello") + ] + }, + ssr: false +}); \ No newline at end of file diff --git a/packages/next-swc/crates/core/tests/fixture/next-dynamic/with-options/output-server.js b/packages/next-swc/crates/core/tests/fixture/next-dynamic/with-options/output-server.js new file mode 100644 index 000000000000..0fb610435eb5 --- /dev/null +++ b/packages/next-swc/crates/core/tests/fixture/next-dynamic/with-options/output-server.js @@ -0,0 +1,16 @@ +import dynamic from 'next/dynamic' +const DynamicComponentWithCustomLoading = dynamic( + () => import('../components/hello'), + { + loadableGenerated: { + modules: ['some-file.js -> ' + '../components/hello'], + }, + loading: () =>

...

, + } +) +const DynamicClientOnlyComponent = dynamic(null, { + loadableGenerated: { + modules: ['some-file.js -> ' + '../components/hello'], + }, + ssr: false, +}) diff --git a/packages/next-swc/crates/core/tests/fixture/next-dynamic/wrapped-import/output-server.js b/packages/next-swc/crates/core/tests/fixture/next-dynamic/wrapped-import/output-server.js new file mode 100644 index 000000000000..dc2e6b9ecfa9 --- /dev/null +++ b/packages/next-swc/crates/core/tests/fixture/next-dynamic/wrapped-import/output-server.js @@ -0,0 +1,11 @@ +import dynamic from "next/dynamic"; +const DynamicComponent = dynamic(null, { + loadableGenerated: { + modules: [ + "some-file.js -> " + "./components/hello" + ] + }, + loading: ()=>null + , + ssr: false +}); \ No newline at end of file From b22fdc4006f00f027c0b8496b660b6877493d8a5 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Mon, 10 Jan 2022 15:49:42 +0100 Subject: [PATCH 2/2] avoid cloning, use expr factory --- .../next-swc/crates/core/src/next_dynamic.rs | 45 ++++++++++--------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/packages/next-swc/crates/core/src/next_dynamic.rs b/packages/next-swc/crates/core/src/next_dynamic.rs index 387391e9005f..12cb475dfba5 100644 --- a/packages/next-swc/crates/core/src/next_dynamic.rs +++ b/packages/next-swc/crates/core/src/next_dynamic.rs @@ -8,6 +8,7 @@ use swc_ecmascript::ast::{ ExprOrSuper, Ident, ImportDecl, ImportSpecifier, KeyValueProp, Lit, MemberExpr, Null, ObjectLit, Prop, PropName, PropOrSpread, Str, StrKind, }; +use swc_ecmascript::utils::ExprFactory; use swc_ecmascript::utils::{ ident::{Id, IdentLike}, HANDLER, @@ -245,22 +246,29 @@ impl Fold for NextDynamicPatcher { }) = &*expr.args[1].expr { for prop in options_props.iter() { - if let Some(KeyValueProp { key, value }) = - prop.clone().prop().and_then(|p| p.key_value()) - { - if key.ident().and_then(|i| (Some(i.sym.eq("ssr".into())))) - == Some(true) - { - if let Some(Bool { value, span: _ }) = - value.lit().and_then(|l| { - if let Lit::Bool(value) = l { - Some(value) - } else { - None - } - }) - { - if value == false { + if let Some(KeyValueProp { key, value }) = match prop { + PropOrSpread::Prop(prop) => match &**prop { + Prop::KeyValue(key_value_prop) => Some(key_value_prop), + _ => None, + }, + _ => None, + } { + if let Some(Ident { + sym, + span: _, + optional: _, + }) = match key { + PropName::Ident(ident) => Some(ident), + _ => None, + } { + if sym == "ssr" { + if let Some(Lit::Bool(Bool { + value: false, + span: _, + })) = match &**value { + Expr::Lit(lit) => Some(lit), + _ => None, + } { has_ssr_false = true } } @@ -272,10 +280,7 @@ impl Fold for NextDynamicPatcher { } if has_ssr_false && self.is_server { - expr.args[0] = ExprOrSpread { - spread: None, - expr: Box::new(Expr::Lit(Lit::Null(Null { span: DUMMY_SP }))), - } + expr.args[0] = Lit::Null(Null { span: DUMMY_SP }).as_arg(); } let second_arg = ExprOrSpread {