Skip to content

React.lazy() content HTML does not get included in SSG output #33879

Closed
@gaearon

Description

@gaearon

Run next info (available from version 12.0.8 and up)

Operating System:
  Platform: darwin
  Arch: x64
  Version: Darwin Kernel Version 21.2.0: Sun Nov 28 20:28:54 PST 2021; root:xnu-8019.61.5~1/RELEASE_X86_64
Binaries:
  Node: 16.13.0
  npm: 8.1.0
  Yarn: 1.22.0
  pnpm: N/A
Relevant packages:
  next: 12.0.10
  react: 0.0.0-experimental-fa816be7f-20220128
  react-dom: 0.0.0-experimental-fa816be7f-20220128

What version of Next.js are you using?

12.0.10

What version of Node.js are you using?

16.13.0

What browser are you using?

Chrome

What operating system are you using?

macOS

How are you deploying your application?

next start

Describe the Bug

@devknoll asked me to file an issue for this. Basically, I'm observing that with React experimental versions, SSG doesn't wait for lazy() to be resolved and outputs the Suspense fallback HTML. Whereas I would've expected it to include content in SSG.

I'm not sure if this means import() needs to be compiled differently, or something.

A similar issue is that in SSR mode, the first hit will get fallback HTML and the next hits will get content HTML. Because the module is cached now.

Expected Behavior

HTML output of SSG includes the SSR content of the lazy child.

To Reproduce

Create a new clean project.

Add experimental React versions to it.

Page code:

import {lazy, Suspense} from 'react'
import Head from 'next/head'

const Child = lazy(() => import('../components/Child'))

export default function Home() {
  return (
    <div>
      <Head>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main>
        <h1>
          Welcome to <a href="https://nextjs.org">Next.js!</a>
        </h1>
        <Suspense fallback={<p style={{ color: 'red' }}>Loading...</p>}>
          <Child />
        </Suspense>
      </main>
    </div>
  )
}

Component code:

// Some heavy lib to simulate loading a large chunk
import {marked} from 'marked'

export default function Child() {
  return <div dangerouslySetInnerHTML={{
    __html: marked(`# hello, world!`)
  }} />
}

Run yarn build and then yarn start.

Observe that the served HTML does not include hello, world! but does include Loading....

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugIssue was opened via the bug report template.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions