diff --git a/client/index.js b/client/index.js
index 5391ff0c..540e669c 100644
--- a/client/index.js
+++ b/client/index.js
@@ -34,30 +34,32 @@ if (window.__NEXT_LOADED_PAGES__) {
delete window.__NEXT_LOADED_PAGES__
}
-const ErrorComponent = pageLoader.loadPageSync('/_error')
-let Component
-
-try {
- Component = pageLoader.loadPageSync(pathname)
-} catch (err) {
- console.error(`${err.message}\n${err.stack}`)
- Component = ErrorComponent
-}
-
-let lastAppProps
-
-export const router = createRouter(pathname, query, getURL(), {
- pageLoader,
- Component,
- ErrorComponent,
- err
-})
-
const headManager = new HeadManager()
const appContainer = document.getElementById('__next')
const errorContainer = document.getElementById('__next-error')
-export default () => {
+let lastAppProps
+export let router
+export let ErrorComponent
+let Component
+
+export default async () => {
+ ErrorComponent = await pageLoader.loadPage('/_error')
+
+ try {
+ Component = await pageLoader.loadPage(pathname)
+ } catch (err) {
+ console.error(`${err.message}\n${err.stack}`)
+ Component = ErrorComponent
+ }
+
+ router = createRouter(pathname, query, getURL(), {
+ pageLoader,
+ Component,
+ ErrorComponent,
+ err
+ })
+
const emitter = mitt()
router.subscribe(({ Component, props, hash, err }) => {
@@ -120,7 +122,7 @@ async function doRender ({ Component, props, hash, err, emitter }) {
}
if (emitter) {
- emitter.emit('before-reactdom-render', { Component })
+ emitter.emit('before-reactdom-render', { Component, ErrorComponent })
}
Component = Component || lastAppProps.Component
@@ -135,6 +137,6 @@ async function doRender ({ Component, props, hash, err, emitter }) {
ReactDOM.render(createElement(App, appProps), appContainer)
if (emitter) {
- emitter.emit('after-reactdom-render', { Component })
+ emitter.emit('after-reactdom-render', { Component, ErrorComponent })
}
}
diff --git a/client/next-dev.js b/client/next-dev.js
index 071ec03d..b25f4169 100644
--- a/client/next-dev.js
+++ b/client/next-dev.js
@@ -1,14 +1,40 @@
-import evalScript from '../lib/eval-script'
+import 'react-hot-loader/patch'
import ReactReconciler from 'react-dom/lib/ReactReconciler'
-
-const { __NEXT_DATA__: { errorComponent } } = window
-const ErrorComponent = evalScript(errorComponent).default
-
-require('react-hot-loader/patch')
+import initOnDemandEntries from './on-demand-entries-client'
+import initWebpackHMR from './webpack-hot-middleware-client'
const next = window.next = require('./')
-const emitter = next.default()
+next.default()
+ .then((emitter) => {
+ initOnDemandEntries()
+ initWebpackHMR()
+
+ let lastScroll
+
+ emitter.on('before-reactdom-render', ({ Component, ErrorComponent }) => {
+ // Remember scroll when ErrorComponent is being rendered to later restore it
+ if (!lastScroll && Component === ErrorComponent) {
+ const { pageXOffset, pageYOffset } = window
+ lastScroll = {
+ x: pageXOffset,
+ y: pageYOffset
+ }
+ }
+ })
+
+ emitter.on('after-reactdom-render', ({ Component, ErrorComponent }) => {
+ if (lastScroll && Component !== ErrorComponent) {
+ // Restore scroll after ErrorComponent was replaced with a page component by HMR
+ const { x, y } = lastScroll
+ window.scroll(x, y)
+ lastScroll = null
+ }
+ })
+ })
+ .catch((err) => {
+ console.error(`${err.message}\n${err.stack}`)
+ })
// This is a patch to catch most of the errors throw inside React components.
const originalMountComponent = ReactReconciler.mountComponent
@@ -21,25 +47,3 @@ ReactReconciler.mountComponent = function (...args) {
throw err
}
}
-
-let lastScroll
-
-emitter.on('before-reactdom-render', ({ Component }) => {
- // Remember scroll when ErrorComponent is being rendered to later restore it
- if (!lastScroll && Component === ErrorComponent) {
- const { pageXOffset, pageYOffset } = window
- lastScroll = {
- x: pageXOffset,
- y: pageYOffset
- }
- }
-})
-
-emitter.on('after-reactdom-render', ({ Component }) => {
- if (lastScroll && Component !== ErrorComponent) {
- // Restore scroll after ErrorComponent was replaced with a page component by HMR
- const { x, y } = lastScroll
- window.scroll(x, y)
- lastScroll = null
- }
-})
diff --git a/client/next.js b/client/next.js
index 5400a409..25654b7e 100644
--- a/client/next.js
+++ b/client/next.js
@@ -1,3 +1,6 @@
import next from './'
next()
+ .catch((err) => {
+ console.error(`${err.message}\n${err.stack}`)
+ })
diff --git a/client/on-demand-entries-client.js b/client/on-demand-entries-client.js
index 7fcd8c18..3bd379dc 100644
--- a/client/on-demand-entries-client.js
+++ b/client/on-demand-entries-client.js
@@ -3,31 +3,33 @@
import Router from '../lib/router'
import fetch from 'unfetch'
-Router.ready(() => {
- Router.router.events.on('routeChangeComplete', ping)
-})
-
-async function ping () {
- try {
- const url = `/_next/on-demand-entries-ping?page=${Router.pathname}`
- const res = await fetch(url)
- const payload = await res.json()
- if (payload.invalid) {
- location.reload()
- }
- } catch (err) {
- console.error(`Error with on-demand-entries-ping: ${err.message}`)
- }
-}
-
-async function runPinger () {
- while (true) {
- await new Promise((resolve) => setTimeout(resolve, 5000))
- await ping()
- }
-}
-
-runPinger()
- .catch((err) => {
- console.error(err)
+export default () => {
+ Router.ready(() => {
+ Router.router.events.on('routeChangeComplete', ping)
})
+
+ async function ping () {
+ try {
+ const url = `/_next/on-demand-entries-ping?page=${Router.pathname}`
+ const res = await fetch(url)
+ const payload = await res.json()
+ if (payload.invalid) {
+ location.reload()
+ }
+ } catch (err) {
+ console.error(`Error with on-demand-entries-ping: ${err.message}`)
+ }
+ }
+
+ async function runPinger () {
+ while (true) {
+ await new Promise((resolve) => setTimeout(resolve, 5000))
+ await ping()
+ }
+ }
+
+ runPinger()
+ .catch((err) => {
+ console.error(err)
+ })
+}
diff --git a/client/webpack-hot-middleware-client.js b/client/webpack-hot-middleware-client.js
index 7dfc4949..38b55df6 100644
--- a/client/webpack-hot-middleware-client.js
+++ b/client/webpack-hot-middleware-client.js
@@ -1,48 +1,50 @@
import webpackHotMiddlewareClient from 'webpack-hot-middleware/client?overlay=false&reload=true'
import Router from '../lib/router'
-const handlers = {
- reload (route) {
- if (route === '/_error') {
- for (const r of Object.keys(Router.components)) {
- const { err } = Router.components[r]
- if (err) {
- // reload all error routes
- // which are expected to be errors of '/_error' routes
- Router.reload(r)
+export default () => {
+ const handlers = {
+ reload (route) {
+ if (route === '/_error') {
+ for (const r of Object.keys(Router.components)) {
+ const { err } = Router.components[r]
+ if (err) {
+ // reload all error routes
+ // which are expected to be errors of '/_error' routes
+ Router.reload(r)
+ }
}
+ return
}
- return
- }
- if (route === '/_document') {
- window.location.reload()
- return
- }
+ if (route === '/_document') {
+ window.location.reload()
+ return
+ }
- Router.reload(route)
- },
-
- change (route) {
- if (route === '/_document') {
- window.location.reload()
- return
- }
-
- const { err } = Router.components[route] || {}
- if (err) {
- // reload to recover from runtime errors
Router.reload(route)
+ },
+
+ change (route) {
+ if (route === '/_document') {
+ window.location.reload()
+ return
+ }
+
+ const { err } = Router.components[route] || {}
+ if (err) {
+ // reload to recover from runtime errors
+ Router.reload(route)
+ }
}
}
-}
-webpackHotMiddlewareClient.subscribe((obj) => {
- const fn = handlers[obj.action]
- if (fn) {
- const data = obj.data || []
- fn(...data)
- } else {
- throw new Error('Unexpected action ' + obj.action)
- }
-})
+ webpackHotMiddlewareClient.subscribe((obj) => {
+ const fn = handlers[obj.action]
+ if (fn) {
+ const data = obj.data || []
+ fn(...data)
+ } else {
+ throw new Error('Unexpected action ' + obj.action)
+ }
+ })
+}
diff --git a/server/document.js b/server/document.js
index 7160aeeb..15e99a44 100644
--- a/server/document.js
+++ b/server/document.js
@@ -103,8 +103,8 @@ export class NextScript extends Component {
{staticMarkup ? null : }
-
-
+
+
{staticMarkup ? null : this.getScripts()}
}
diff --git a/server/hot-reloader.js b/server/hot-reloader.js
index 15998aab..ebb17d3f 100644
--- a/server/hot-reloader.js
+++ b/server/hot-reloader.js
@@ -5,7 +5,6 @@ import onDemandEntryHandler from './on-demand-entry-handler'
import isWindowsBash from 'is-windows-bash'
import webpack from './build/webpack'
import clean from './build/clean'
-import readPage from './read-page'
import getConfig from './config'
export default class HotReloader {
@@ -202,7 +201,6 @@ export default class HotReloader {
function deleteCache (path) {
delete require.cache[path]
- delete readPage.cache[path]
}
function diff (a, b) {
diff --git a/server/read-page.js b/server/read-page.js
deleted file mode 100644
index b585d629..00000000
--- a/server/read-page.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import fs from 'mz/fs'
-import resolve from './resolve'
-
-/**
- * resolve a JSON page like `require.resolve`,
- * and read and cache the file content
- */
-
-async function readPage (path) {
- const f = await resolve(path)
- if (cache.hasOwnProperty(f)) {
- return cache[f]
- }
-
- const source = await fs.readFile(f, 'utf8')
- cache[f] = source
- return source
-}
-
-export default readPage
-export const cache = {}
-
-readPage.cache = cache