Skip to content

Commit

Permalink
Fix SWC dynamic transform with suspense but without ssr
Browse files Browse the repository at this point in the history
  • Loading branch information
Brooooooklyn committed May 12, 2022
1 parent 72f5c93 commit 2a38e86
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 6 deletions.
21 changes: 15 additions & 6 deletions packages/next-swc/crates/core/src/next_dynamic.rs
Expand Up @@ -226,6 +226,7 @@ impl Fold for NextDynamicPatcher {
})))];

let mut has_ssr_false = false;
let mut has_suspense = false;

if expr.args.len() == 2 {
if let Expr::Object(ObjectLit {
Expand Down Expand Up @@ -253,21 +254,29 @@ impl Fold for NextDynamicPatcher {
if let Some(Lit::Bool(Bool {
value: false,
span: _,
})) = match &**value {
Expr::Lit(lit) => Some(lit),
_ => None,
} {
})) = value.as_lit()
{
has_ssr_false = true
}
}
if sym == "suspense" {
if let Some(Lit::Bool(Bool {
value: true,
span: _,
})) = value.as_lit()
{
has_suspense = true
}
}
}
}
}
props.extend(options_props.iter().cloned());
}
}

if has_ssr_false && self.is_server {
// Don't need to strip the `loader` argument if suspense is true
// See https://github.com/vercel/next.js/issues/36636 for background
if has_ssr_false && !has_suspense && self.is_server {
expr.args[0] = Lit::Null(Null { span: DUMMY_SP }).as_arg();
}

Expand Down
Expand Up @@ -9,3 +9,8 @@ const DynamicClientOnlyComponent = dynamic(
() => import('../components/hello'),
{ ssr: false }
)

const DynamicClientOnlyComponentWithSuspense = dynamic(
() => import('../components/hello'),
{ ssr: false, suspense: true }
)
Expand Up @@ -17,3 +17,13 @@ const DynamicClientOnlyComponent = dynamic(()=>import('../components/hello')
},
ssr: false
});
const DynamicClientOnlyComponentWithSuspense = dynamic(()=>import('../components/hello')
, {
loadableGenerated: {
modules: [
"some-file.js -> " + "../components/hello"
]
},
ssr: false,
suspense: true
});
Expand Up @@ -17,3 +17,13 @@ const DynamicClientOnlyComponent = dynamic(()=>import('../components/hello')
},
ssr: false
});
const DynamicClientOnlyComponentWithSuspense = dynamic(()=>import('../components/hello')
, {
loadableGenerated: {
webpack: ()=>[
require.resolveWeak("../components/hello")
]
},
ssr: false,
suspense: true
});
Expand Up @@ -16,3 +16,13 @@ const DynamicClientOnlyComponent = dynamic(null, {
},
ssr: false
});
const DynamicClientOnlyComponentWithSuspense = dynamic(()=>import('../components/hello')
, {
loadableGenerated: {
modules: [
"some-file.js -> " + "../components/hello"
]
},
ssr: false,
suspense: true
});
55 changes: 55 additions & 0 deletions test/e2e/dynamic-with-suspense/index.test.ts
@@ -0,0 +1,55 @@
import { createNext } from 'e2e-utils'
import { NextInstance } from 'test/lib/next-modes/base'
import { hasRedbox, renderViaHTTP } from 'next-test-utils'
import webdriver from 'next-webdriver'

const suite =
process.env.NEXT_TEST_REACT_VERSION === '^17' ? describe.skip : describe

// Skip the suspense test if react version is 17
suite('dynamic with suspense', () => {
let next: NextInstance

beforeAll(async () => {
next = await createNext({
files: {
'pages/index.js': `
import { Suspense } from "react";
import dynamic from "next/dynamic";
const Thing = dynamic(() => import("./thing"), { ssr: false, suspense: true });
export default function IndexPage() {
return (
<div>
<p>Next.js Example</p>
<Suspense fallback="Loading...">
<Thing />
</Suspense>
</div>
);
}
`,
'pages/thing.js': `
export default function Thing() {
return "Thing";
}
`,
},
dependencies: {},
})
})
afterAll(() => next.destroy())

it('should render server-side', async () => {
const html = await renderViaHTTP(next.url, '/')
expect(html).toContain('Next.js Example')
expect(html).toContain('Thing')
})

it('should render client-side', async () => {
const browser = await webdriver(next.url, '/')
expect(await hasRedbox(browser)).toBe(false)
await browser.close()
})
})

0 comments on commit 2a38e86

Please sign in to comment.