mirror of
https://github.com/hanzoai/next.js.git
synced 2026-09-24 17:00:51 +00:00
Previously, we created chunk list register chunks for every reachable chunk in the chunk graph on a page. Now, we only create one that subscribes to all recursively reachable assets. This has to pass around an explicit list of client references chunks as those cannot be discovered via the chunk graph alone. This results in a significant performance improvement when loading pages with the dev server, improving performance of a 60s cold build in a large app by about 10s.
142 lines
4.8 KiB
TypeScript
142 lines
4.8 KiB
TypeScript
import { join } from 'path'
|
|
import { nextTestSetup } from 'e2e-utils'
|
|
import { retry } from 'next-test-utils'
|
|
|
|
describe('hmr-dynamic-component', () => {
|
|
const { next } = nextTestSetup({
|
|
files: __dirname,
|
|
patchFileDelay: 500,
|
|
})
|
|
|
|
it('should update text in a dynamically-imported client component without a full reload', async () => {
|
|
const browser = await next.browser('/')
|
|
const componentPath = join('app', 'components', 'dynamic.tsx')
|
|
const originalContent = await next.readFile(componentPath)
|
|
try {
|
|
await retry(async () => {
|
|
const div = await browser.elementByCss('#dynamic-component')
|
|
expect(await div.text()).toContain('Dynamic Component')
|
|
})
|
|
|
|
const timeOrigin = await browser.eval('performance.timeOrigin')
|
|
|
|
const editedContent = originalContent.replace(
|
|
'Dynamic Component',
|
|
'Dynamic Component UPDATED'
|
|
)
|
|
|
|
await next.patchFile(componentPath, editedContent)
|
|
|
|
await retry(async () => {
|
|
const div = await browser.elementByCss('#dynamic-component')
|
|
expect(await div.text()).toContain('Dynamic Component UPDATED')
|
|
}, 10000)
|
|
|
|
// Ensure the page was updated via HMR and not a full reload
|
|
expect(await browser.eval('performance.timeOrigin')).toEqual(timeOrigin)
|
|
} finally {
|
|
await next.patchFile(componentPath, originalContent)
|
|
}
|
|
})
|
|
|
|
it('should update text via HMR after loading a button-triggered dynamic component', async () => {
|
|
const browser = await next.browser('/lazy')
|
|
const componentPath = join('app', 'components', 'dynamic.tsx')
|
|
const originalContent = await next.readFile(componentPath)
|
|
try {
|
|
// Click button to trigger the dynamic import
|
|
await browser.elementByCss('#load-button').click()
|
|
|
|
await retry(async () => {
|
|
const div = await browser.elementByCss('#dynamic-component')
|
|
expect(await div.text()).toContain('Dynamic Component')
|
|
})
|
|
|
|
const timeOrigin = await browser.eval('performance.timeOrigin')
|
|
|
|
await next.patchFile(
|
|
componentPath,
|
|
originalContent.replace(
|
|
'Dynamic Component',
|
|
'Dynamic Component UPDATED'
|
|
)
|
|
)
|
|
|
|
await retry(async () => {
|
|
const div = await browser.elementByCss('#dynamic-component')
|
|
expect(await div.text()).toContain('Dynamic Component UPDATED')
|
|
}, 10000)
|
|
|
|
// Ensure the page was updated via HMR and not a full reload
|
|
expect(await browser.eval('performance.timeOrigin')).toEqual(timeOrigin)
|
|
} finally {
|
|
await next.patchFile(componentPath, originalContent)
|
|
}
|
|
})
|
|
|
|
it('should load updated code when button is clicked after a code change', async () => {
|
|
const browser = await next.browser('/lazy')
|
|
const componentPath = join('app', 'components', 'dynamic.tsx')
|
|
const originalContent = await next.readFile(componentPath)
|
|
try {
|
|
// Patch the file before the dynamic component has been loaded
|
|
await next.patchFile(
|
|
componentPath,
|
|
originalContent.replace(
|
|
'Dynamic Component',
|
|
'Dynamic Component PRE-LOADED'
|
|
)
|
|
)
|
|
|
|
// Now click the button — the component should load with the updated code
|
|
await browser.elementByCss('#load-button').click()
|
|
|
|
await retry(async () => {
|
|
const div = await browser.elementByCss('#dynamic-component')
|
|
expect(await div.text()).toContain('Dynamic Component PRE-LOADED')
|
|
}, 10000)
|
|
} finally {
|
|
await next.patchFile(componentPath, originalContent)
|
|
}
|
|
})
|
|
|
|
it('should update styles in a dynamically-imported client component via HMR', async () => {
|
|
const browser = await next.browser('/')
|
|
const cssPath = join('app', 'components', 'dynamic.module.css')
|
|
const originalCss = await next.readFile(cssPath)
|
|
try {
|
|
await retry(async () => {
|
|
const div = await browser.elementByCss('#dynamic-component')
|
|
expect(await div.text()).toContain('Dynamic Component')
|
|
})
|
|
|
|
// Verify initial style
|
|
await retry(async () => {
|
|
const color = await browser.eval(
|
|
`window.getComputedStyle(document.getElementById('dynamic-component')).color`
|
|
)
|
|
expect(color).toBe('rgb(255, 0, 0)')
|
|
})
|
|
|
|
const timeOrigin = await browser.eval('performance.timeOrigin')
|
|
|
|
await next.patchFile(
|
|
cssPath,
|
|
originalCss.replace('color: red', 'color: blue')
|
|
)
|
|
|
|
await retry(async () => {
|
|
const color = await browser.eval(
|
|
`window.getComputedStyle(document.getElementById('dynamic-component')).color`
|
|
)
|
|
expect(color).toBe('rgb(0, 0, 255)')
|
|
}, 10000)
|
|
|
|
// Ensure the update was via HMR and not a full reload
|
|
expect(await browser.eval('performance.timeOrigin')).toEqual(timeOrigin)
|
|
} finally {
|
|
await next.patchFile(cssPath, originalCss)
|
|
}
|
|
})
|
|
})
|