Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial support for Server Component style Documents #27794

Closed
wants to merge 24 commits into from

Conversation

devknoll
Copy link
Contributor

@devknoll devknoll commented Aug 5, 2021

Adds support for Server Component style pages/_document components, since this component only runs on the server.

Server Components aren't stable yet, we just support a very minimal subset. You may only return HTML elements and elements from next/document. Hooks, suspense, context, etc are not currently supported. It's highly likely that anything more sophisticated than the following example will be broken by a future version of Next.js:

import {
  Html,
  Head,
  Main,
  NextScript
} from 'next/document'

// pages/_document
export default function Document(props) {
  return (
    <Html>
      <Head />
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}

Instead of getInitialProps, you should use suspense. The current iteration of this PR doesn't include that anymore, but support can be introduced if necessary.

@ijjk ijjk added created-by: Chrome Aurora PRs by the Google Chrome team: https://web.dev/aurora type: next labels Aug 5, 2021
@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@devknoll devknoll changed the title Initial support for modern custom Document components Initial support for pseudo-Server Component Documents Aug 9, 2021
@ijjk

This comment has been minimized.

@devknoll devknoll changed the title Initial support for pseudo-Server Component Documents Initial support for Server Component style Documents Aug 11, 2021
@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

kodiakhq bot pushed a commit that referenced this pull request Aug 13, 2021
Implements `renderToString` in terms of a new `renderToStream`. The former is used for legacy documents that generate the body HTML as part of `getInitialProps`. The latter will be used directly in #27794 when streaming dynamic HTML.

Since we're exposing an actual streaming response for dynamic HTML (instead of buffering with `resultFromChunks`), we use `multiplexResult` to buffer and multiplex the underlying result to multiple subscribers.
@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk
Copy link
Member

ijjk commented Aug 16, 2021

Failing test suites

Commit: 8be28d4

test/integration/react-18/test/index.test.js

  • Basics > suspense is not allowed in blocking rendering mode (dev)
  • Basics > default setting with react 18 (dev) > should render fallback without preloads on server side
  • Basics > default setting with react 18 (prod) > should render fallback without preloads on server side
  • Blocking mode > concurrentFeatures is disabled (dev) > should render fallback on server side if suspense without preload
  • Blocking mode > concurrentFeatures is disabled (dev) > should render fallback on server side if suspended on server with preload
  • Blocking mode > concurrentFeatures is disabled (prod) > should render fallback on server side if suspense without preload
  • Blocking mode > concurrentFeatures is disabled (prod) > should render fallback on server side if suspended on server with preload
Expand output

● Basics › default setting with react 18 (dev) › should render fallback without preloads on server side

expect(received).toBe(expected) // Object.is equality

Expected: "rab"
Received: "barfoo"

  26 |     const content = $('#__next').text()
  27 |     // <Bar> is suspended
> 28 |     expect(content).toBe('rab')
     |                     ^
  29 |     expect(nextData.dynamicIds).toBeUndefined()
  30 |   })
  31 | }

  at Object.<anonymous> (integration/react-18/test/basics.js:28:21)

● Basics › default setting with react 18 (prod) › should render fallback without preloads on server side

expect(received).toBe(expected) // Object.is equality

Expected: "rab"
Received: "barfoo"

  26 |     const content = $('#__next').text()
  27 |     // <Bar> is suspended
> 28 |     expect(content).toBe('rab')
     |                     ^
  29 |     expect(nextData.dynamicIds).toBeUndefined()
  30 |   })
  31 | }

  at Object.<anonymous> (integration/react-18/test/basics.js:28:21)

● Basics › suspense is not allowed in blocking rendering mode (dev)

expect(received).toContain(expected) // indexOf

Expected substring: "A React component suspended while rendering, but no fallback UI was specified"
Received string:    "<!DOCTYPE html><html><head><style data-next-hide-fouc=\"true\">body{display:none}</style><noscript data-next-hide-fouc=\"true\"><style>body{display:block}</style></noscript><meta charSet=\"utf-8\"/><meta name=\"viewport\" content=\"width=device-width\"/><meta name=\"next-head-count\" content=\"2\"/><noscript data-n-css=\"\"></noscript><script defer=\"\" nomodule=\"\" src=\"/_next/static/chunks/polyfills.js?ts=1629140156462\"></script><script src=\"/_next/static/chunks/webpack.js?ts=1629140156462\" defer=\"\"></script><script src=\"/_next/static/chunks/main.js?ts=1629140156462\" defer=\"\"></script><script src=\"/_next/static/chunks/pages/_app.js?ts=1629140156462\" defer=\"\"></script><script src=\"/_next/static/chunks/pages/suspense/unwrapped.js?ts=1629140156462\" defer=\"\"></script><script src=\"/_next/static/development/_buildManifest.js?ts=1629140156462\" defer=\"\"></script><script src=\"/_next/static/development/_ssgManifest.js?ts=1629140156462\" defer=\"\"></script><noscript id=\"__next_css__DO_NOT_USE__\"></noscript></head><body><div id=\"__next\"><p>hello <!-- -->18.0.0-c76e4dbbc-20210722<!-- --></p></div><script src=\"/_next/static/chunks/react-refresh.js?ts=1629140156462\"></script><script id=\"__NEXT_DATA__\" type=\"application/json\">{\"props\":{\"pageProps\":{}},\"page\":\"/suspense/unwrapped\",\"query\":{},\"buildId\":\"development\",\"nextExport\":true,\"autoExport\":true,\"isFallback\":false,\"scriptLoader\":[]}</script></body></html>"

  132 |     await killApp(app)
  133 |     // expect(html).toContain('Disallowed suspense option usage with next/dynamic')
> 134 |     expect(html).toContain(
      |                  ^
  135 |       'A React component suspended while rendering, but no fallback UI was specified'
  136 |     )
  137 |   })

  at Object.<anonymous> (integration/react-18/test/index.test.js:134:18)

● Blocking mode › concurrentFeatures is disabled (dev) › should render fallback on server side if suspense without preload

expect(received).toBe(expected) // Object.is equality

Expected: "rab"
Received: "barfoo"

  13 |     const nextData = JSON.parse($('#__NEXT_DATA__').text())
  14 |     const content = $('#__next').text()
> 15 |     expect(content).toBe('rab')
     |                     ^
  16 |     expect(nextData.dynamicIds).toBeUndefined()
  17 |   })
  18 |

  at Object.<anonymous> (integration/react-18/test/blocking.js:15:21)

● Blocking mode › concurrentFeatures is disabled (dev) › should render fallback on server side if suspended on server with preload

expect(received).toContain(expected) // indexOf

Expected substring: "loading"
Received string:    "<div id=\"__next\"><!--$--><p>hello <!-- -->18.0.0-c76e4dbbc-20210722<!-- --></p><!--/$--></div><script src=\"/_next/static/chunks/react-refresh.js?ts=1629140161260\"></script><script id=\"__NEXT_DATA__\" type=\"application/json\">{\"props\":{\"pageProps\":{}},\"page\":\"/suspense/thrown\",\"query\":{},\"buildId\":\"development\",\"nextExport\":true,\"autoExport\":true,\"isFallback\":false,\"scriptLoader\":[]}</script>"

  20 |     const $ = await get$('/suspense/thrown')
  21 |     const html = $('body').html()
> 22 |     expect(html).toContain('loading')
     |                  ^
  23 |     expect(JSON.parse($('#__NEXT_DATA__').text()).dynamicIds).toBeUndefined()
  24 |   })
  25 | }

  at Object.<anonymous> (integration/react-18/test/blocking.js:22:18)

● Blocking mode › concurrentFeatures is disabled (prod) › should render fallback on server side if suspense without preload

expect(received).toBe(expected) // Object.is equality

Expected: "rab"
Received: "barfoo"

  13 |     const nextData = JSON.parse($('#__NEXT_DATA__').text())
  14 |     const content = $('#__next').text()
> 15 |     expect(content).toBe('rab')
     |                     ^
  16 |     expect(nextData.dynamicIds).toBeUndefined()
  17 |   })
  18 |

  at Object.<anonymous> (integration/react-18/test/blocking.js:15:21)

● Blocking mode › concurrentFeatures is disabled (prod) › should render fallback on server side if suspended on server with preload

expect(received).toContain(expected) // indexOf

Expected substring: "loading"
Received string:    "<div id=\"__next\"><!--$--><p>hello <!-- -->18.0.0-c76e4dbbc-20210722<!-- --></p><!--/$--></div><script id=\"__NEXT_DATA__\" type=\"application/json\">{\"props\":{\"pageProps\":{}},\"page\":\"/suspense/thrown\",\"query\":{},\"buildId\":\"JB853z5rxwhfjGTm7c-YJ\",\"nextExport\":true,\"autoExport\":true,\"isFallback\":false,\"scriptLoader\":[]}</script>"

  20 |     const $ = await get$('/suspense/thrown')
  21 |     const html = $('body').html()
> 22 |     expect(html).toContain('loading')
     |                  ^
  23 |     expect(JSON.parse($('#__NEXT_DATA__').text()).dynamicIds).toBeUndefined()
  24 |   })
  25 | }

  at Object.<anonymous> (integration/react-18/test/blocking.js:22:18)

@ijjk
Copy link
Member

ijjk commented Aug 16, 2021

Stats from current PR

Default Build (Decrease detected ✓)
General Overall increase ⚠️
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
buildDuration 13.6s 13.5s -76ms
buildDurationCached 3.5s 3.5s -83ms
nodeModulesSize 49.7 MB 49.7 MB ⚠️ +51.3 kB
Page Load Tests Overall decrease ⚠️
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
/ failed reqs 0 0
/ total time (seconds) 2.598 2.612 ⚠️ +0.01
/ avg req/sec 962.32 957.24 ⚠️ -5.08
/error-in-render failed reqs 0 0
/error-in-render total time (seconds) 1.423 1.503 ⚠️ +0.08
/error-in-render avg req/sec 1756.44 1663.43 ⚠️ -93.01
Client Bundles (main, webpack, commons)
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
745.HASH.js gzip 179 B 179 B
framework-HASH.js gzip 42.2 kB 42.2 kB
main-HASH.js gzip 23.1 kB 23.1 kB
webpack-HASH.js gzip 1.44 kB 1.44 kB
Overall change 67 kB 67 kB
Legacy Client Bundles (polyfills)
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
polyfills-a4..dd70.js gzip 31 kB 31 kB
Overall change 31 kB 31 kB
Client Pages
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
_app-HASH.js gzip 980 B 980 B
_error-HASH.js gzip 194 B 194 B
amp-HASH.js gzip 312 B 312 B
css-HASH.js gzip 329 B 329 B
dynamic-HASH.js gzip 2.64 kB 2.64 kB
head-HASH.js gzip 350 B 350 B
hooks-HASH.js gzip 904 B 904 B
image-HASH.js gzip 4.13 kB 4.13 kB
index-HASH.js gzip 261 B 261 B
link-HASH.js gzip 1.66 kB 1.66 kB
routerDirect..HASH.js gzip 319 B 319 B
script-HASH.js gzip 387 B 387 B
withRouter-HASH.js gzip 320 B 320 B
bb14e60e810b..30f.css gzip 125 B 125 B
Overall change 12.9 kB 12.9 kB
Client Build Manifests
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
_buildManifest.js gzip 491 B 491 B
Overall change 491 B 491 B
Rendered Page Sizes
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
index.html gzip 540 B 540 B
link.html gzip 551 B 551 B
withRouter.html gzip 532 B 532 B
Overall change 1.62 kB 1.62 kB

Webpack 4 Mode (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
buildDuration 11.2s 10.9s -304ms
buildDurationCached 4.6s 4.5s -142ms
nodeModulesSize 49.7 MB 49.7 MB ⚠️ +51.3 kB
Page Load Tests Overall increase ✓
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
/ failed reqs 0 0
/ total time (seconds) 2.675 2.569 -0.11
/ avg req/sec 934.62 973.08 +38.46
/error-in-render failed reqs 0 0
/error-in-render total time (seconds) 1.483 1.44 -0.04
/error-in-render avg req/sec 1685.54 1735.91 +50.37
Client Bundles (main, webpack, commons)
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
16.HASH.js gzip 186 B 186 B
677f882d2ed8..HASH.js gzip 14 kB 14 kB
framework.HASH.js gzip 41.9 kB 41.9 kB
main-HASH.js gzip 10.6 kB 10.6 kB
webpack-HASH.js gzip 1.19 kB 1.19 kB
Overall change 67.9 kB 67.9 kB
Legacy Client Bundles (polyfills)
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
polyfills-a4..dd70.js gzip 31 kB 31 kB
Overall change 31 kB 31 kB
Client Pages
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
_app-HASH.js gzip 965 B 965 B
_error-HASH.js gzip 3.71 kB 3.71 kB
amp-HASH.js gzip 552 B 552 B
css-HASH.js gzip 333 B 333 B
dynamic-HASH.js gzip 2.83 kB 2.83 kB
head-HASH.js gzip 2.97 kB 2.97 kB
hooks-HASH.js gzip 911 B 911 B
index-HASH.js gzip 231 B 231 B
link-HASH.js gzip 1.64 kB 1.64 kB
routerDirect..HASH.js gzip 298 B 298 B
script-HASH.js gzip 2.95 kB 2.95 kB
withRouter-HASH.js gzip 294 B 294 B
e025d2764813..52f.css gzip 125 B 125 B
Overall change 17.8 kB 17.8 kB
Client Build Manifests
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
_buildManifest.js gzip 498 B 498 B
Overall change 498 B 498 B
Rendered Page Sizes
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
index.html gzip 584 B 584 B
link.html gzip 596 B 596 B
withRouter.html gzip 578 B 578 B
Overall change 1.76 kB 1.76 kB
Commit: 481fa90

@ijjk
Copy link
Member

ijjk commented Aug 16, 2021

Failing test suites

Commit: 481fa90

test/integration/react-18/test/index.test.js

  • Basics > suspense is not allowed in blocking rendering mode (dev)
  • Basics > default setting with react 18 (dev) > should render fallback without preloads on server side
  • Basics > default setting with react 18 (prod) > should render fallback without preloads on server side
  • Blocking mode > concurrentFeatures is disabled (dev) > should render fallback on server side if suspense without preload
  • Blocking mode > concurrentFeatures is disabled (dev) > should render fallback on server side if suspended on server with preload
  • Blocking mode > concurrentFeatures is disabled (prod) > should render fallback on server side if suspense without preload
  • Blocking mode > concurrentFeatures is disabled (prod) > should render fallback on server side if suspended on server with preload
Expand output

● Basics › default setting with react 18 (dev) › should render fallback without preloads on server side

expect(received).toBe(expected) // Object.is equality

Expected: "rab"
Received: "barfoo"

  26 |     const content = $('#__next').text()
  27 |     // <Bar> is suspended
> 28 |     expect(content).toBe('rab')
     |                     ^
  29 |     expect(nextData.dynamicIds).toBeUndefined()
  30 |   })
  31 | }

  at Object.<anonymous> (integration/react-18/test/basics.js:28:21)

● Basics › default setting with react 18 (prod) › should render fallback without preloads on server side

expect(received).toBe(expected) // Object.is equality

Expected: "rab"
Received: "barfoo"

  26 |     const content = $('#__next').text()
  27 |     // <Bar> is suspended
> 28 |     expect(content).toBe('rab')
     |                     ^
  29 |     expect(nextData.dynamicIds).toBeUndefined()
  30 |   })
  31 | }

  at Object.<anonymous> (integration/react-18/test/basics.js:28:21)

● Basics › suspense is not allowed in blocking rendering mode (dev)

expect(received).toContain(expected) // indexOf

Expected substring: "A React component suspended while rendering, but no fallback UI was specified"
Received string:    "<!DOCTYPE html><html><head><style data-next-hide-fouc=\"true\">body{display:none}</style><noscript data-next-hide-fouc=\"true\"><style>body{display:block}</style></noscript><meta charSet=\"utf-8\"/><meta name=\"viewport\" content=\"width=device-width\"/><meta name=\"next-head-count\" content=\"2\"/><noscript data-n-css=\"\"></noscript><script defer=\"\" nomodule=\"\" src=\"/_next/static/chunks/polyfills.js?ts=1629147111937\"></script><script src=\"/_next/static/chunks/webpack.js?ts=1629147111937\" defer=\"\"></script><script src=\"/_next/static/chunks/main.js?ts=1629147111937\" defer=\"\"></script><script src=\"/_next/static/chunks/pages/_app.js?ts=1629147111937\" defer=\"\"></script><script src=\"/_next/static/chunks/pages/suspense/unwrapped.js?ts=1629147111937\" defer=\"\"></script><script src=\"/_next/static/development/_buildManifest.js?ts=1629147111937\" defer=\"\"></script><script src=\"/_next/static/development/_ssgManifest.js?ts=1629147111937\" defer=\"\"></script><noscript id=\"__next_css__DO_NOT_USE__\"></noscript></head><body><div id=\"__next\"><p>hello <!-- -->18.0.0-c76e4dbbc-20210722<!-- --></p></div><script src=\"/_next/static/chunks/react-refresh.js?ts=1629147111937\"></script><script id=\"__NEXT_DATA__\" type=\"application/json\">{\"props\":{\"pageProps\":{}},\"page\":\"/suspense/unwrapped\",\"query\":{},\"buildId\":\"development\",\"nextExport\":true,\"autoExport\":true,\"isFallback\":false,\"scriptLoader\":[]}</script></body></html>"

  132 |     await killApp(app)
  133 |     // expect(html).toContain('Disallowed suspense option usage with next/dynamic')
> 134 |     expect(html).toContain(
      |                  ^
  135 |       'A React component suspended while rendering, but no fallback UI was specified'
  136 |     )
  137 |   })

  at Object.<anonymous> (integration/react-18/test/index.test.js:134:18)

● Blocking mode › concurrentFeatures is disabled (dev) › should render fallback on server side if suspense without preload

expect(received).toBe(expected) // Object.is equality

Expected: "rab"
Received: "barfoo"

  13 |     const nextData = JSON.parse($('#__NEXT_DATA__').text())
  14 |     const content = $('#__next').text()
> 15 |     expect(content).toBe('rab')
     |                     ^
  16 |     expect(nextData.dynamicIds).toBeUndefined()
  17 |   })
  18 |

  at Object.<anonymous> (integration/react-18/test/blocking.js:15:21)

● Blocking mode › concurrentFeatures is disabled (dev) › should render fallback on server side if suspended on server with preload

expect(received).toContain(expected) // indexOf

Expected substring: "loading"
Received string:    "<div id=\"__next\"><!--$--><p>hello <!-- -->18.0.0-c76e4dbbc-20210722<!-- --></p><!--/$--></div><script src=\"/_next/static/chunks/react-refresh.js?ts=1629147117903\"></script><script id=\"__NEXT_DATA__\" type=\"application/json\">{\"props\":{\"pageProps\":{}},\"page\":\"/suspense/thrown\",\"query\":{},\"buildId\":\"development\",\"nextExport\":true,\"autoExport\":true,\"isFallback\":false,\"scriptLoader\":[]}</script>"

  20 |     const $ = await get$('/suspense/thrown')
  21 |     const html = $('body').html()
> 22 |     expect(html).toContain('loading')
     |                  ^
  23 |     expect(JSON.parse($('#__NEXT_DATA__').text()).dynamicIds).toBeUndefined()
  24 |   })
  25 | }

  at Object.<anonymous> (integration/react-18/test/blocking.js:22:18)

● Blocking mode › concurrentFeatures is disabled (prod) › should render fallback on server side if suspense without preload

expect(received).toBe(expected) // Object.is equality

Expected: "rab"
Received: "barfoo"

  13 |     const nextData = JSON.parse($('#__NEXT_DATA__').text())
  14 |     const content = $('#__next').text()
> 15 |     expect(content).toBe('rab')
     |                     ^
  16 |     expect(nextData.dynamicIds).toBeUndefined()
  17 |   })
  18 |

  at Object.<anonymous> (integration/react-18/test/blocking.js:15:21)

● Blocking mode › concurrentFeatures is disabled (prod) › should render fallback on server side if suspended on server with preload

expect(received).toContain(expected) // indexOf

Expected substring: "loading"
Received string:    "<div id=\"__next\"><!--$--><p>hello <!-- -->18.0.0-c76e4dbbc-20210722<!-- --></p><!--/$--></div><script id=\"__NEXT_DATA__\" type=\"application/json\">{\"props\":{\"pageProps\":{}},\"page\":\"/suspense/thrown\",\"query\":{},\"buildId\":\"aqKjIFXeE5eB7h_0xQqFy\",\"nextExport\":true,\"autoExport\":true,\"isFallback\":false,\"scriptLoader\":[]}</script>"

  20 |     const $ = await get$('/suspense/thrown')
  21 |     const html = $('body').html()
> 22 |     expect(html).toContain('loading')
     |                  ^
  23 |     expect(JSON.parse($('#__NEXT_DATA__').text()).dynamicIds).toBeUndefined()
  24 |   })
  25 | }

  at Object.<anonymous> (integration/react-18/test/blocking.js:22:18)

@ijjk
Copy link
Member

ijjk commented Aug 16, 2021

Stats from current PR

Default Build (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
buildDuration 16.6s 16.8s ⚠️ +153ms
buildDurationCached 4.2s 4.2s -13ms
nodeModulesSize 49.7 MB 49.7 MB ⚠️ +53.9 kB
Page Load Tests Overall increase ✓
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
/ failed reqs 0 0
/ total time (seconds) 3.395 3.268 -0.13
/ avg req/sec 736.47 765.09 +28.62
/error-in-render failed reqs 0 0
/error-in-render total time (seconds) 2.005 2.012 ⚠️ +0.01
/error-in-render avg req/sec 1246.81 1242.66 ⚠️ -4.15
Client Bundles (main, webpack, commons)
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
745.HASH.js gzip 179 B 179 B
framework-HASH.js gzip 42.2 kB 42.2 kB
main-HASH.js gzip 23.1 kB 23.1 kB
webpack-HASH.js gzip 1.44 kB 1.44 kB
Overall change 67 kB 67 kB
Legacy Client Bundles (polyfills)
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
polyfills-a4..dd70.js gzip 31 kB 31 kB
Overall change 31 kB 31 kB
Client Pages
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
_app-HASH.js gzip 980 B 980 B
_error-HASH.js gzip 194 B 194 B
amp-HASH.js gzip 312 B 312 B
css-HASH.js gzip 329 B 329 B
dynamic-HASH.js gzip 2.64 kB 2.64 kB
head-HASH.js gzip 350 B 350 B
hooks-HASH.js gzip 904 B 904 B
image-HASH.js gzip 4.13 kB 4.13 kB
index-HASH.js gzip 261 B 261 B
link-HASH.js gzip 1.66 kB 1.66 kB
routerDirect..HASH.js gzip 319 B 319 B
script-HASH.js gzip 387 B 387 B
withRouter-HASH.js gzip 320 B 320 B
bb14e60e810b..30f.css gzip 125 B 125 B
Overall change 12.9 kB 12.9 kB
Client Build Manifests
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
_buildManifest.js gzip 491 B 491 B
Overall change 491 B 491 B
Rendered Page Sizes
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
index.html gzip 540 B 540 B
link.html gzip 551 B 551 B
withRouter.html gzip 532 B 532 B
Overall change 1.62 kB 1.62 kB

Webpack 4 Mode
General Overall increase ⚠️
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
buildDuration 13.5s 13.4s -54ms
buildDurationCached 5.6s 5.5s -89ms
nodeModulesSize 49.7 MB 49.7 MB ⚠️ +53.9 kB
Page Load Tests Overall increase ✓
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
/ failed reqs 0 0
/ total time (seconds) 3.397 3.359 -0.04
/ avg req/sec 735.86 744.32 +8.46
/error-in-render failed reqs 0 0
/error-in-render total time (seconds) 2.085 2.097 ⚠️ +0.01
/error-in-render avg req/sec 1199.09 1192.31 ⚠️ -6.78
Client Bundles (main, webpack, commons)
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
16.HASH.js gzip 186 B 186 B
677f882d2ed8..HASH.js gzip 14 kB 14 kB
framework.HASH.js gzip 41.9 kB 41.9 kB
main-HASH.js gzip 10.6 kB 10.6 kB
webpack-HASH.js gzip 1.19 kB 1.19 kB
Overall change 67.9 kB 67.9 kB
Legacy Client Bundles (polyfills)
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
polyfills-a4..dd70.js gzip 31 kB 31 kB
Overall change 31 kB 31 kB
Client Pages
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
_app-HASH.js gzip 965 B 965 B
_error-HASH.js gzip 3.71 kB 3.71 kB
amp-HASH.js gzip 552 B 552 B
css-HASH.js gzip 333 B 333 B
dynamic-HASH.js gzip 2.83 kB 2.83 kB
head-HASH.js gzip 2.97 kB 2.97 kB
hooks-HASH.js gzip 911 B 911 B
index-HASH.js gzip 231 B 231 B
link-HASH.js gzip 1.64 kB 1.64 kB
routerDirect..HASH.js gzip 298 B 298 B
script-HASH.js gzip 2.95 kB 2.95 kB
withRouter-HASH.js gzip 294 B 294 B
e025d2764813..52f.css gzip 125 B 125 B
Overall change 17.8 kB 17.8 kB
Client Build Manifests
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
_buildManifest.js gzip 498 B 498 B
Overall change 498 B 498 B
Rendered Page Sizes
vercel/next.js canary azukaru/next.js x-modern-legacy-doc-support Change
index.html gzip 584 B 584 B
link.html gzip 596 B 596 B
withRouter.html gzip 578 B 578 B
Overall change 1.76 kB 1.76 kB
Commit: 4302ab4

@ijjk
Copy link
Member

ijjk commented Aug 17, 2021

Failing test suites

Commit: 4302ab4

test/integration/react-18/test/index.test.js

  • Basics > suspense is not allowed in blocking rendering mode (dev)
  • Basics > default setting with react 18 (dev) > hydrates correctly for normal page
  • Basics > default setting with react 18 (dev) > should works with suspense in ssg
  • Basics > default setting with react 18 (dev) > should render fallback without preloads on server side
  • Basics > default setting with react 18 (prod) > hydrates correctly for normal page
  • Basics > default setting with react 18 (prod) > should works with suspense in ssg
  • Basics > default setting with react 18 (prod) > should render fallback without preloads on server side
  • Blocking mode > concurrentFeatures is disabled (dev) > should render fallback on server side if suspense without preload
  • Blocking mode > concurrentFeatures is disabled (dev) > should render fallback on server side if suspended on server with preload
  • Blocking mode > concurrentFeatures is disabled (prod) > should render fallback on server side if suspense without preload
  • Blocking mode > concurrentFeatures is disabled (prod) > should render fallback on server side if suspended on server with preload
  • Concurrent mode > concurrentFeatures is enabled (dev) > should resolve suspense modules on server side if suspense
  • Concurrent mode > concurrentFeatures is enabled (dev) > should resolve suspense on server side if not suspended on server
  • Concurrent mode > concurrentFeatures is enabled (dev) > should resolve suspense on server side if suspended on server
  • Concurrent mode > concurrentFeatures is enabled (dev) > should hydrate suspenses on client side if suspended on server
  • Concurrent mode > concurrentFeatures is enabled (prod) > should resolve suspense modules on server side if suspense
  • Concurrent mode > concurrentFeatures is enabled (prod) > should resolve suspense on server side if not suspended on server
  • Concurrent mode > concurrentFeatures is enabled (prod) > should resolve suspense on server side if suspended on server
  • Concurrent mode > concurrentFeatures is enabled (prod) > should hydrate suspenses on client side if suspended on server
Expand output

● Basics › default setting with react 18 (dev) › hydrates correctly for normal page

thrown: "Exceeded timeout of 300000 ms for a test.
Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."

   6 |
   7 | export default (context) => {
>  8 |   it('hydrates correctly for normal page', async () => {
     |   ^
   9 |     const browser = await webdriver(context.appPort, '/')
  10 |     expect(await browser.eval('window.didHydrate')).toBe(true)
  11 |     expect(await browser.elementById('react-dom-version').text()).toMatch(/18/)

  at _default (integration/react-18/test/basics.js:8:3)
  at fn (integration/react-18/test/index.test.js:123:58)
  at integration/react-18/test/index.test.js:192:5
  at runTest (integration/react-18/test/index.test.js:175:3)
  at runTests (integration/react-18/test/index.test.js:197:3)
  at integration/react-18/test/index.test.js:123:3

● Basics › default setting with react 18 (dev) › should works with suspense in ssg

thrown: "Exceeded timeout of 300000 ms for a test.
Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."

  12 |   })
  13 |
> 14 |   it('should works with suspense in ssg', async () => {
     |   ^
  15 |     const res1 = await fetchViaHTTP(context.appPort, '/suspense/thrown')
  16 |     const res2 = await fetchViaHTTP(context.appPort, '/suspense/no-thrown')
  17 |

  at _default (integration/react-18/test/basics.js:14:3)
  at fn (integration/react-18/test/index.test.js:123:58)
  at integration/react-18/test/index.test.js:192:5
  at runTest (integration/react-18/test/index.test.js:175:3)
  at runTests (integration/react-18/test/index.test.js:197:3)
  at integration/react-18/test/index.test.js:123:3

● Basics › default setting with react 18 (dev) › should render fallback without preloads on server side

thrown: "Exceeded timeout of 300000 ms for a test.
Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."

  20 |   })
  21 |
> 22 |   it('should render fallback without preloads on server side', async () => {
     |   ^
  23 |     const html = await renderViaHTTP(context.appPort, '/suspense/no-preload')
  24 |     const $ = cheerio.load(html)
  25 |     const nextData = JSON.parse($('#__NEXT_DATA__').text())

  at _default (integration/react-18/test/basics.js:22:3)
  at fn (integration/react-18/test/index.test.js:123:58)
  at integration/react-18/test/index.test.js:192:5
  at runTest (integration/react-18/test/index.test.js:175:3)
  at runTests (integration/react-18/test/index.test.js:197:3)
  at integration/react-18/test/index.test.js:123:3

● Basics › default setting with react 18 (prod) › hydrates correctly for normal page

command failed with code 1

  160 |         code !== 0
  161 |       ) {
> 162 |         return reject(new Error(`command failed with code ${code}`))
      |                       ^
  163 |       }
  164 |
  165 |       resolve({

  at ChildProcess.<anonymous> (lib/next-test-utils.js:162:23)

● Basics › default setting with react 18 (prod) › should works with suspense in ssg

command failed with code 1

  160 |         code !== 0
  161 |       ) {
> 162 |         return reject(new Error(`command failed with code ${code}`))
      |                       ^
  163 |       }
  164 |
  165 |       resolve({

  at ChildProcess.<anonymous> (lib/next-test-utils.js:162:23)

● Basics › default setting with react 18 (prod) › should render fallback without preloads on server side

command failed with code 1

  160 |         code !== 0
  161 |       ) {
> 162 |         return reject(new Error(`command failed with code ${code}`))
      |                       ^
  163 |       }
  164 |
  165 |       resolve({

  at ChildProcess.<anonymous> (lib/next-test-utils.js:162:23)

● Basics › suspense is not allowed in blocking rendering mode (dev)

Failed to replace content.

Pattern: wrapped = true

Content: import React, { Suspense } from 'react'
import dynamic from 'next/dynamic'

// flag for testing
const wrapped = false

const Hello = dynamic(() => import('../../components/hello'), {
  suspense: true,
})

export default function Unwrapped() {
  if (!wrapped) return <Hello />

  return (
    <Suspense fallback={`loading`}>
      <Hello />
    </Suspense>
  )
}

  453 |     } else if (typeof pattern === 'string') {
  454 |       if (!currentContent.includes(pattern)) {
> 455 |         throw new Error(
      |               ^
  456 |           `Failed to replace content.\n\nPattern: ${pattern}\n\nContent: ${currentContent}`
  457 |         )
  458 |       }

  at File.replace (lib/next-test-utils.js:455:15)
  at Object.<anonymous> (integration/react-18/test/index.test.js:127:19)

● Blocking mode › concurrentFeatures is disabled (dev) › should render fallback on server side if suspense without preload

thrown: "Exceeded timeout of 300000 ms for a test.
Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."

   9 |   }
  10 |
> 11 |   it('should render fallback on server side if suspense without preload', async () => {
     |   ^
  12 |     const $ = await get$('/suspense/no-preload')
  13 |     const nextData = JSON.parse($('#__NEXT_DATA__').text())
  14 |     const content = $('#__next').text()

  at _default (integration/react-18/test/blocking.js:11:3)
  at fn (integration/react-18/test/index.test.js:149:5)
  at integration/react-18/test/index.test.js:192:5
  at runTest (integration/react-18/test/index.test.js:175:3)
  at runTests (integration/react-18/test/index.test.js:197:3)
  at integration/react-18/test/index.test.js:148:3

● Blocking mode › concurrentFeatures is disabled (dev) › should render fallback on server side if suspended on server with preload

thrown: "Exceeded timeout of 300000 ms for a test.
Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."

  17 |   })
  18 |
> 19 |   it('should render fallback on server side if suspended on server with preload', async () => {
     |   ^
  20 |     const $ = await get$('/suspense/thrown')
  21 |     const html = $('body').html()
  22 |     expect(html).toContain('loading')

  at _default (integration/react-18/test/blocking.js:19:3)
  at fn (integration/react-18/test/index.test.js:149:5)
  at integration/react-18/test/index.test.js:192:5
  at runTest (integration/react-18/test/index.test.js:175:3)
  at runTests (integration/react-18/test/index.test.js:197:3)
  at integration/react-18/test/index.test.js:148:3

● Blocking mode › concurrentFeatures is disabled (prod) › should render fallback on server side if suspense without preload

command failed with code 1

  160 |         code !== 0
  161 |       ) {
> 162 |         return reject(new Error(`command failed with code ${code}`))
      |                       ^
  163 |       }
  164 |
  165 |       resolve({

  at ChildProcess.<anonymous> (lib/next-test-utils.js:162:23)

● Blocking mode › concurrentFeatures is disabled (prod) › should render fallback on server side if suspended on server with preload

command failed with code 1

  160 |         code !== 0
  161 |       ) {
> 162 |         return reject(new Error(`command failed with code ${code}`))
      |                       ^
  163 |       }
  164 |
  165 |       resolve({

  at ChildProcess.<anonymous> (lib/next-test-utils.js:162:23)

● Concurrent mode › concurrentFeatures is enabled (dev) › should resolve suspense modules on server side if suspense

thrown: "Exceeded timeout of 300000 ms for a test.
Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."

  11 |   }
  12 |
> 13 |   it('should resolve suspense modules on server side if suspense', async () => {
     |   ^
  14 |     const $ = await get$('/suspense/no-preload')
  15 |     const nextData = JSON.parse($('#__NEXT_DATA__').text())
  16 |     const content = $('#__next').text()

  at _default (integration/react-18/test/concurrent.js:13:3)
  at fn (integration/react-18/test/index.test.js:169:5)
  at integration/react-18/test/index.test.js:192:5
  at runTest (integration/react-18/test/index.test.js:175:3)
  at runTests (integration/react-18/test/index.test.js:197:3)
  at integration/react-18/test/index.test.js:168:3

● Concurrent mode › concurrentFeatures is enabled (dev) › should resolve suspense on server side if not suspended on server

thrown: "Exceeded timeout of 300000 ms for a test.
Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."

  19 |   })
  20 |
> 21 |   it('should resolve suspense on server side if not suspended on server', async () => {
     |   ^
  22 |     const $ = await get$('/suspense/no-thrown')
  23 |     const html = $('body').html()
  24 |     // there might be html comments between text, test hello only

  at _default (integration/react-18/test/concurrent.js:21:3)
  at fn (integration/react-18/test/index.test.js:169:5)
  at integration/react-18/test/index.test.js:192:5
  at runTest (integration/react-18/test/index.test.js:175:3)
  at runTests (integration/react-18/test/index.test.js:197:3)
  at integration/react-18/test/index.test.js:168:3

● Concurrent mode › concurrentFeatures is enabled (dev) › should resolve suspense on server side if suspended on server

thrown: "Exceeded timeout of 300000 ms for a test.
Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."

  27 |   })
  28 |
> 29 |   it('should resolve suspense on server side if suspended on server', async () => {
     |   ^
  30 |     const $ = await get$('/suspense/thrown')
  31 |     const html = $('body').html()
  32 |     expect(html).toContain('hello')

  at _default (integration/react-18/test/concurrent.js:29:3)
  at fn (integration/react-18/test/index.test.js:169:5)
  at integration/react-18/test/index.test.js:192:5
  at runTest (integration/react-18/test/index.test.js:175:3)
  at runTests (integration/react-18/test/index.test.js:197:3)
  at integration/react-18/test/index.test.js:168:3

● Concurrent mode › concurrentFeatures is enabled (dev) › should hydrate suspenses on client side if suspended on server

thrown: "Exceeded timeout of 300000 ms for a test.
Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."

  34 |   })
  35 |
> 36 |   it('should hydrate suspenses on client side if suspended on server', async () => {
     |   ^
  37 |     let browser
  38 |     try {
  39 |       browser = await webdriver(context.appPort, '/suspense/thrown')

  at _default (integration/react-18/test/concurrent.js:36:3)
  at fn (integration/react-18/test/index.test.js:169:5)
  at integration/react-18/test/index.test.js:192:5
  at runTest (integration/react-18/test/index.test.js:175:3)
  at runTests (integration/react-18/test/index.test.js:197:3)
  at integration/react-18/test/index.test.js:168:3

● Concurrent mode › concurrentFeatures is enabled (prod) › should resolve suspense modules on server side if suspense

command failed with code 1

  160 |         code !== 0
  161 |       ) {
> 162 |         return reject(new Error(`command failed with code ${code}`))
      |                       ^
  163 |       }
  164 |
  165 |       resolve({

  at ChildProcess.<anonymous> (lib/next-test-utils.js:162:23)

● Concurrent mode › concurrentFeatures is enabled (prod) › should resolve suspense on server side if not suspended on server

command failed with code 1

  160 |         code !== 0
  161 |       ) {
> 162 |         return reject(new Error(`command failed with code ${code}`))
      |                       ^
  163 |       }
  164 |
  165 |       resolve({

  at ChildProcess.<anonymous> (lib/next-test-utils.js:162:23)

● Concurrent mode › concurrentFeatures is enabled (prod) › should resolve suspense on server side if suspended on server

command failed with code 1

  160 |         code !== 0
  161 |       ) {
> 162 |         return reject(new Error(`command failed with code ${code}`))
      |                       ^
  163 |       }
  164 |
  165 |       resolve({

  at ChildProcess.<anonymous> (lib/next-test-utils.js:162:23)

● Concurrent mode › concurrentFeatures is enabled (prod) › should hydrate suspenses on client side if suspended on server

command failed with code 1

  160 |         code !== 0
  161 |       ) {
> 162 |         return reject(new Error(`command failed with code ${code}`))
      |                       ^
  163 |       }
  164 |
  165 |       resolve({

  at ChildProcess.<anonymous> (lib/next-test-utils.js:162:23)

● Test suite failed to run

TypeError: Cannot read property 'pid' of undefined

  315 | export async function killApp(instance) {
  316 |   await new Promise((resolve, reject) => {
> 317 |     treeKill(instance.pid, (err) => {
      |                       ^
  318 |       if (err) {
  319 |         if (
  320 |           process.platform === 'win32' &&

  at lib/next-test-utils.js:317:23
  at killApp (lib/next-test-utils.js:316:9)
  at integration/react-18/test/index.test.js:190:13

● Test suite failed to run

TypeError: Cannot read property 'pid' of undefined

  315 | export async function killApp(instance) {
  316 |   await new Promise((resolve, reject) => {
> 317 |     treeKill(instance.pid, (err) => {
      |                       ^
  318 |       if (err) {
  319 |         if (
  320 |           process.platform === 'win32' &&

  at lib/next-test-utils.js:317:23
  at killApp (lib/next-test-utils.js:316:9)
  at integration/react-18/test/index.test.js:190:13

● Test suite failed to run

TypeError: Cannot read property 'pid' of undefined

  315 | export async function killApp(instance) {
  316 |   await new Promise((resolve, reject) => {
> 317 |     treeKill(instance.pid, (err) => {
      |                       ^
  318 |       if (err) {
  319 |         if (
  320 |           process.platform === 'win32' &&

  at lib/next-test-utils.js:317:23
  at killApp (lib/next-test-utils.js:316:9)
  at integration/react-18/test/index.test.js:190:13

@devknoll devknoll closed this Aug 25, 2021
@vercel vercel locked as resolved and limited conversation to collaborators Jan 27, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
created-by: Chrome Aurora PRs by the Google Chrome team: https://web.dev/aurora type: next
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants