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

Fix Experimental Modern Mode with CSS #10289

Merged
merged 4 commits into from Jan 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -33,7 +33,9 @@ const generateClientManifest = (
// Filter out dependencies in the _app entry, because those will have already
// been loaded by the client prior to a navigation event
const filteredDeps = dependencies.filter(
dep => !appDependencies.has(dep) && /\.module\.js$/.test(dep) === isModern
dep =>
!appDependencies.has(dep) &&
(!dep.endsWith('.js') || dep.endsWith('.module.js') === isModern)
)

// The manifest can omit the page if it has no requirements
Expand Down
156 changes: 156 additions & 0 deletions test/integration/css-client-nav/test/index.test.js
Expand Up @@ -171,3 +171,159 @@ describe('CSS Module client-side navigation in Production', () => {
}
})
})

describe('CSS Module client-side navigation in Production (Modern)', () => {
const appDir = join(fixturesDir, 'multi-module-modern')

beforeAll(async () => {
await remove(join(appDir, '.next'))
})

let appPort
let app
beforeAll(async () => {
await nextBuild(appDir)
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(async () => {
await killApp(app)
})

it('should be able to client-side navigate from red to blue', async () => {
let browser
try {
browser = await webdriver(appPort, '/red')

await browser.eval(`window.__did_not_ssr = 'make sure this is set'`)

const redColor = await browser.eval(
`window.getComputedStyle(document.querySelector('#verify-red')).color`
)
expect(redColor).toMatchInlineSnapshot(`"rgb(255, 0, 0)"`)

await browser.elementByCss('#link-blue').click()

await browser.waitForElementByCss('#verify-blue')

const blueColor = await browser.eval(
`window.getComputedStyle(document.querySelector('#verify-blue')).color`
)
expect(blueColor).toMatchInlineSnapshot(`"rgb(0, 0, 255)"`)

expect(await browser.eval(`window.__did_not_ssr`)).toMatchInlineSnapshot(
`"make sure this is set"`
)
} finally {
if (browser) {
await browser.close()
}
}
})

it('should be able to client-side navigate from blue to red', async () => {
const content = await renderViaHTTP(appPort, '/blue')
const $ = cheerio.load(content)

// Ensure only `/blue` page's CSS is preloaded
const serverCssPreloads = $('link[rel="preload"][as="style"]')
expect(serverCssPreloads.length).toBe(1)

const serverCssPrefetches = $('link[rel="prefetch"][as="style"]')
expect(serverCssPrefetches.length).toBe(0)

let browser
try {
browser = await webdriver(appPort, '/blue')
await browser.eval(`window.__did_not_ssr = 'make sure this is set'`)

const redColor = await browser.eval(
`window.getComputedStyle(document.querySelector('#verify-blue')).color`
)
expect(redColor).toMatchInlineSnapshot(`"rgb(0, 0, 255)"`)

// Check that Red was preloaded
const result = await browser.eval(
`[].slice.call(document.querySelectorAll('link[rel="prefetch"][as="style"]')).map(e=>({href:e.href})).sort()`
)
expect(result.length).toBe(1)

// Check that CSS was not loaded as script
const cssPreloads = await browser.eval(
`[].slice.call(document.querySelectorAll('link[rel=preload][href*=".css"]')).map(e=>e.as)`
)
expect(cssPreloads.every(e => e === 'style')).toBe(true)
const cssPreloads2 = await browser.eval(
`[].slice.call(document.querySelectorAll('link[rel=prefetch][href*=".css"]')).map(e=>e.as)`
)
expect(cssPreloads2.every(e => e === 'style')).toBe(true)

await browser.elementByCss('#link-red').click()

await browser.waitForElementByCss('#verify-red')

const blueColor = await browser.eval(
`window.getComputedStyle(document.querySelector('#verify-red')).color`
)
expect(blueColor).toMatchInlineSnapshot(`"rgb(255, 0, 0)"`)

expect(await browser.eval(`window.__did_not_ssr`)).toMatchInlineSnapshot(
`"make sure this is set"`
)
} finally {
if (browser) {
await browser.close()
}
}
})

it('should be able to client-side navigate from none to red', async () => {
let browser
try {
browser = await webdriver(appPort, '/none')

await browser.eval(`window.__did_not_ssr = 'make sure this is set'`)

await browser.elementByCss('#link-red').click()
await browser.waitForElementByCss('#verify-red')

const blueColor = await browser.eval(
`window.getComputedStyle(document.querySelector('#verify-red')).color`
)
expect(blueColor).toMatchInlineSnapshot(`"rgb(255, 0, 0)"`)

expect(await browser.eval(`window.__did_not_ssr`)).toMatchInlineSnapshot(
`"make sure this is set"`
)
} finally {
if (browser) {
await browser.close()
}
}
})

it('should be able to client-side navigate from none to blue', async () => {
let browser
try {
browser = await webdriver(appPort, '/none')

await browser.eval(`window.__did_not_ssr = 'make sure this is set'`)

await browser.elementByCss('#link-blue').click()
await browser.waitForElementByCss('#verify-blue')

const blueColor = await browser.eval(
`window.getComputedStyle(document.querySelector('#verify-blue')).color`
)
expect(blueColor).toMatchInlineSnapshot(`"rgb(0, 0, 255)"`)

expect(await browser.eval(`window.__did_not_ssr`)).toMatchInlineSnapshot(
`"make sure this is set"`
)
} finally {
if (browser) {
await browser.close()
}
}
})
})
@@ -0,0 +1,9 @@
const parent = require('../next.config')

module.exports = {
...parent,
experimental: {
...parent.experimental,
modern: true,
},
}
20 changes: 20 additions & 0 deletions test/integration/css-fixtures/multi-module-modern/pages/blue.js
@@ -0,0 +1,20 @@
import Link from 'next/link'
import { blueText } from './blue.module.css'

export default function Blue() {
return (
<>
<div id="verify-blue" className={blueText}>
This text should be blue.
</div>
<br />
<Link href="/red" prefetch>
<a id="link-red">Red</a>
</Link>
<br />
<Link href="/none" prefetch={false}>
<a id="link-none">None</a>
</Link>
</>
)
}
@@ -0,0 +1,3 @@
.blueText {
color: blue;
}
19 changes: 19 additions & 0 deletions test/integration/css-fixtures/multi-module-modern/pages/none.js
@@ -0,0 +1,19 @@
import Link from 'next/link'

export default function None() {
return (
<>
<div id="verify-black" style={{ color: 'black' }}>
This text should be black.
</div>
<br />
<Link href="/red" prefetch={false}>
<a id="link-red">Red</a>
</Link>
<br />
<Link href="/blue" prefetch={false}>
<a id="link-blue">Blue</a>
</Link>
</>
)
}
20 changes: 20 additions & 0 deletions test/integration/css-fixtures/multi-module-modern/pages/red.js
@@ -0,0 +1,20 @@
import Link from 'next/link'
import { redText } from './red.module.css'

export default function Red() {
return (
<>
<div id="verify-red" className={redText}>
This text should be red.
</div>
<br />
<Link href="/blue" prefetch={false}>
<a id="link-blue">Blue</a>
</Link>
<br />
<Link href="/none" prefetch={false}>
<a id="link-none">None</a>
</Link>
</>
)
}
@@ -0,0 +1,3 @@
.redText {
color: red;
}
9 changes: 9 additions & 0 deletions test/integration/css-fixtures/multi-module/next.config.js
@@ -0,0 +1,9 @@
const parent = require('../next.config')

module.exports = {
...parent,
experimental: {
...parent.experimental,
modern: false,
},
}