Skip to content

Commit

Permalink
Delay hydration until after page is visible in development
Browse files Browse the repository at this point in the history
  • Loading branch information
ijjk committed Jan 19, 2020
1 parent 71c2354 commit 057fcf1
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 5 deletions.
5 changes: 4 additions & 1 deletion packages/next/client/dev/fouc.js
@@ -1,4 +1,4 @@
export function displayContent() {
export function displayContent(callback) {
// This is the fallback helper that removes Next.js' no-FOUC styles when
// CSS mode is enabled. This only really activates if you haven't created
// _any_ styles in your application yet.
Expand All @@ -10,5 +10,8 @@ export function displayContent() {
) {
x[i].parentNode.removeChild(x[i])
}
if (callback) {
callback()
}
})
}
7 changes: 5 additions & 2 deletions packages/next/client/index.js
Expand Up @@ -200,9 +200,12 @@ export default async ({ webpackHMR: passedWebpackHMR } = {}) => {
}

const renderCtx = { App, Component, props, err: initialErr }
render(renderCtx)

return emitter
if (process.env.NODE_ENV === 'production') {
render(renderCtx)
} else {
return { emitter, render, renderCtx }
}
}

export async function render(props) {
Expand Down
7 changes: 5 additions & 2 deletions packages/next/client/next-dev.js
Expand Up @@ -28,7 +28,7 @@ const webpackHMR = initWebpackHMR({ assetPrefix: prefix })

window.next = next
initNext({ webpackHMR })
.then(emitter => {
.then(({ emitter, renderCtx, render }) => {
initOnDemandEntries({ assetPrefix: prefix })
if (process.env.__NEXT_BUILD_INDICATOR) initializeBuildWatcher()
if (
Expand All @@ -39,7 +39,10 @@ initNext({ webpackHMR })
initializePrerenderIndicator()
}

displayContent()
// delay rendering until after styles have been applied in development
displayContent(() => {
render(renderCtx)
})

let lastScroll

Expand Down
31 changes: 31 additions & 0 deletions test/integration/initial-ref/pages/index.js
@@ -0,0 +1,31 @@
import React from 'react'

class App extends React.Component {
constructor() {
super()

this.divRef = React.createRef()

this.state = {
refHeight: 0,
}
}

componentDidMount() {
const refHeight = this.divRef.current.clientHeight
this.setState({ refHeight })
}

render() {
const { refHeight } = this.state

return (
<div ref={this.divRef}>
<h1>DOM Ref test using 9.2.0</h1>
<code id="ref-val">{`this component is ${refHeight}px tall`}</code>
</div>
)
}
}

export default App
48 changes: 48 additions & 0 deletions test/integration/initial-ref/test/index.test.js
@@ -0,0 +1,48 @@
/* eslint-env jest */
/* global jasmine */
import path from 'path'
import webdriver from 'next-webdriver'
import {
nextBuild,
nextStart,
launchApp,
findPort,
waitFor,
killApp,
} from 'next-test-utils'

jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 1
const appDir = path.join(__dirname, '..')
let app
let appPort

const runTest = () => {
it('Has correct initial ref values', async () => {
const browser = await webdriver(appPort, '/')
await waitFor(2000)
expect(await browser.elementByCss('#ref-val').text()).toContain('76px')
})
}

describe('Hydration', () => {
describe('production mode', () => {
beforeAll(async () => {
await nextBuild(appDir)
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(() => killApp(app))

runTest()
})

describe('dev mode', () => {
beforeAll(async () => {
appPort = await findPort()
app = await launchApp(appDir, appPort)
})
afterAll(() => killApp(app))

runTest()
})
})

0 comments on commit 057fcf1

Please sign in to comment.