diff --git a/packages/next-swc/crates/core/src/next_dynamic.rs b/packages/next-swc/crates/core/src/next_dynamic.rs index dd67b916e13b..12cb475dfba5 100644 --- a/packages/next-swc/crates/core/src/next_dynamic.rs +++ b/packages/next-swc/crates/core/src/next_dynamic.rs @@ -4,10 +4,11 @@ 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::ExprFactory; use swc_ecmascript::utils::{ ident::{Id, IdentLike}, HANDLER, @@ -236,16 +237,52 @@ 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 }) = 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 + } + } + } + } + } props.extend(options_props.iter().cloned()); } } + if has_ssr_false && self.is_server { + expr.args[0] = Lit::Null(Null { span: DUMMY_SP }).as_arg(); + } + 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