From e46edc2460e1e28276001880e5253219605f1dc2 Mon Sep 17 00:00:00 2001 From: Arunoda Susiripala Date: Thu, 6 Apr 2017 11:41:13 +0530 Subject: [PATCH] Load everything async. --- client/index.js | 46 ++++++++------- client/next-dev.js | 62 ++++++++++---------- client/next.js | 3 + client/on-demand-entries-client.js | 56 +++++++++--------- client/webpack-hot-middleware-client.js | 76 +++++++++++++------------ server/document.js | 4 +- server/hot-reloader.js | 2 - server/read-page.js | 23 -------- 8 files changed, 130 insertions(+), 142 deletions(-) delete mode 100644 server/read-page.js 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 :