diff --git a/lib/page-loader.js b/lib/page-loader.js index 866216fe..0dac7030 100644 --- a/lib/page-loader.js +++ b/lib/page-loader.js @@ -1,4 +1,6 @@ /* global window, document */ +import mitt from 'mitt' + const webpackModule = module export default class PageLoader { @@ -6,6 +8,7 @@ export default class PageLoader { this.buildId = buildId this.pageCache = {} this.pageLoadedHandlers = {} + this.registerEvents = mitt() this.loadingRoutes = {} } @@ -14,8 +17,7 @@ export default class PageLoader { throw new Error('Route name should start with a "/"') } - if (route === '/') return route - return route.replace(/(\/)?(index)?$/, '') + return route.replace(/index$/, '') } loadPage (route) { @@ -29,41 +31,37 @@ export default class PageLoader { }) } - if (this.loadingRoutes[route]) { - return this.loadingRoutes[route] - } + return new Promise((resolve, reject) => { + const fire = ({ error, page }) => { + this.registerEvents.off(route, fire) - const loadingPromise = new Promise((resolve, reject) => { - this.loadScript(route, (error) => { - delete this.loadingRoutes[route] + if (error) { + reject(error) + } else { + resolve(page) + } + } - if (error) return reject(error) + this.registerEvents.on(route, fire) - const cachedPage = this.pageCache[route] - if (cachedPage.error) return reject(cachedPage.error) - return resolve(cachedPage.page) - }) + // Load the script if not asked to load yet. + if (!this.loadingRoutes[route]) { + this.loadScript(route) + this.loadingRoutes[route] = true + } }) - - this.loadingRoutes[route] = loadingPromise - return loadingPromise } - loadScript (route, fn) { + loadScript (route) { route = this.normalizeRoute(route) const script = document.createElement('script') const url = `/_next/${encodeURIComponent(this.buildId)}/page${route}` script.src = url script.type = 'text/javascript' - - script.onerror = (e) => { - const error = new Error(`Network error occurred when loading route: ${route}`) - fn(error) - } - - script.onload = () => { - fn() + script.onerror = () => { + const error = new Error(`Error when loading route: ${route}`) + this.registerEvents.emit(route, { error }) } document.body.appendChild(script) @@ -71,12 +69,10 @@ export default class PageLoader { // This method if called by the route code. registerPage (route, regFn) { - route = this.normalizeRoute(route) - const register = () => { - // add the page to the cache 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.