From af32fc3d00ce3c675db702267c552bf7e30c14d6 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Fri, 17 Jan 2020 13:06:37 -0600 Subject: [PATCH 1/6] Add failing hydration test --- test/integration/hydration/pages/_app.js | 1 + test/integration/hydration/pages/_document.js | 16 ++++++++++ test/integration/hydration/pages/details.js | 6 ++++ test/integration/hydration/pages/index.js | 6 ++++ test/integration/hydration/test/index.test.js | 31 +++++++++++++++++++ 5 files changed, 60 insertions(+) create mode 100644 test/integration/hydration/pages/_app.js create mode 100644 test/integration/hydration/pages/_document.js create mode 100644 test/integration/hydration/pages/details.js create mode 100644 test/integration/hydration/pages/index.js create mode 100644 test/integration/hydration/test/index.test.js diff --git a/test/integration/hydration/pages/_app.js b/test/integration/hydration/pages/_app.js new file mode 100644 index 000000000000000..e3c005467a1695a --- /dev/null +++ b/test/integration/hydration/pages/_app.js @@ -0,0 +1 @@ +export default ({ Component, pageProps }) => diff --git a/test/integration/hydration/pages/_document.js b/test/integration/hydration/pages/_document.js new file mode 100644 index 000000000000000..d4d66d494410fb1 --- /dev/null +++ b/test/integration/hydration/pages/_document.js @@ -0,0 +1,16 @@ +import Document, { Head, Html, Main, NextScript } from 'next/document' +import React from 'react' + +class WeddingDocument extends Document { + render() { + return ( + + +
+ + + ) + } +} + +export default WeddingDocument diff --git a/test/integration/hydration/pages/details.js b/test/integration/hydration/pages/details.js new file mode 100644 index 000000000000000..0acf307fdefc8c7 --- /dev/null +++ b/test/integration/hydration/pages/details.js @@ -0,0 +1,6 @@ +export default () => { + if (typeof window !== 'undefined') { + window.didHydrate = true + } + return 'details' +} diff --git a/test/integration/hydration/pages/index.js b/test/integration/hydration/pages/index.js new file mode 100644 index 000000000000000..b0989ad629fb61d --- /dev/null +++ b/test/integration/hydration/pages/index.js @@ -0,0 +1,6 @@ +export default () => { + if (typeof window !== 'undefined') { + window.didHydrate = true + } + return 'index' +} diff --git a/test/integration/hydration/test/index.test.js b/test/integration/hydration/test/index.test.js new file mode 100644 index 000000000000000..380db7991168286 --- /dev/null +++ b/test/integration/hydration/test/index.test.js @@ -0,0 +1,31 @@ +/* eslint-env jest */ +/* global jasmine */ +import path from 'path' +import webdriver from 'next-webdriver' +import { + nextBuild, + nextStart, + findPort, + waitFor, + killApp, +} from 'next-test-utils' + +jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 1 +const appDir = path.join(__dirname, '..') +let app +let appPort + +describe('Hydration', () => { + beforeAll(async () => { + await nextBuild(appDir) + appPort = await findPort() + app = await nextStart(appDir, appPort) + }) + afterAll(() => killApp(app)) + + it('Hydrates correctly', async () => { + const browser = await webdriver(appPort, '/') + await waitFor(2000) + expect(await browser.eval('window.didHydrate')).toBe(true) + }) +}) From 823e218ee5b1c623d851872887aacbcadc430ede Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Fri, 17 Jan 2020 13:08:24 -0600 Subject: [PATCH 2/6] Add importing of next/router to _app --- .../next/build/babel/plugins/next-page-config.ts | 12 ++++++++++++ test/integration/hydration/test/index.test.js | 2 ++ 2 files changed, 14 insertions(+) diff --git a/packages/next/build/babel/plugins/next-page-config.ts b/packages/next/build/babel/plugins/next-page-config.ts index a101ca91f463a2f..7cbe038eeef864b 100644 --- a/packages/next/build/babel/plugins/next-page-config.ts +++ b/packages/next/build/babel/plugins/next-page-config.ts @@ -27,6 +27,7 @@ function replaceBundle(path: any, t: typeof BabelTypes) { } interface ConfigState { + filename: string bundleDropped?: boolean } @@ -40,6 +41,17 @@ export default function nextPageConfig({ visitor: { Program: { enter(path, state: ConfigState) { + // Make sure next/router is imported in _app or else granularChunks + // might cause the router to not be able to load causing hydration + // to fail + if (state.filename.match(/\/_app\./)) { + path.node.body.splice( + 0, + 0, + t.importDeclaration([], t.stringLiteral('next/router')) + ) + } + path.traverse( { ExportNamedDeclaration( diff --git a/test/integration/hydration/test/index.test.js b/test/integration/hydration/test/index.test.js index 380db7991168286..5a18abec58403b1 100644 --- a/test/integration/hydration/test/index.test.js +++ b/test/integration/hydration/test/index.test.js @@ -1,6 +1,7 @@ /* eslint-env jest */ /* global jasmine */ import path from 'path' +import fs from 'fs-extra' import webdriver from 'next-webdriver' import { nextBuild, @@ -17,6 +18,7 @@ let appPort describe('Hydration', () => { beforeAll(async () => { + await fs.remove(path.join(appDir, '.next')) await nextBuild(appDir) appPort = await findPort() app = await nextStart(appDir, appPort) From 5b734df489451e3716f3bd06e576f8d14cd3c6d6 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Fri, 17 Jan 2020 13:13:13 -0600 Subject: [PATCH 3/6] Fix type --- packages/next/build/babel/plugins/next-page-config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/next/build/babel/plugins/next-page-config.ts b/packages/next/build/babel/plugins/next-page-config.ts index 7cbe038eeef864b..cdabc32715c85ea 100644 --- a/packages/next/build/babel/plugins/next-page-config.ts +++ b/packages/next/build/babel/plugins/next-page-config.ts @@ -27,7 +27,7 @@ function replaceBundle(path: any, t: typeof BabelTypes) { } interface ConfigState { - filename: string + filename?: string bundleDropped?: boolean } @@ -44,7 +44,7 @@ export default function nextPageConfig({ // Make sure next/router is imported in _app or else granularChunks // might cause the router to not be able to load causing hydration // to fail - if (state.filename.match(/\/_app\./)) { + if (state.filename?.match(/\/_app\./)) { path.node.body.splice( 0, 0, From 51831441bd5f44662929781e811da1841397244a Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Fri, 17 Jan 2020 13:18:39 -0600 Subject: [PATCH 4/6] Update _app check for windows --- packages/next/build/babel/plugins/next-page-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/next/build/babel/plugins/next-page-config.ts b/packages/next/build/babel/plugins/next-page-config.ts index cdabc32715c85ea..912ed6253514c48 100644 --- a/packages/next/build/babel/plugins/next-page-config.ts +++ b/packages/next/build/babel/plugins/next-page-config.ts @@ -44,7 +44,7 @@ export default function nextPageConfig({ // Make sure next/router is imported in _app or else granularChunks // might cause the router to not be able to load causing hydration // to fail - if (state.filename?.match(/\/_app\./)) { + if (state.filename?.match(/(\\|\/)_app\./)) { path.node.body.splice( 0, 0, From 5acbaa0a596826f53f041508eef6e9129ffa2d18 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Fri, 17 Jan 2020 13:40:03 -0600 Subject: [PATCH 5/6] Remove babel fix --- .../next/build/babel/plugins/next-page-config.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/packages/next/build/babel/plugins/next-page-config.ts b/packages/next/build/babel/plugins/next-page-config.ts index 912ed6253514c48..a101ca91f463a2f 100644 --- a/packages/next/build/babel/plugins/next-page-config.ts +++ b/packages/next/build/babel/plugins/next-page-config.ts @@ -27,7 +27,6 @@ function replaceBundle(path: any, t: typeof BabelTypes) { } interface ConfigState { - filename?: string bundleDropped?: boolean } @@ -41,17 +40,6 @@ export default function nextPageConfig({ visitor: { Program: { enter(path, state: ConfigState) { - // Make sure next/router is imported in _app or else granularChunks - // might cause the router to not be able to load causing hydration - // to fail - if (state.filename?.match(/(\\|\/)_app\./)) { - path.node.body.splice( - 0, - 0, - t.importDeclaration([], t.stringLiteral('next/router')) - ) - } - path.traverse( { ExportNamedDeclaration( From 95eb73cd84f56ca636fba76f1afd787350828212 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Fri, 17 Jan 2020 14:07:07 -0600 Subject: [PATCH 6/6] Update to use webpack to require next/router --- packages/next/build/entries.ts | 11 ++++++++++- packages/next/pages/_app.tsx | 1 - 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/next/build/entries.ts b/packages/next/build/entries.ts index f51675d36655c16..a518b7b9877c69c 100644 --- a/packages/next/build/entries.ts +++ b/packages/next/build/entries.ts @@ -115,10 +115,19 @@ export function createEntrypoints( } if (!isApiRoute) { - client[bundlePath] = `next-client-pages-loader?${stringify({ + const pageLoader = `next-client-pages-loader?${stringify({ page, absolutePagePath, })}!` + + // Make sure next/router is a dependency of _app or else granularChunks + // might cause the router to not be able to load causing hydration + // to fail + + client[bundlePath] = + page === '/_app' + ? [pageLoader, require.resolve('../client/router')] + : pageLoader } }) diff --git a/packages/next/pages/_app.tsx b/packages/next/pages/_app.tsx index c4041f9613d76a5..3971441a24339ef 100644 --- a/packages/next/pages/_app.tsx +++ b/packages/next/pages/_app.tsx @@ -7,7 +7,6 @@ import { AppPropsType, } from '../next-server/lib/utils' import { Router } from '../client/router' -import '../client/router' export { AppInitialProps }