1+ /* global NEXT_PAGE_LOADER */
2+
13import { parse , format } from 'url'
24import mitt from 'mitt'
3- import fetch from 'unfetch'
4- import evalScript from '../eval-script'
55import shallowEquals from '../shallow-equals'
66import PQueue from '../p-queue'
77import { loadGetInitialProps , getURL } from '../utils'
@@ -15,10 +15,13 @@ export default class Router {
1515 this . route = toRoute ( pathname )
1616
1717 // set up the component cache (by route keys)
18- this . components = { [ this . route ] : { Component, err } }
19-
20- // contain a map of promise of fetch routes
21- this . fetchingRoutes = { }
18+ this . components = { }
19+ // We should not keep the cache, if there's an error
20+ // Otherwise, this cause issues when when going back and
21+ // come again to the errored page.
22+ if ( Component !== ErrorComponent ) {
23+ this . components [ this . route ] = { Component, err }
24+ }
2225
2326 // Handling Router Events
2427 this . events = mitt ( )
@@ -77,7 +80,7 @@ export default class Router {
7780
7881 async reload ( route ) {
7982 delete this . components [ route ]
80- delete this . fetchingRoutes [ route ]
83+ NEXT_PAGE_LOADER . clearCache ( route )
8184
8285 if ( route !== this . route ) return
8386
@@ -186,11 +189,11 @@ export default class Router {
186189 try {
187190 routeInfo = this . components [ route ]
188191 if ( ! routeInfo ) {
189- routeInfo = await this . fetchComponent ( route , as )
192+ routeInfo = { Component : await this . fetchComponent ( route , as ) }
190193 }
191194
192- const { Component, err , jsonPageRes } = routeInfo
193- const ctx = { err , pathname, query, jsonPageRes }
195+ const { Component } = routeInfo
196+ const ctx = { pathname, query }
194197 routeInfo . props = await this . getInitialProps ( Component , ctx )
195198
196199 this . components [ route ] = routeInfo
@@ -199,13 +202,27 @@ export default class Router {
199202 return { error : err }
200203 }
201204
205+ if ( err . buildIdMismatched ) {
206+ // Now we need to reload the page or do the action asked by the user
207+ _notifyBuildIdMismatch ( as )
208+ // We also need to cancel this current route change.
209+ // We do it like this.
210+ err . cancelled = true
211+ return { error : err }
212+ }
213+
214+ if ( err . pageNotFound ) {
215+ // Indicate main error display logic to
216+ // ignore rendering this error as a runtime error.
217+ err . ignore = true
218+ }
219+
202220 const Component = this . ErrorComponent
203221 routeInfo = { Component, err }
204222 const ctx = { err, pathname, query }
205223 routeInfo . props = await this . getInitialProps ( Component , ctx )
206224
207225 routeInfo . error = err
208- console . error ( err )
209226 }
210227
211228 return routeInfo
@@ -268,28 +285,7 @@ export default class Router {
268285 cancelled = true
269286 }
270287
271- const jsonPageRes = await this . fetchRoute ( route )
272- let jsonData
273- // We can call .json() only once for a response.
274- // That's why we need to keep a copy of data if we already parsed it.
275- if ( jsonPageRes . data ) {
276- jsonData = jsonPageRes . data
277- } else {
278- jsonData = jsonPageRes . data = await jsonPageRes . json ( )
279- }
280-
281- if ( jsonData . buildIdMismatch ) {
282- _notifyBuildIdMismatch ( as )
283-
284- const error = Error ( 'Abort due to BUILD_ID mismatch' )
285- error . cancelled = true
286- throw error
287- }
288-
289- const newData = {
290- ...await loadComponent ( jsonData ) ,
291- jsonPageRes
292- }
288+ const Component = await this . fetchRoute ( route )
293289
294290 if ( cancelled ) {
295291 const error = new Error ( `Abort fetching component for route: "${ route } "` )
@@ -301,7 +297,7 @@ export default class Router {
301297 this . componentLoadCancel = null
302298 }
303299
304- return newData
300+ return Component
305301 }
306302
307303 async getInitialProps ( Component , ctx ) {
@@ -324,24 +320,22 @@ export default class Router {
324320 return props
325321 }
326322
327- fetchRoute ( route ) {
328- let promise = this . fetchingRoutes [ route ]
329- if ( ! promise ) {
330- promise = this . fetchingRoutes [ route ] = this . doFetchRoute ( route )
323+ async fetchRoute ( route ) {
324+ // Wait for webpack to became idle if it's not.
325+ // More info: https://github.com/zeit/next.js/pull/1511
326+ if ( webpackModule && webpackModule . hot && webpackModule . hot . status ( ) !== 'idle' ) {
327+ await new Promise ( ( resolve ) => {
328+ const check = ( status ) => {
329+ if ( status === 'idle' ) {
330+ webpackModule . hot . removeStatusHandler ( check )
331+ resolve ( )
332+ }
333+ }
334+ webpackModule . hot . status ( check )
335+ } )
331336 }
332337
333- return promise
334- }
335-
336- doFetchRoute ( route ) {
337- const { buildId } = window . __NEXT_DATA__
338- const url = `/_next/${ encodeURIComponent ( buildId ) } /pages${ route } `
339-
340- return fetch ( url , {
341- method : 'GET' ,
342- credentials : 'same-origin' ,
343- headers : { 'Accept' : 'application/json' }
344- } )
338+ return await NEXT_PAGE_LOADER . loadPage ( route )
345339 }
346340
347341 abortComponentLoad ( as ) {
@@ -365,22 +359,3 @@ export default class Router {
365359function toRoute ( path ) {
366360 return path . replace ( / \/ $ / , '' ) || '/'
367361}
368-
369- async function loadComponent ( jsonData ) {
370- if ( webpackModule && webpackModule . hot && webpackModule . hot . status ( ) !== 'idle' ) {
371- await new Promise ( ( resolve ) => {
372- const check = ( status ) => {
373- if ( status === 'idle' ) {
374- webpackModule . hot . removeStatusHandler ( check )
375- resolve ( )
376- }
377- }
378- webpackModule . hot . status ( check )
379- } )
380- }
381-
382- const module = evalScript ( jsonData . component )
383- const Component = module . default || module
384-
385- return { Component, err : jsonData . err }
386- }
0 commit comments