1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00

Load everything async.

This commit is contained in:
Arunoda Susiripala 2017-04-06 11:41:13 +05:30
parent f6f175db73
commit e46edc2460
8 changed files with 130 additions and 142 deletions

View file

@ -34,30 +34,32 @@ if (window.__NEXT_LOADED_PAGES__) {
delete 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 headManager = new HeadManager()
const appContainer = document.getElementById('__next') const appContainer = document.getElementById('__next')
const errorContainer = document.getElementById('__next-error') 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() const emitter = mitt()
router.subscribe(({ Component, props, hash, err }) => { router.subscribe(({ Component, props, hash, err }) => {
@ -120,7 +122,7 @@ async function doRender ({ Component, props, hash, err, emitter }) {
} }
if (emitter) { if (emitter) {
emitter.emit('before-reactdom-render', { Component }) emitter.emit('before-reactdom-render', { Component, ErrorComponent })
} }
Component = Component || lastAppProps.Component Component = Component || lastAppProps.Component
@ -135,6 +137,6 @@ async function doRender ({ Component, props, hash, err, emitter }) {
ReactDOM.render(createElement(App, appProps), appContainer) ReactDOM.render(createElement(App, appProps), appContainer)
if (emitter) { if (emitter) {
emitter.emit('after-reactdom-render', { Component }) emitter.emit('after-reactdom-render', { Component, ErrorComponent })
} }
} }

View file

@ -1,14 +1,40 @@
import evalScript from '../lib/eval-script' import 'react-hot-loader/patch'
import ReactReconciler from 'react-dom/lib/ReactReconciler' import ReactReconciler from 'react-dom/lib/ReactReconciler'
import initOnDemandEntries from './on-demand-entries-client'
const { __NEXT_DATA__: { errorComponent } } = window import initWebpackHMR from './webpack-hot-middleware-client'
const ErrorComponent = evalScript(errorComponent).default
require('react-hot-loader/patch')
const next = window.next = require('./') 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. // This is a patch to catch most of the errors throw inside React components.
const originalMountComponent = ReactReconciler.mountComponent const originalMountComponent = ReactReconciler.mountComponent
@ -21,25 +47,3 @@ ReactReconciler.mountComponent = function (...args) {
throw err 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
}
})

View file

@ -1,3 +1,6 @@
import next from './' import next from './'
next() next()
.catch((err) => {
console.error(`${err.message}\n${err.stack}`)
})

View file

@ -3,11 +3,12 @@
import Router from '../lib/router' import Router from '../lib/router'
import fetch from 'unfetch' import fetch from 'unfetch'
Router.ready(() => { export default () => {
Router.ready(() => {
Router.router.events.on('routeChangeComplete', ping) Router.router.events.on('routeChangeComplete', ping)
}) })
async function ping () { async function ping () {
try { try {
const url = `/_next/on-demand-entries-ping?page=${Router.pathname}` const url = `/_next/on-demand-entries-ping?page=${Router.pathname}`
const res = await fetch(url) const res = await fetch(url)
@ -18,16 +19,17 @@ async function ping () {
} catch (err) { } catch (err) {
console.error(`Error with on-demand-entries-ping: ${err.message}`) console.error(`Error with on-demand-entries-ping: ${err.message}`)
} }
} }
async function runPinger () { async function runPinger () {
while (true) { while (true) {
await new Promise((resolve) => setTimeout(resolve, 5000)) await new Promise((resolve) => setTimeout(resolve, 5000))
await ping() await ping()
} }
} }
runPinger() runPinger()
.catch((err) => { .catch((err) => {
console.error(err) console.error(err)
}) })
}

View file

@ -1,7 +1,8 @@
import webpackHotMiddlewareClient from 'webpack-hot-middleware/client?overlay=false&reload=true' import webpackHotMiddlewareClient from 'webpack-hot-middleware/client?overlay=false&reload=true'
import Router from '../lib/router' import Router from '../lib/router'
const handlers = { export default () => {
const handlers = {
reload (route) { reload (route) {
if (route === '/_error') { if (route === '/_error') {
for (const r of Object.keys(Router.components)) { for (const r of Object.keys(Router.components)) {
@ -35,9 +36,9 @@ const handlers = {
Router.reload(route) Router.reload(route)
} }
} }
} }
webpackHotMiddlewareClient.subscribe((obj) => { webpackHotMiddlewareClient.subscribe((obj) => {
const fn = handlers[obj.action] const fn = handlers[obj.action]
if (fn) { if (fn) {
const data = obj.data || [] const data = obj.data || []
@ -45,4 +46,5 @@ webpackHotMiddlewareClient.subscribe((obj) => {
} else { } else {
throw new Error('Unexpected action ' + obj.action) throw new Error('Unexpected action ' + obj.action)
} }
}) })
}

View file

@ -103,8 +103,8 @@ export class NextScript extends Component {
{staticMarkup ? null : <script dangerouslySetInnerHTML={{ {staticMarkup ? null : <script dangerouslySetInnerHTML={{
__html: `__NEXT_DATA__ = ${htmlescape(__NEXT_DATA__)}; module={};` __html: `__NEXT_DATA__ = ${htmlescape(__NEXT_DATA__)}; module={};`
}} />} }} />}
<script type='text/javascript' src={`/_next/${buildId}/page${pathname}`} /> <script async type='text/javascript' src={`/_next/${buildId}/page${pathname}`} />
<script type='text/javascript' src={`/_next/${buildId}/page/_error`} /> <script async type='text/javascript' src={`/_next/${buildId}/page/_error`} />
{staticMarkup ? null : this.getScripts()} {staticMarkup ? null : this.getScripts()}
</div> </div>
} }

View file

@ -5,7 +5,6 @@ import onDemandEntryHandler from './on-demand-entry-handler'
import isWindowsBash from 'is-windows-bash' import isWindowsBash from 'is-windows-bash'
import webpack from './build/webpack' import webpack from './build/webpack'
import clean from './build/clean' import clean from './build/clean'
import readPage from './read-page'
import getConfig from './config' import getConfig from './config'
export default class HotReloader { export default class HotReloader {
@ -202,7 +201,6 @@ export default class HotReloader {
function deleteCache (path) { function deleteCache (path) {
delete require.cache[path] delete require.cache[path]
delete readPage.cache[path]
} }
function diff (a, b) { function diff (a, b) {

View file

@ -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