mirror of
https://github.com/terribleplan/next.js.git
synced 2024-01-19 02:48:18 +00:00
dec85fe6c4
* Introduce script tag based page loading system. * Call ensurePage only in the dev mode. * Implement router using the page-loader. * Fix a typo and remove unwanted code. * Fix some issues related to rendering. * Fix production tests. * Fix ondemand test cases. * Fix unit tests. * Get rid of eval completely. * Remove all the inline code. * Remove the json-pages plugin. * Rename NEXT_PAGE_LOADER into __NEXT_PAGE_LOADER__ * Rename NEXT_LOADED_PAGES into __NEXT_LOADED_PAGES__ * Remove some unwanted code. * Load everything async. * Remove lib/eval-script.js We no longer need it. * Move webpack idle wait code to the page-loader. Because that's the place to do it. * Remove pageNotFound key from the error. * Remove unused error field 'buildError' * Add much better logic to normalize routes. * Get rid of mitt. * Introduce a better way to register pages. * Came back to the mitt() based page-loader. * Add link rel=preload support. * Add assetPrefix support to add support for CDNs. * Add assetPrefix support for preload links. * Update readme.md
103 lines
2.6 KiB
JavaScript
103 lines
2.6 KiB
JavaScript
/* global window, document */
|
|
import mitt from 'mitt'
|
|
|
|
const webpackModule = module
|
|
|
|
export default class PageLoader {
|
|
constructor (buildId, assetPrefix) {
|
|
this.buildId = buildId
|
|
this.assetPrefix = assetPrefix
|
|
|
|
this.pageCache = {}
|
|
this.pageLoadedHandlers = {}
|
|
this.registerEvents = mitt()
|
|
this.loadingRoutes = {}
|
|
}
|
|
|
|
normalizeRoute (route) {
|
|
if (route[0] !== '/') {
|
|
throw new Error('Route name should start with a "/"')
|
|
}
|
|
|
|
return route.replace(/index$/, '')
|
|
}
|
|
|
|
loadPage (route) {
|
|
route = this.normalizeRoute(route)
|
|
|
|
const cachedPage = this.pageCache[route]
|
|
if (cachedPage) {
|
|
return new Promise((resolve, reject) => {
|
|
if (cachedPage.error) return reject(cachedPage.error)
|
|
return resolve(cachedPage.page)
|
|
})
|
|
}
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const fire = ({ error, page }) => {
|
|
this.registerEvents.off(route, fire)
|
|
|
|
if (error) {
|
|
reject(error)
|
|
} else {
|
|
resolve(page)
|
|
}
|
|
}
|
|
|
|
this.registerEvents.on(route, fire)
|
|
|
|
// Load the script if not asked to load yet.
|
|
if (!this.loadingRoutes[route]) {
|
|
this.loadScript(route)
|
|
this.loadingRoutes[route] = true
|
|
}
|
|
})
|
|
}
|
|
|
|
loadScript (route) {
|
|
route = this.normalizeRoute(route)
|
|
|
|
const script = document.createElement('script')
|
|
const url = `${this.assetPrefix}/_next/${encodeURIComponent(this.buildId)}/page${route}`
|
|
script.src = url
|
|
script.type = 'text/javascript'
|
|
script.onerror = () => {
|
|
const error = new Error(`Error when loading route: ${route}`)
|
|
this.registerEvents.emit(route, { error })
|
|
}
|
|
|
|
document.body.appendChild(script)
|
|
}
|
|
|
|
// This method if called by the route code.
|
|
registerPage (route, regFn) {
|
|
const register = () => {
|
|
const { error, page } = regFn()
|
|
this.pageCache[route] = { error, page }
|
|
this.registerEvents.emit(route, { error, page })
|
|
}
|
|
|
|
// Wait for webpack to became idle if it's not.
|
|
// More info: https://github.com/zeit/next.js/pull/1511
|
|
if (webpackModule && webpackModule.hot && webpackModule.hot.status() !== 'idle') {
|
|
console.log(`Waiting webpack to became "idle" to initialize the page: "${route}"`)
|
|
|
|
const check = (status) => {
|
|
if (status === 'idle') {
|
|
webpackModule.hot.removeStatusHandler(check)
|
|
register()
|
|
}
|
|
}
|
|
webpackModule.hot.status(check)
|
|
} else {
|
|
register()
|
|
}
|
|
}
|
|
|
|
clearCache (route) {
|
|
route = this.normalizeRoute(route)
|
|
delete this.pageCache[route]
|
|
delete this.loadingRoutes[route]
|
|
}
|
|
}
|