Skip to content

Commit

Permalink
Merge branch 'canary' into 11-15-tweak_cache_revalidate_fetch_warning
Browse files Browse the repository at this point in the history
  • Loading branch information
ztanner authored Nov 16, 2023
2 parents 382181c + d6d6d56 commit cf83dfd
Show file tree
Hide file tree
Showing 17 changed files with 272 additions and 22 deletions.
2 changes: 1 addition & 1 deletion packages/next-swc/crates/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ where
Some(config) if config.truthy() => match config {
// Always enable the Server Components mode for both
// server and client layers.
react_server_components::Config::WithOptions(_) => true,
react_server_components::Config::WithOptions(config) => config.is_react_server_layer,
_ => false,
},
_ => false,
Expand Down
22 changes: 21 additions & 1 deletion packages/next-swc/crates/core/tests/fixture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,11 @@ fn next_dynamic_fixture(input: PathBuf) {
fn app_dir_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");
let output_server: PathBuf = input.parent().unwrap().join("output-server.js");
let output_server_client_layer = input
.parent()
.unwrap()
.join("output-server-client-layer.js");
test_fixture(
syntax(),
&|_tr| {
Expand Down Expand Up @@ -161,6 +165,22 @@ fn app_dir_next_dynamic_fixture(input: PathBuf) {
&output_server,
Default::default(),
);
test_fixture(
syntax(),
&|_tr| {
next_dynamic(
false,
true,
false,
NextDynamicMode::Webpack,
FileName::Real(PathBuf::from("/some-project/src/some-file.js")),
Some("/some-project/src".into()),
)
},
&input,
&output_server_client_layer,
Default::default(),
);
}

#[fixture("tests/fixture/ssg/**/input.js")]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import dynamic from 'next/dynamic';
export const NextDynamicNoSSRServerComponent = dynamic(async ()=>{
typeof require.resolveWeak !== "undefined" && require.resolveWeak("../text-dynamic-no-ssr-server");
}, {
loadableGenerated: {
modules: [
"some-file.js -> " + "../text-dynamic-no-ssr-server"
]
},
ssr: false
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import dynamic from 'next/dynamic';
export const NextDynamicNoSSRServerComponent = dynamic(null, {
export const NextDynamicNoSSRServerComponent = dynamic(async ()=>{
typeof require.resolveWeak !== "undefined" && require.resolveWeak("../text-dynamic-no-ssr-server");
}, {
loadableGenerated: {
modules: [
"some-file.js -> " + "../text-dynamic-no-ssr-server"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@ const DynamicComponentWithCustomLoading = dynamic(()=>import('../components/hell
},
loading: ()=><p>...</p>
});
const DynamicClientOnlyComponent = dynamic(null, {
const DynamicClientOnlyComponent = dynamic(async ()=>{
typeof require.resolveWeak !== "undefined" && require.resolveWeak("../components/hello");
}, {
loadableGenerated: {
modules: [
"some-file.js -> " + "../components/hello"
]
},
ssr: false
});
const DynamicClientOnlyComponentWithSuspense = dynamic(()=>import('../components/hello'), {
const DynamicClientOnlyComponentWithSuspense = dynamic(async ()=>{
typeof require.resolveWeak !== "undefined" && require.resolveWeak("../components/hello");
}, {
loadableGenerated: {
modules: [
"some-file.js -> " + "../components/hello"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import dynamic from 'next/dynamic';
const DynamicComponent = dynamic(null, {
const DynamicComponent = dynamic(async ()=>{
typeof require.resolveWeak !== "undefined" && require.resolveWeak("./components/hello");
}, {
loadableGenerated: {
modules: [
"some-file.js -> " + "./components/hello"
Expand Down
102 changes: 88 additions & 14 deletions packages/next-swc/crates/next-transform-dynamic/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ use swc_core::{
common::{errors::HANDLER, FileName, Span, DUMMY_SP},
ecma::{
ast::{
ArrayLit, ArrowExpr, BlockStmtOrExpr, Bool, CallExpr, Callee, Expr, ExprOrSpread,
ExprStmt, Id, Ident, ImportDecl, ImportDefaultSpecifier, ImportNamedSpecifier,
ImportSpecifier, KeyValueProp, Lit, ModuleDecl, ModuleItem, Null, ObjectLit, Prop,
PropName, PropOrSpread, Stmt, Str, Tpl,
op, ArrayLit, ArrowExpr, BinExpr, BlockStmt, BlockStmtOrExpr, Bool, CallExpr, Callee,
Expr, ExprOrSpread, ExprStmt, Id, Ident, ImportDecl, ImportDefaultSpecifier,
ImportNamedSpecifier, ImportSpecifier, KeyValueProp, Lit, ModuleDecl, ModuleItem,
ObjectLit, Prop, PropName, PropOrSpread, Stmt, Str, Tpl, UnaryExpr, UnaryOp,
},
utils::{private_ident, ExprFactory},
utils::{private_ident, quote_ident, ExprFactory},
visit::{Fold, FoldWith},
},
quote,
Expand Down Expand Up @@ -236,12 +236,12 @@ impl Fold for NextDynamicPatcher {
rel_filename(self.pages_dir.as_deref(), &self.filename)
)
.into(),
right: Expr = dynamically_imported_specifier.into(),
right: Expr = dynamically_imported_specifier.clone().into(),
))
} else {
webpack_options(quote!(
"require.resolveWeak($id)" as Expr,
id: Expr = dynamically_imported_specifier.into()
id: Expr = dynamically_imported_specifier.clone().into()
))
}
}
Expand All @@ -259,7 +259,7 @@ impl Fold for NextDynamicPatcher {
imports.push(TurbopackImport::DevelopmentTransition {
id_ident: id_ident.clone(),
chunks_ident: chunks_ident.clone(),
specifier: dynamically_imported_specifier,
specifier: dynamically_imported_specifier.clone(),
});

// On the server, the key needs to be serialized because it
Expand All @@ -280,7 +280,7 @@ impl Fold for NextDynamicPatcher {
(true, false) => {
imports.push(TurbopackImport::DevelopmentId {
id_ident: id_ident.clone(),
specifier: dynamically_imported_specifier,
specifier: dynamically_imported_specifier.clone(),
});

// On the client, we only need the target module ID, which
Expand Down Expand Up @@ -365,11 +365,54 @@ impl Fold for NextDynamicPatcher {
}
}

// Also don't strip the `loader` argument for server components (both
// server/client layers), since they're aliased to a
// React.lazy implementation.
if has_ssr_false && self.is_server_compiler && !self.is_react_server_layer {
expr.args[0] = Lit::Null(Null { span: DUMMY_SP }).as_arg();
if has_ssr_false
&& self.is_server_compiler
&& !self.is_react_server_layer
// Only use `require.resolveWebpack` to decouple modules for webpack,
// turbopack doesn't need this
&& self.state == NextDynamicPatcherState::Webpack
{
// if it's server components SSR layer
// Transform 1st argument `expr.args[0]` aka the module loader from:
// dynamic(() => import('./client-mod'), { ssr: false }))`
// into:
// dynamic(async () => {
// require.resolveWeak('./client-mod')
// }, { ssr: false }))`

let require_resolve_weak_expr = Expr::Call(CallExpr {
span: DUMMY_SP,
callee: quote_ident!("require.resolveWeak").as_callee(),
args: vec![ExprOrSpread {
spread: None,
expr: Box::new(Expr::Lit(Lit::Str(Str {
span: DUMMY_SP,
value: dynamically_imported_specifier.clone().into(),
raw: None,
}))),
}],
type_args: Default::default(),
});

let side_effect_free_loader_arg = Expr::Arrow(ArrowExpr {
span: DUMMY_SP,
params: vec![],
body: Box::new(BlockStmtOrExpr::BlockStmt(BlockStmt {
span: DUMMY_SP,
stmts: vec![Stmt::Expr(ExprStmt {
span: DUMMY_SP,
expr: Box::new(exec_expr_when_resolve_weak_available(
&require_resolve_weak_expr,
)),
})],
})),
is_async: true,
is_generator: false,
type_params: None,
return_type: None,
});

expr.args[0] = side_effect_free_loader_arg.as_arg();
}

let second_arg = ExprOrSpread {
Expand Down Expand Up @@ -562,6 +605,37 @@ impl NextDynamicPatcher {
}
}

fn exec_expr_when_resolve_weak_available(expr: &Expr) -> Expr {
let undefined_str_literal = Expr::Lit(Lit::Str(Str {
span: DUMMY_SP,
value: "undefined".into(),
raw: None,
}));

let typeof_expr = Expr::Unary(UnaryExpr {
span: DUMMY_SP,
op: UnaryOp::TypeOf, // 'typeof' operator
arg: Box::new(Expr::Ident(Ident {
span: DUMMY_SP,
sym: quote_ident!("require.resolveWeak").sym,
optional: false,
})),
});

// typeof require.resolveWeak !== 'undefined' && <expression>
Expr::Bin(BinExpr {
span: DUMMY_SP,
left: Box::new(Expr::Bin(BinExpr {
span: DUMMY_SP,
op: op!("!=="),
left: Box::new(typeof_expr),
right: Box::new(undefined_str_literal),
})),
op: op!("&&"),
right: Box::new(expr.clone()),
})
}

fn rel_filename(base: Option<&Path>, file: &FileName) -> String {
let base = match base {
Some(v) => v,
Expand Down
14 changes: 14 additions & 0 deletions test/e2e/app-dir/actions/app-action.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,20 @@ createNextDescribe(
}, '1')
})

it('should support next/dynamic with ssr: false (edge)', async () => {
const browser = await next.browser('/dynamic-csr/edge')

await check(() => {
return browser.elementByCss('button').text()
}, '0')

await browser.elementByCss('button').click()

await check(() => {
return browser.elementByCss('button').text()
}, '1')
})

it('should only submit action once when resubmitting an action after navigation', async () => {
let requestCount = 0

Expand Down
20 changes: 20 additions & 0 deletions test/e2e/app-dir/actions/app/dynamic-csr/edge/page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use client'

import dynamic from 'next/dynamic'

const DynamicComponent = dynamic(
() => import('../csr').then((mod) => mod.CSR),
{
ssr: false,
}
)

export default function Client() {
return (
<div>
<DynamicComponent />
</div>
)
}

export const runtime = 'edge'
4 changes: 3 additions & 1 deletion test/e2e/app-dir/dynamic/app/chunk-loading/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@

'use client'

function noop() {}

export default function Page() {
import('./comp').then((m) => {
console.log(m)
noop(m)
})
return null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use client'

export { default } from '../dynamic-import'

export const runtime = 'edge'
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
'use client'

export { default } from '../dynamic-import'
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import dynamic from 'next/dynamic'

const DynamicSSRFalse = dynamic(() => import('./ssr-false-module'), {
ssr: false,
})

export default function page() {
return (
<div>
<DynamicSSRFalse />
<p id="content">dynamic-mixed-ssr-false</p>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Client from './ssr-false-client'
import Server from './ssr-false-server'

export default function Comp() {
return (
<>
<Client />
<Server />
</>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use client'

export default function Comp() {
return <p id="ssr-false-client-module">ssr-false-client-module-text</p>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Comp() {
return <p id="ssr-false-server-module">ssr-false-server-module-text</p>
}
Loading

0 comments on commit cf83dfd

Please sign in to comment.