first commit
Some checks failed
Test examples / Test Examples (20) (push) Has been cancelled
Test examples / Test Examples (22) (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Trigger Release / start (push) Has been cancelled
Stale issue handler / stale (push) Has been cancelled
Update Font Data / create-pull-request (push) Has been cancelled
build-and-deploy / deploy-target (push) Has been cancelled
build-and-deploy / build (push) Has been cancelled
build-and-deploy / stable - aarch64-unknown-linux-musl - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-unknown-linux-musl - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-unknown-linux-gnu - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-unknown-linux-gnu - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-pc-windows-msvc - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-pc-windows-msvc - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-apple-darwin - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-apple-darwin - node@16 (push) Has been cancelled
build-and-deploy / build-wasm (nodejs) (push) Has been cancelled
build-and-deploy / build-wasm (web) (push) Has been cancelled
build-and-deploy / Deploy preview tarball (push) Has been cancelled
build-and-deploy / Potentially publish release (push) Has been cancelled
build-and-deploy / publish-turbopack-npm-packages (push) Has been cancelled
build-and-deploy / Deploy examples (push) Has been cancelled
build-and-deploy / thank you, build (push) Has been cancelled
build-and-deploy / Upload Turbopack Bytesize metrics to Datadog (push) Has been cancelled
Rspack Next.js development integration tests / Rspack integration tests (push) Has been cancelled
Rspack Next.js production integration tests / Rspack integration tests (push) Has been cancelled
Turbopack Next.js development integration tests / Next.js integration tests (push) Has been cancelled
Turbopack Next.js production integration tests / Next.js integration tests (push) Has been cancelled
Update Rspack test manifest / Update and upload Rspack development test manifest (push) Has been cancelled
Update Rspack test manifest / Update and upload Rspack production test manifest (push) Has been cancelled
Upload bundler test manifests to areweturboyet.com / Upload test results (push) Has been cancelled
Update React / create-pull-request (push) Has been cancelled
test-e2e-project-reset-cron / reset-test-project (push) Has been cancelled
Notify about the top 15 issues/PRs/feature requests (most reacted) in the last 90 days / run (push) Has been cancelled

This commit is contained in:
Arian Tron
2026-03-10 19:37:31 +03:30
commit 61f56f997c
27684 changed files with 2784175 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
import React from 'react'
window.ua = navigator.userAgent
export default function Component() {
return <p>esm.mjs</p>
}

View File

@@ -0,0 +1 @@
export default () => <div>test chunkfilename</div>

View File

@@ -0,0 +1,13 @@
import React from 'react'
import PropTypes from 'prop-types'
export default class extends React.Component {
static contextTypes = {
data: PropTypes.object,
}
render() {
const { data } = this.context
return <div>{data.title}</div>
}
}

View File

@@ -0,0 +1 @@
export default () => <p>Hello World 1</p>

View File

@@ -0,0 +1 @@
export default () => <p>Hello World 2</p>

View File

@@ -0,0 +1 @@
export default () => <p>Hello World 1</p>

View File

@@ -0,0 +1 @@
export default () => <p>Hello World 2</p>

View File

@@ -0,0 +1,10 @@
import dynamic from 'next/dynamic'
const Nested2 = dynamic(() => import('./nested2'))
export default () => (
<div>
Nested 1
<Nested2 />
</div>
)

View File

@@ -0,0 +1,12 @@
import dynamic from 'next/dynamic'
const BrowserLoaded = dynamic(async () => () => <div>Browser hydrated</div>, {
ssr: false,
})
export default () => (
<div>
<div>Nested 2</div>
<BrowserLoaded />
</div>
)

View File

@@ -0,0 +1,5 @@
window.ua = navigator.userAgent
export default function PureClient() {
return <p id="pure-client">navigator</p>
}

View File

@@ -0,0 +1,17 @@
import React from 'react'
export default class Welcome extends React.Component {
state = { name: null }
componentDidMount() {
const { name } = this.props
this.setState({ name })
}
render() {
const { name } = this.state
if (!name) return null
return <p>Welcome, {name}</p>
}
}

View File

@@ -0,0 +1,3 @@
process.env.TEST_BABEL = '1'
process.env.TEST_SRC_DIR = '1'
require('./next-dynamic.test')

View File

@@ -0,0 +1,2 @@
process.env.TEST_BABEL = '1'
require('./next-dynamic.test')

View File

@@ -0,0 +1,2 @@
process.env.TEST_BASE_PATH = '/docs'
require('./next-dynamic.test')

View File

@@ -0,0 +1,2 @@
process.env.TEST_CUSTOMIZED_DOCUMENT = '1'
require('./next-dynamic.test')

View File

@@ -0,0 +1,325 @@
import { join } from 'path'
import cheerio from 'cheerio'
import webdriver from 'next-webdriver'
import { createNext, FileRef } from 'e2e-utils'
import { waitForNoRedbox, renderViaHTTP, check } from 'next-test-utils'
import { NextInstance } from 'e2e-utils'
const customDocumentGipContent = `\
import { Html, Main, NextScript, Head } from 'next/document'
export default function Document() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
Document.getInitialProps = (ctx) => {
return ctx.defaultGetInitialProps(ctx)
}
`
const basePath = process.env.TEST_BASE_PATH || ''
const srcPrefix = process.env.TEST_SRC_DIR ? 'src/' : ''
describe('next/dynamic', () => {
let next: NextInstance
beforeAll(async () => {
next = await createNext({
files: {
[`${srcPrefix}/components`]: new FileRef(join(__dirname, 'components')),
[`${srcPrefix}/pages`]: new FileRef(join(__dirname, 'pages')),
...(process.env.TEST_CUSTOMIZED_DOCUMENT === '1' && {
[`${srcPrefix}/pages/_document.js`]: customDocumentGipContent,
}),
// When it's not turbopack and babel is enabled, we add a .babelrc file.
...(!process.env.IS_TURBOPACK_TEST &&
process.env.TEST_BABEL === '1' && {
'.babelrc': `{ "presets": ["next/babel"] }`,
}),
},
nextConfig: {
basePath,
},
})
})
afterAll(() => next.destroy())
async function get$(path, query?: any) {
const html = await renderViaHTTP(next.url, path, query)
return cheerio.load(html)
}
// Turbopack doesn't support babel.
;(process.env.IS_TURBOPACK_TEST && process.env.TEST_BABEL === '1'
? describe.skip
: describe)('Dynamic import', () => {
describe('default behavior', () => {
it('should render dynamic import components', async () => {
const $ = await get$(basePath + '/dynamic/ssr')
// Make sure the client side knows it has to wait for the bundle
expect(JSON.parse($('#__NEXT_DATA__').html()).dynamicIds).toContain(
process.env.IS_TURBOPACK_TEST
? '[project]/components/hello1.js [client] (ecmascript, next/dynamic entry)'
: 'pages/dynamic/ssr.js -> ../../components/hello1'
)
expect($('body').text()).toMatch(/Hello World 1/)
})
it('should render dynamic import components using a function as first parameter', async () => {
const $ = await get$(basePath + '/dynamic/function')
// Make sure the client side knows it has to wait for the bundle
expect(JSON.parse($('#__NEXT_DATA__').html()).dynamicIds).toContain(
process.env.IS_TURBOPACK_TEST
? '[project]/components/hello1.js [client] (ecmascript, next/dynamic entry)'
: 'pages/dynamic/function.js -> ../../components/hello1'
)
expect($('body').text()).toMatch(/Hello World 1/)
})
it('should render even there are no physical chunk exists', async () => {
let browser
try {
browser = await webdriver(next.url, basePath + '/dynamic/no-chunk')
await check(
() => browser.elementByCss('body').text(),
/Welcome, normal/
)
await check(
() => browser.elementByCss('body').text(),
/Welcome, dynamic/
)
} finally {
if (browser) {
await browser.close()
}
}
})
it('should SSR nested dynamic components and skip nonSSR ones', async () => {
const $ = await get$(basePath + '/dynamic/nested')
const text = $('#__next').text()
expect(text).toContain('Nested 1')
expect(text).toContain('Nested 2')
expect(text).not.toContain('Browser hydrated')
})
it('should hydrate nested chunks', async () => {
let browser
try {
browser = await webdriver(next.url, basePath + '/dynamic/nested')
await check(() => browser.elementByCss('body').text(), /Nested 1/)
await check(() => browser.elementByCss('body').text(), /Nested 2/)
await check(
() => browser.elementByCss('body').text(),
/Browser hydrated/
)
if ((global as any).browserName === 'chrome') {
const logs = await browser.log()
logs.forEach((logItem) => {
expect(logItem.message).not.toMatch(
/Expected server HTML to contain/
)
})
}
} finally {
if (browser) {
await browser.close()
}
}
})
it('should render the component Head content', async () => {
let browser
try {
browser = await webdriver(next.url, basePath + '/dynamic/head')
await check(() => browser.elementByCss('body').text(), /test/)
const backgroundColor = await browser
.elementByCss('.dynamic-style')
.getComputedCss('background-color')
const height = await browser
.elementByCss('.dynamic-style')
.getComputedCss('height')
expect(height).toBe('200px')
expect(backgroundColor).toMatch(/rgba?\(0, 128, 0/)
} finally {
if (browser) {
await browser.close()
}
}
})
})
describe('ssr:false option', () => {
it('should not render loading on the server side', async () => {
const $ = await get$(basePath + '/dynamic/no-ssr')
expect($('body').html()).not.toContain('"dynamicIds"')
expect($('body').text()).not.toMatch('loading...')
})
it('should render the component on client side', async () => {
let browser
try {
browser = await webdriver(next.url, basePath + '/dynamic/no-ssr')
await check(() => browser.elementByCss('body').text(), /navigator/)
await waitForNoRedbox(browser)
} finally {
if (browser) {
await browser.close()
}
}
})
it('should import and render the ESM module correctly on client side', async () => {
let browser
try {
browser = await webdriver(next.url, basePath + '/dynamic/no-ssr-esm')
await check(() => browser.elementByCss('body').text(), /esm.mjs/)
await waitForNoRedbox(browser)
} finally {
if (browser) {
await browser.close()
}
}
})
})
describe('ssr:true option', () => {
it('Should render the component on the server side', async () => {
const $ = await get$(basePath + '/dynamic/ssr-true')
expect($('body').html()).toContain('"dynamicIds"')
expect($('p').text()).toBe('Hello World 1')
})
it('should render the component on client side', async () => {
let browser
try {
browser = await webdriver(next.url, basePath + '/dynamic/ssr-true')
await check(
() => browser.elementByCss('body').text(),
/Hello World 1/
)
} finally {
if (browser) {
await browser.close()
}
}
})
if (!(global as any).isNextDev) {
it('should not include ssr:false imports to server trace', async () => {
const trace = JSON.parse(
await next.readFile('.next/server/pages/dynamic/no-ssr.js.nft.json')
) as { files: string[] }
expect(trace).not.toContain('navigator')
})
}
})
// Turbopack doesn't have this feature.
;(process.env.IS_TURBOPACK_TEST ? describe.skip : describe)(
'custom chunkfilename',
() => {
it('should render the correct filename', async () => {
const $ = await get$(basePath + '/dynamic/chunkfilename')
expect($('body').text()).toMatch(/test chunkfilename/)
expect($('html').html()).toMatch(/hello-world\.js/)
})
it('should render the component on client side', async () => {
let browser
try {
browser = await webdriver(
next.url,
basePath + '/dynamic/chunkfilename'
)
await check(
() => browser.elementByCss('body').text(),
/test chunkfilename/
)
} finally {
if (browser) {
await browser.close()
}
}
})
}
)
describe('custom loading', () => {
it('should render custom loading on the server side when `ssr:false` and `loading` is provided', async () => {
const $ = await get$(basePath + '/dynamic/no-ssr-custom-loading')
expect($('p').text()).toBe('LOADING')
})
it('should render the component on client side', async () => {
let browser
try {
browser = await webdriver(
next.url,
basePath + '/dynamic/no-ssr-custom-loading'
)
await check(
() => browser.elementByCss('body').text(),
/Hello World 1/
)
} finally {
if (browser) {
await browser.close()
}
}
})
})
// TODO: Make this test work with Turbopack. Currently the test relies on `chunkFileName` which is not supported by Turbopack.
;(process.env.IS_TURBOPACK_TEST ? describe.skip : describe)(
'Multiple modules',
() => {
it('should only include the rendered module script tag', async () => {
const $ = await get$(basePath + '/dynamic/multiple-modules')
const html = $('html').html()
expect(html).toMatch(/hello1\.js/)
expect(html).not.toMatch(/hello2\.js/)
})
it('should only load the rendered module in the browser', async () => {
let browser
try {
browser = await webdriver(
next.url,
basePath + '/dynamic/multiple-modules'
)
const html = await browser.eval(
'document.documentElement.innerHTML'
)
expect(html).toMatch(/hello1\.js/)
expect(html).not.toMatch(/hello2\.js/)
} finally {
if (browser) {
await browser.close()
}
}
})
it('should only render one bundle if component is used multiple times', async () => {
const $ = await get$(basePath + '/dynamic/multiple-modules')
const html = $('html').html()
try {
expect(html.match(/chunks[\\/]hello1\.js/g).length).toBe(1)
expect(html).not.toMatch(/hello2\.js/)
} catch (err) {
console.error(html)
throw err
}
})
}
)
})
})

View File

@@ -0,0 +1,9 @@
import dynamic from 'next/dynamic'
const Hello = dynamic(
import(
/* webpackChunkName: 'hello-world' */ '../../components/hello-chunkfilename'
)
)
export default Hello

View File

@@ -0,0 +1,5 @@
import dynamic from 'next/dynamic'
const Hello = dynamic(() => import('../../components/hello1'))
export default Hello

View File

@@ -0,0 +1,30 @@
import dynamic from 'next/dynamic'
import Head from 'next/head'
const Test = dynamic({
loader: async () => {
// component
return () => {
return (
<div className="dynamic-style">
<Head>
<style
dangerouslySetInnerHTML={{
__html: `
.dynamic-style {
background-color: green;
height: 200px;
}
`,
}}
/>
</Head>
test
</div>
)
}
},
ssr: false,
})
export default Test

View File

@@ -0,0 +1,7 @@
import Link from 'next/link'
export default () => (
<div>
<Link href="/dynamic/no-chunk">No Chunk</Link>
</div>
)

View File

@@ -0,0 +1,23 @@
/* eslint-disable */
import dynamic from 'next/dynamic'
const Hello = dynamic(
import(/* webpackChunkName: 'hello1' */ '../../components/hello3')
)
const Hello2 = dynamic(
import(/* webpackChunkName: 'hello2' */ '../../components/hello4')
)
export default () => {
return (
<div>
<Hello />
<Hello />
<Hello />
<Hello />
<Hello />
<Hello />
<Hello />
</div>
)
}

View File

@@ -0,0 +1,5 @@
import dynamic from 'next/dynamic'
const DynamicComponent = dynamic(() => import('../../components/nested1'))
export default DynamicComponent

View File

@@ -0,0 +1,11 @@
import dynamic from 'next/dynamic'
import Welcome from '../../components/welcome'
const Welcome2 = dynamic(import('../../components/welcome'))
export default () => (
<div>
<Welcome name="normal" />
<Welcome2 name="dynamic" />
</div>
)

View File

@@ -0,0 +1,8 @@
import dynamic from 'next/dynamic'
const Hello = dynamic(import('../../components/hello1'), {
ssr: false,
loading: () => <p>LOADING</p>,
})
export default Hello

View File

@@ -0,0 +1,5 @@
import dynamic from 'next/dynamic'
const Page = dynamic(() => import('../../components/esm.mjs'), { ssr: false })
export default Page

View File

@@ -0,0 +1,7 @@
import dynamic from 'next/dynamic'
const PureClient = dynamic(import('../../components/pure-client'), {
ssr: false,
})
export default PureClient

View File

@@ -0,0 +1,5 @@
import dynamic from 'next/dynamic'
const Hello = dynamic(import('../../components/hello1'), { ssr: true })
export default Hello

View File

@@ -0,0 +1,5 @@
import dynamic from 'next/dynamic'
const Hello = dynamic(import('../../components/hello1'))
export default Hello