From d25fdf587aa334b5ce3fcec09cb00961fc0b55d6 Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Mon, 27 Jan 2020 13:00:19 -0500 Subject: [PATCH] Fix Experimental Modern Mode with CSS --- .../webpack/plugins/build-manifest-plugin.ts | 4 +- .../css-client-nav/test/index.test.js | 156 ++++++++++++++++++ .../multi-module-modern/next.config.js | 9 + .../multi-module-modern/pages/blue.js | 20 +++ .../multi-module-modern/pages/blue.module.css | 3 + .../multi-module-modern/pages/none.js | 19 +++ .../multi-module-modern/pages/red.js | 20 +++ .../multi-module-modern/pages/red.module.css | 3 + .../css-fixtures/multi-module/next.config.js | 9 + 9 files changed, 242 insertions(+), 1 deletion(-) create mode 100644 test/integration/css-fixtures/multi-module-modern/next.config.js create mode 100644 test/integration/css-fixtures/multi-module-modern/pages/blue.js create mode 100644 test/integration/css-fixtures/multi-module-modern/pages/blue.module.css create mode 100644 test/integration/css-fixtures/multi-module-modern/pages/none.js create mode 100644 test/integration/css-fixtures/multi-module-modern/pages/red.js create mode 100644 test/integration/css-fixtures/multi-module-modern/pages/red.module.css create mode 100644 test/integration/css-fixtures/multi-module/next.config.js diff --git a/packages/next/build/webpack/plugins/build-manifest-plugin.ts b/packages/next/build/webpack/plugins/build-manifest-plugin.ts index be640cbed31f6..75a3b2500d027 100644 --- a/packages/next/build/webpack/plugins/build-manifest-plugin.ts +++ b/packages/next/build/webpack/plugins/build-manifest-plugin.ts @@ -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 diff --git a/test/integration/css-client-nav/test/index.test.js b/test/integration/css-client-nav/test/index.test.js index d5dfc8cba184a..4f35823bc276c 100644 --- a/test/integration/css-client-nav/test/index.test.js +++ b/test/integration/css-client-nav/test/index.test.js @@ -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() + } + } + }) +}) diff --git a/test/integration/css-fixtures/multi-module-modern/next.config.js b/test/integration/css-fixtures/multi-module-modern/next.config.js new file mode 100644 index 0000000000000..a6e26e2467154 --- /dev/null +++ b/test/integration/css-fixtures/multi-module-modern/next.config.js @@ -0,0 +1,9 @@ +const parent = require('../next.config') + +module.exports = { + ...parent, + experimental: { + ...parent.experimental, + modern: true, + }, +} diff --git a/test/integration/css-fixtures/multi-module-modern/pages/blue.js b/test/integration/css-fixtures/multi-module-modern/pages/blue.js new file mode 100644 index 0000000000000..49dff85067fa3 --- /dev/null +++ b/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 ( + <> +
+ This text should be blue. +
+
+ + Red + +
+ + None + + + ) +} diff --git a/test/integration/css-fixtures/multi-module-modern/pages/blue.module.css b/test/integration/css-fixtures/multi-module-modern/pages/blue.module.css new file mode 100644 index 0000000000000..4c5ac28ce4ef8 --- /dev/null +++ b/test/integration/css-fixtures/multi-module-modern/pages/blue.module.css @@ -0,0 +1,3 @@ +.blueText { + color: blue; +} diff --git a/test/integration/css-fixtures/multi-module-modern/pages/none.js b/test/integration/css-fixtures/multi-module-modern/pages/none.js new file mode 100644 index 0000000000000..f26c2d80b3ae0 --- /dev/null +++ b/test/integration/css-fixtures/multi-module-modern/pages/none.js @@ -0,0 +1,19 @@ +import Link from 'next/link' + +export default function None() { + return ( + <> +
+ This text should be black. +
+
+ + Red + +
+ + Blue + + + ) +} diff --git a/test/integration/css-fixtures/multi-module-modern/pages/red.js b/test/integration/css-fixtures/multi-module-modern/pages/red.js new file mode 100644 index 0000000000000..d67276dda2d76 --- /dev/null +++ b/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 ( + <> +
+ This text should be red. +
+
+ + Blue + +
+ + None + + + ) +} diff --git a/test/integration/css-fixtures/multi-module-modern/pages/red.module.css b/test/integration/css-fixtures/multi-module-modern/pages/red.module.css new file mode 100644 index 0000000000000..08a38e09ef8ea --- /dev/null +++ b/test/integration/css-fixtures/multi-module-modern/pages/red.module.css @@ -0,0 +1,3 @@ +.redText { + color: red; +} diff --git a/test/integration/css-fixtures/multi-module/next.config.js b/test/integration/css-fixtures/multi-module/next.config.js new file mode 100644 index 0000000000000..b0f299cd75640 --- /dev/null +++ b/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, + }, +}