Skip to content

Commit abd69ec

Browse files
authored
Fix Experimental Modern Mode with CSS (vercel#10289)
1 parent ac6a7f9 commit abd69ec

File tree

9 files changed

+242
-1
lines changed

9 files changed

+242
-1
lines changed

packages/next/build/webpack/plugins/build-manifest-plugin.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ const generateClientManifest = (
3333
// Filter out dependencies in the _app entry, because those will have already
3434
// been loaded by the client prior to a navigation event
3535
const filteredDeps = dependencies.filter(
36-
dep => !appDependencies.has(dep) && /\.module\.js$/.test(dep) === isModern
36+
dep =>
37+
!appDependencies.has(dep) &&
38+
(!dep.endsWith('.js') || dep.endsWith('.module.js') === isModern)
3739
)
3840

3941
// The manifest can omit the page if it has no requirements

test/integration/css-client-nav/test/index.test.js

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,159 @@ describe('CSS Module client-side navigation in Production', () => {
171171
}
172172
})
173173
})
174+
175+
describe('CSS Module client-side navigation in Production (Modern)', () => {
176+
const appDir = join(fixturesDir, 'multi-module-modern')
177+
178+
beforeAll(async () => {
179+
await remove(join(appDir, '.next'))
180+
})
181+
182+
let appPort
183+
let app
184+
beforeAll(async () => {
185+
await nextBuild(appDir)
186+
appPort = await findPort()
187+
app = await nextStart(appDir, appPort)
188+
})
189+
afterAll(async () => {
190+
await killApp(app)
191+
})
192+
193+
it('should be able to client-side navigate from red to blue', async () => {
194+
let browser
195+
try {
196+
browser = await webdriver(appPort, '/red')
197+
198+
await browser.eval(`window.__did_not_ssr = 'make sure this is set'`)
199+
200+
const redColor = await browser.eval(
201+
`window.getComputedStyle(document.querySelector('#verify-red')).color`
202+
)
203+
expect(redColor).toMatchInlineSnapshot(`"rgb(255, 0, 0)"`)
204+
205+
await browser.elementByCss('#link-blue').click()
206+
207+
await browser.waitForElementByCss('#verify-blue')
208+
209+
const blueColor = await browser.eval(
210+
`window.getComputedStyle(document.querySelector('#verify-blue')).color`
211+
)
212+
expect(blueColor).toMatchInlineSnapshot(`"rgb(0, 0, 255)"`)
213+
214+
expect(await browser.eval(`window.__did_not_ssr`)).toMatchInlineSnapshot(
215+
`"make sure this is set"`
216+
)
217+
} finally {
218+
if (browser) {
219+
await browser.close()
220+
}
221+
}
222+
})
223+
224+
it('should be able to client-side navigate from blue to red', async () => {
225+
const content = await renderViaHTTP(appPort, '/blue')
226+
const $ = cheerio.load(content)
227+
228+
// Ensure only `/blue` page's CSS is preloaded
229+
const serverCssPreloads = $('link[rel="preload"][as="style"]')
230+
expect(serverCssPreloads.length).toBe(1)
231+
232+
const serverCssPrefetches = $('link[rel="prefetch"][as="style"]')
233+
expect(serverCssPrefetches.length).toBe(0)
234+
235+
let browser
236+
try {
237+
browser = await webdriver(appPort, '/blue')
238+
await browser.eval(`window.__did_not_ssr = 'make sure this is set'`)
239+
240+
const redColor = await browser.eval(
241+
`window.getComputedStyle(document.querySelector('#verify-blue')).color`
242+
)
243+
expect(redColor).toMatchInlineSnapshot(`"rgb(0, 0, 255)"`)
244+
245+
// Check that Red was preloaded
246+
const result = await browser.eval(
247+
`[].slice.call(document.querySelectorAll('link[rel="prefetch"][as="style"]')).map(e=>({href:e.href})).sort()`
248+
)
249+
expect(result.length).toBe(1)
250+
251+
// Check that CSS was not loaded as script
252+
const cssPreloads = await browser.eval(
253+
`[].slice.call(document.querySelectorAll('link[rel=preload][href*=".css"]')).map(e=>e.as)`
254+
)
255+
expect(cssPreloads.every(e => e === 'style')).toBe(true)
256+
const cssPreloads2 = await browser.eval(
257+
`[].slice.call(document.querySelectorAll('link[rel=prefetch][href*=".css"]')).map(e=>e.as)`
258+
)
259+
expect(cssPreloads2.every(e => e === 'style')).toBe(true)
260+
261+
await browser.elementByCss('#link-red').click()
262+
263+
await browser.waitForElementByCss('#verify-red')
264+
265+
const blueColor = await browser.eval(
266+
`window.getComputedStyle(document.querySelector('#verify-red')).color`
267+
)
268+
expect(blueColor).toMatchInlineSnapshot(`"rgb(255, 0, 0)"`)
269+
270+
expect(await browser.eval(`window.__did_not_ssr`)).toMatchInlineSnapshot(
271+
`"make sure this is set"`
272+
)
273+
} finally {
274+
if (browser) {
275+
await browser.close()
276+
}
277+
}
278+
})
279+
280+
it('should be able to client-side navigate from none to red', async () => {
281+
let browser
282+
try {
283+
browser = await webdriver(appPort, '/none')
284+
285+
await browser.eval(`window.__did_not_ssr = 'make sure this is set'`)
286+
287+
await browser.elementByCss('#link-red').click()
288+
await browser.waitForElementByCss('#verify-red')
289+
290+
const blueColor = await browser.eval(
291+
`window.getComputedStyle(document.querySelector('#verify-red')).color`
292+
)
293+
expect(blueColor).toMatchInlineSnapshot(`"rgb(255, 0, 0)"`)
294+
295+
expect(await browser.eval(`window.__did_not_ssr`)).toMatchInlineSnapshot(
296+
`"make sure this is set"`
297+
)
298+
} finally {
299+
if (browser) {
300+
await browser.close()
301+
}
302+
}
303+
})
304+
305+
it('should be able to client-side navigate from none to blue', async () => {
306+
let browser
307+
try {
308+
browser = await webdriver(appPort, '/none')
309+
310+
await browser.eval(`window.__did_not_ssr = 'make sure this is set'`)
311+
312+
await browser.elementByCss('#link-blue').click()
313+
await browser.waitForElementByCss('#verify-blue')
314+
315+
const blueColor = await browser.eval(
316+
`window.getComputedStyle(document.querySelector('#verify-blue')).color`
317+
)
318+
expect(blueColor).toMatchInlineSnapshot(`"rgb(0, 0, 255)"`)
319+
320+
expect(await browser.eval(`window.__did_not_ssr`)).toMatchInlineSnapshot(
321+
`"make sure this is set"`
322+
)
323+
} finally {
324+
if (browser) {
325+
await browser.close()
326+
}
327+
}
328+
})
329+
})
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const parent = require('../next.config')
2+
3+
module.exports = {
4+
...parent,
5+
experimental: {
6+
...parent.experimental,
7+
modern: true,
8+
},
9+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import Link from 'next/link'
2+
import { blueText } from './blue.module.css'
3+
4+
export default function Blue() {
5+
return (
6+
<>
7+
<div id="verify-blue" className={blueText}>
8+
This text should be blue.
9+
</div>
10+
<br />
11+
<Link href="/red" prefetch>
12+
<a id="link-red">Red</a>
13+
</Link>
14+
<br />
15+
<Link href="/none" prefetch={false}>
16+
<a id="link-none">None</a>
17+
</Link>
18+
</>
19+
)
20+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.blueText {
2+
color: blue;
3+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import Link from 'next/link'
2+
3+
export default function None() {
4+
return (
5+
<>
6+
<div id="verify-black" style={{ color: 'black' }}>
7+
This text should be black.
8+
</div>
9+
<br />
10+
<Link href="/red" prefetch={false}>
11+
<a id="link-red">Red</a>
12+
</Link>
13+
<br />
14+
<Link href="/blue" prefetch={false}>
15+
<a id="link-blue">Blue</a>
16+
</Link>
17+
</>
18+
)
19+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import Link from 'next/link'
2+
import { redText } from './red.module.css'
3+
4+
export default function Red() {
5+
return (
6+
<>
7+
<div id="verify-red" className={redText}>
8+
This text should be red.
9+
</div>
10+
<br />
11+
<Link href="/blue" prefetch={false}>
12+
<a id="link-blue">Blue</a>
13+
</Link>
14+
<br />
15+
<Link href="/none" prefetch={false}>
16+
<a id="link-none">None</a>
17+
</Link>
18+
</>
19+
)
20+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.redText {
2+
color: red;
3+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const parent = require('../next.config')
2+
3+
module.exports = {
4+
...parent,
5+
experimental: {
6+
...parent.experimental,
7+
modern: false,
8+
},
9+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy