Skip to content

Commit

Permalink
v9.0.4-canary.3
Browse files Browse the repository at this point in the history
  • Loading branch information
timneutkens committed Aug 11, 2019
1 parent a90a555 commit 963726d
Show file tree
Hide file tree
Showing 6 changed files with 7 additions and 7 deletions.
2 changes: 1 addition & 1 deletion lerna.json
Expand Up @@ -17,5 +17,5 @@
"registry": "https://registry.npmjs.org/"
}
},
"version": "9.0.4-canary.2"
"version": "9.0.4-canary.3"
}
2 changes: 1 addition & 1 deletion packages/create-next-app/package.json
@@ -1,6 +1,6 @@
{
"name": "create-next-app",
"version": "9.0.4-canary.2",
"version": "9.0.4-canary.3",
"keywords": [
"react",
"next",
Expand Down
2 changes: 1 addition & 1 deletion packages/next-bundle-analyzer/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/bundle-analyzer",
"version": "9.0.4-canary.2",
"version": "9.0.4-canary.3",

This comment has been minimized.

Copy link
@mvasilkov

mvasilkov Aug 12, 2019

Contributor

yarn info @next/bundle-analyzer shows 9.0.4-canary.2 to be the latest canary still.

This comment has been minimized.

Copy link
@ilionic

ilionic Aug 12, 2019

Same for next, 9.0.4-canary.2 is latest version on npm

This comment has been minimized.

Copy link
@c0b41

c0b41 Aug 12, 2019

Contributor

@timneutkens can we get new canary to npm?

This comment has been minimized.

Copy link
@ijjk

ijjk Aug 12, 2019

Member

Hi, the 9.0.4-canary.3 release should be up now

"main": "index.js",
"license": "MIT",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion packages/next-mdx/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/mdx",
"version": "9.0.4-canary.2",
"version": "9.0.4-canary.3",
"main": "index.js",
"license": "MIT",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion packages/next-server/package.json
@@ -1,6 +1,6 @@
{
"name": "next-server",
"version": "9.0.4-canary.2",
"version": "9.0.4-canary.3",
"main": "./index.js",
"license": "MIT",
"repository": "zeit/next.js",
Expand Down
4 changes: 2 additions & 2 deletions packages/next/package.json
@@ -1,6 +1,6 @@
{
"name": "next",
"version": "9.0.4-canary.2",
"version": "9.0.4-canary.3",
"description": "The React Framework",
"main": "./dist/server/next.js",
"license": "MIT",
Expand Down Expand Up @@ -83,7 +83,7 @@
"launch-editor": "2.2.1",
"loader-utils": "1.2.3",
"mkdirp": "0.5.1",
"next-server": "9.0.4-canary.2",
"next-server": "9.0.4-canary.3",
"prop-types": "15.7.2",
"prop-types-exact": "1.2.0",
"react-error-overlay": "5.1.6",
Expand Down

1 comment on commit 963726d

@ijjk
Copy link
Member

@ijjk ijjk commented on 963726d Aug 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stats from current release

Click to expand stats ⚠️ Total Bundle Size Increase ⚠️
zeit/next.js master zeit/next.js refs/tags/v9.0.4-canary.3 Change
Build Duration 20.1s 20.1s -48ms
node_modules Size 41.5 MB 41.6 MB ⚠️ +49.7 kB
Total Bundle (main, webpack, commons) Size 213 kB 214 kB ⚠️ +1.06 kB
Total Bundle (main, webpack, commons) gzip Size 70.1 kB 70.6 kB ⚠️ +550 B
Total Bundle (main, webpack, commons) Modern Size 188 kB 189 kB ⚠️ +691 B
Total Bundle (main, webpack, commons) Modern gzip Size 62 kB 62.4 kB ⚠️ +388 B
Client _app Size 2.39 kB 2.35 kB -35 B
Client _app gzip Size 1.08 kB 1.07 kB -8 B
Client _app Modern Size 1.83 kB 1.79 kB -35 B
Client _app gzip Modern Size 890 B 880 B -10 B
Client _error Size 8.22 kB 8.22 kB
Client _error gzip Size 3.16 kB 3.16 kB
Client _error Modern Size 5.85 kB 5.85 kB
Client _error gzip Modern Size 2.33 kB 2.33 kB
Client pages/index Size 343 B 343 B
Client pages/index gzip Size 246 B 246 B
Client pages/index Modern Size 319 B 319 B
Client pages/index gzip Modern Size 254 B 254 B
Client pages/link Size 4.08 kB 4.18 kB ⚠️ +104 B
Client pages/link gzip Size 1.8 kB 1.82 kB ⚠️ +26 B
Client pages/link Modern Size 3.7 kB 3.81 kB ⚠️ +113 B
Client pages/link gzip Modern Size 1.7 kB 1.72 kB ⚠️ +28 B
Client pages/routerDirect Size 423 B 423 B
Client pages/routerDirect gzip Size 306 B 306 B
Client pages/routerDirect Modern Size 411 B 411 B
Client pages/routerDirect gzip Modern Size 314 B 314 B
Client pages/withRouter Size 435 B 435 B
Client pages/withRouter gzip Size 301 B 301 B
Client pages/withRouter Modern Size 423 B 423 B
Client pages/withRouter gzip Modern Size 309 B 309 B
Client main Size 15.8 kB 16.3 kB ⚠️ +474 B
Client main gzip Size 5.44 kB 5.73 kB ⚠️ +286 B
Client main Modern Size 12.9 kB 13.1 kB ⚠️ +232 B
Client main Modern gzip Size 4.81 kB 4.99 kB ⚠️ +185 B
Client commons Size 195 kB 195 kB ⚠️ +623 B
Client commons gzip Size 63.3 kB 63.6 kB ⚠️ +272 B
Client commons Modern Size 176 kB 176 kB ⚠️ +459 B
Client commons Modern gzip Size 57.2 kB 57.4 kB ⚠️ +203 B
Client webpack Size 1.49 kB 1.53 kB ⚠️ +43 B
Client webpack gzip Size 770 B 778 B ⚠️ +8 B
Client webpack Modern Size 1.49 kB 1.53 kB ⚠️ +43 B
Client webpack Modern gzip Size 777 B 785 B ⚠️ +8 B
Base Rendered Size 2.76 kB 2.76 kB
Build Dir Size 1.42 MB 1.44 MB ⚠️ +12.9 kB
Click to expand serverless stats ⚠️ Total Bundle Size Increase ⚠️
zeit/next.js master zeit/next.js refs/tags/v9.0.4-canary.3 Change
Build Duration 21.3s 21.8s ⚠️ +468ms
node_modules Size 41.5 MB 41.6 MB ⚠️ +49.7 kB
Total Bundle (main, webpack, commons) Size 213 kB 214 kB ⚠️ +1.06 kB
Total Bundle (main, webpack, commons) gzip Size 70.1 kB 70.6 kB ⚠️ +550 B
Total Bundle (main, webpack, commons) Modern Size 188 kB 189 kB ⚠️ +691 B
Total Bundle (main, webpack, commons) Modern gzip Size 62 kB 62.4 kB ⚠️ +388 B
Client _app Size 2.39 kB 2.35 kB -35 B
Client _app gzip Size 1.08 kB 1.07 kB -8 B
Client _app Modern Size 1.83 kB 1.79 kB -35 B
Client _app gzip Modern Size 890 B 880 B -10 B
Client _error Size 8.22 kB 8.22 kB
Client _error gzip Size 3.16 kB 3.16 kB
Client _error Modern Size 5.85 kB 5.85 kB
Client _error gzip Modern Size 2.33 kB 2.33 kB
Client pages/index Size 343 B 343 B
Client pages/index gzip Size 246 B 246 B
Client pages/index Modern Size 319 B 319 B
Client pages/index gzip Modern Size 254 B 254 B
Client pages/link Size 4.08 kB 4.18 kB ⚠️ +104 B
Client pages/link gzip Size 1.8 kB 1.82 kB ⚠️ +26 B
Client pages/link Modern Size 3.7 kB 3.81 kB ⚠️ +113 B
Client pages/link gzip Modern Size 1.7 kB 1.72 kB ⚠️ +28 B
Client pages/routerDirect Size 423 B 423 B
Client pages/routerDirect gzip Size 306 B 306 B
Client pages/routerDirect Modern Size 411 B 411 B
Client pages/routerDirect gzip Modern Size 314 B 314 B
Client pages/withRouter Size 435 B 435 B
Client pages/withRouter gzip Size 301 B 301 B
Client pages/withRouter Modern Size 423 B 423 B
Client pages/withRouter gzip Modern Size 309 B 309 B
Client main Size 15.8 kB 16.3 kB ⚠️ +474 B
Client main gzip Size 5.44 kB 5.73 kB ⚠️ +286 B
Client main Modern Size 12.9 kB 13.1 kB ⚠️ +232 B
Client main Modern gzip Size 4.81 kB 4.99 kB ⚠️ +185 B
Client commons Size 195 kB 195 kB ⚠️ +623 B
Client commons gzip Size 63.3 kB 63.6 kB ⚠️ +272 B
Client commons Modern Size 176 kB 176 kB ⚠️ +459 B
Client commons Modern gzip Size 57.2 kB 57.4 kB ⚠️ +203 B
Client webpack Size 1.49 kB 1.53 kB ⚠️ +43 B
Client webpack gzip Size 770 B 778 B ⚠️ +8 B
Client webpack Modern Size 1.49 kB 1.53 kB ⚠️ +43 B
Client webpack Modern gzip Size 777 B 785 B ⚠️ +8 B
Serverless pages/link Size 255 kB 256 kB ⚠️ +1.34 kB
Serverless pages/link gzip Size 68.4 kB 68.8 kB ⚠️ +476 B
Serverless pages/index Size 247 kB 249 kB ⚠️ +1.07 kB
Serverless pages/index gzip Size 66.2 kB 66.6 kB ⚠️ +407 B
Serverless pages/_error Size 247 kB 248 kB ⚠️ +1.07 kB
Serverless pages/_error gzip Size 65.9 kB 66.3 kB ⚠️ +404 B
Serverless pages/routerDirect Size 248 kB 249 kB ⚠️ +1.07 kB
Serverless pages/routerDirect gzip Size 66.1 kB 66.5 kB ⚠️ +408 B
Serverless pages/withRouter Size 248 kB 249 kB ⚠️ +1.07 kB
Serverless pages/withRouter gzip Size 66.2 kB 66.6 kB ⚠️ +403 B
Build Dir Size 2.62 MB 2.64 MB ⚠️ +20.4 kB
Diff for main.js
@@ -1,20 +1,5 @@
 (window["webpackJsonp"] = window["webpackJsonp"] || []).push([[8],{
 
-/***/ "+iuc":
-/***/ (function(module, exports, __webpack_require__) {
-
-__webpack_require__("wgeU");
-__webpack_require__("FlQf");
-__webpack_require__("bBy9");
-__webpack_require__("B9jh");
-__webpack_require__("dL40");
-__webpack_require__("xvv9");
-__webpack_require__("V+O7");
-module.exports = __webpack_require__("WEpk").Set;
-
-
-/***/ }),
-
 /***/ "+oT+":
 /***/ (function(module, exports, __webpack_require__) {
 
@@ -69,28 +54,6 @@ __webpack_require__("cHUd")('Map');
 
 /***/ }),
 
-/***/ "B9jh":
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-var strong = __webpack_require__("Wu5q");
-var validate = __webpack_require__("n3ko");
-var SET = 'Set';
-
-// 23.2 Set Objects
-module.exports = __webpack_require__("raTm")(SET, function (get) {
-  return function Set() { return get(this, arguments.length > 0 ? arguments[0] : undefined); };
-}, {
-  // 23.2.3.1 Set.prototype.add(value)
-  add: function add(value) {
-    return strong.def(validate(this, SET), value = value === 0 ? 0 : value, value);
-  }
-}, strong);
-
-
-/***/ }),
-
 /***/ "BMP1":
 /***/ (function(module, exports, __webpack_require__) {
 
@@ -503,7 +466,7 @@ function () {
   var _ref2 = (0, _asyncToGenerator2["default"])(
   /*#__PURE__*/
   _regenerator["default"].mark(function _callee(_temp) {
-    var _ref, passedWebpackHMR, initialErr, _require, isValidElementType;
+    var _ref, passedWebpackHMR, initialErr, _require, isValidElementType, renderCtx, appCtx;
 
     return _regenerator["default"].wrap(function _callee$(_context) {
       while (1) {
@@ -584,16 +547,41 @@ function () {
                 });
               }
             });
-            render({
+            renderCtx = {
               App: App,
               Component: Component,
               props: props,
               err: initialErr,
               emitter: emitter
-            });
+            };
+            render(renderCtx);
+
+            if (!(window.__NEXT_DATA__.skeleton && Component.getInitialProps)) {
+              _context.next = 32;
+              break;
+            }
+
+            appCtx = {
+              router: router,
+              AppTree: wrapApp(App),
+              Component: Component,
+              ctx: {
+                pathname: page,
+                asPath: asPath,
+                query: query
+              }
+            };
+            _context.next = 30;
+            return App.getInitialProps(appCtx);
+
+          case 30:
+            props.pageProps = _context.sent.pageProps;
+            render(renderCtx);
+
+          case 32:
             return _context.abrupt("return", emitter);
 
-          case 26:
+          case 33:
           case "end":
             return _context.stop();
         }
@@ -746,14 +734,48 @@ function _renderError() {
 var isInitialRender = typeof _reactDom["default"].hydrate === 'function';
 
 function renderReactElement(reactEl, domEl) {
-  // The check for `.hydrate` is there to support React alternatives like preact
+  // mark start of hydrate/render
+  if (_utils.SUPPORTS_PERFORMANCE_USER_TIMING) {
+    performance.mark('beforeRender');
+  } // The check for `.hydrate` is there to support React alternatives like preact
+
+
   if (isInitialRender) {
-    _reactDom["default"].hydrate(reactEl, domEl);
+    _reactDom["default"].hydrate(reactEl, domEl, markHydrateComplete);
 
     isInitialRender = false;
   } else {
-    _reactDom["default"].render(reactEl, domEl);
+    _reactDom["default"].render(reactEl, domEl, markRenderComplete);
+  }
+}
+
+function markHydrateComplete() {
+  if (!_utils.SUPPORTS_PERFORMANCE_USER_TIMING) return;
+  performance.mark('afterHydrate'); // mark end of hydration
+
+  performance.measure('Next.js-before-hydration', null, 'beforeRender');
+  performance.measure('Next.js-hydration', 'beforeRender', 'afterHydrate');
+  clearMarks();
+}
+
+function markRenderComplete() {
+  if (!_utils.SUPPORTS_PERFORMANCE_USER_TIMING) return;
+  performance.mark('afterRender'); // mark end of render
+
+  var navStartEntries = performance.getEntriesByName('routeChange', 'mark');
+
+  if (!navStartEntries.length) {
+    return;
   }
+
+  performance.measure('Next.js-route-change-to-render', navStartEntries[0].name, 'beforeRender');
+  performance.measure('Next.js-render', 'beforeRender', 'afterRender');
+  clearMarks();
+}
+
+function clearMarks() {
+  performance.clearMarks();
+  performance.clearMeasures();
 }
 
 function AppContainer(_ref4) {
@@ -894,15 +916,6 @@ module.exports = __webpack_require__("WEpk").Map;
 
 /***/ }),
 
-/***/ "V+O7":
-/***/ (function(module, exports, __webpack_require__) {
-
-// https://tc39.github.io/proposal-setmap-offrom/#sec-set.from
-__webpack_require__("aPfg")('Set');
-
-
-/***/ }),
-
 /***/ "XLbu":
 /***/ (function(module, exports, __webpack_require__) {
 
@@ -970,17 +983,6 @@ exports.DataManager = DataManager;
 
 /***/ }),
 
-/***/ "dL40":
-/***/ (function(module, exports, __webpack_require__) {
-
-// https://github.com/DavidBruant/Map-Set.prototype.toJSON
-var $export = __webpack_require__("Y7ZC");
-
-$export($export.P + $export.R, 'Set', { toJSON: __webpack_require__("8iia")('Set') });
-
-
-/***/ }),
-
 /***/ "dVTT":
 /***/ (function(module, exports, __webpack_require__) {
 
@@ -1058,22 +1060,6 @@ exports.DataManagerContext = React.createContext(null);
 
 /***/ }),
 
-/***/ "ttDY":
-/***/ (function(module, exports, __webpack_require__) {
-
-module.exports = __webpack_require__("+iuc");
-
-/***/ }),
-
-/***/ "xvv9":
-/***/ (function(module, exports, __webpack_require__) {
-
-// https://tc39.github.io/proposal-setmap-offrom/#sec-set.of
-__webpack_require__("cHUd")('Set');
-
-
-/***/ }),
-
 /***/ "zmvN":
 /***/ (function(module, exports, __webpack_require__) {
 
@@ -1097,28 +1083,30 @@ var _asyncToGenerator2 = _interopRequireDefault(__webpack_require__("+oT+"));
 
 var _promise = _interopRequireDefault(__webpack_require__("eVuF"));
 
-var _set = _interopRequireDefault(__webpack_require__("ttDY"));
-
 var _mitt = _interopRequireDefault(__webpack_require__("kiME"));
 
 var _unfetch = _interopRequireDefault(__webpack_require__("m/Gl"));
-/* global document */
-// smaller version of https://gist.github.com/igrigorik/a02f2359f3bc50ca7a9c
-
+/* global document, window */
 
-function supportsPreload(list) {
-  if (!list || !list.supports) {
-    return false;
-  }
 
+function supportsPreload(el) {
   try {
-    return list.supports('preload');
-  } catch (e) {
+    return el.relList.supports('preload');
+  } catch (_unused) {
     return false;
   }
 }
 
-var hasPreload = supportsPreload(document.createElement('link').relList);
+var hasPreload = supportsPreload(document.createElement('link'));
+
+function preloadScript(url) {
+  var link = document.createElement('link');
+  link.rel = 'preload';
+  link.crossOrigin = "anonymous";
+  link.href = url;
+  link.as = 'script';
+  document.head.appendChild(link);
+}
 
 var PageLoader =
 /*#__PURE__*/
@@ -1128,13 +1116,24 @@ function () {
     this.buildId = buildId;
     this.assetPrefix = assetPrefix;
     this.pageCache = {};
-    this.prefetchCache = new _set["default"]();
     this.pageRegisterEvents = (0, _mitt["default"])();
     this.loadingRoutes = {};
     this.promisedBuildId = _promise["default"].resolve();
-  }
+
+    if (false) {}
+  } // Returns a promise for the dependencies for a particular route
+
 
   (0, _createClass2["default"])(PageLoader, [{
+    key: "getDependencies",
+    value: function getDependencies(route) {
+      return this.promisedBuildManifest.then(function (man) {
+        return man[route] && man[route].map(function (url) {
+          return "/_next/" + url;
+        }) || [];
+      });
+    }
+  }, {
     key: "normalizeRoute",
     value: function normalizeRoute(route) {
       if (route[0] !== '/') {
@@ -1184,13 +1183,14 @@ function () {
 
         if (document.getElementById("__NEXT_PAGE__" + route)) {
           return;
-        } // Load the script if not asked to load yet.
-
+        }
 
         if (!_this3.loadingRoutes[route]) {
-          _this3.loadScript(route);
+          if (false) {} else {
+            _this3.loadRoute(route);
 
-          _this3.loadingRoutes[route] = true;
+            _this3.loadingRoutes[route] = true;
+          }
         }
       });
     }
@@ -1220,14 +1220,14 @@ function () {
       });
     }
   }, {
-    key: "loadScript",
-    value: function loadScript(route) {
+    key: "loadRoute",
+    value: function loadRoute(route) {
       var _this = this;
 
       return (0, _asyncToGenerator2["default"])(
       /*#__PURE__*/
       _regenerator["default"].mark(function _callee() {
-        var scriptRoute, script, url;
+        var scriptRoute, url;
         return _regenerator["default"].wrap(function _callee$(_context) {
           while (1) {
             switch (_context.prev = _context.next) {
@@ -1238,41 +1238,51 @@ function () {
               case 2:
                 route = _this.normalizeRoute(route);
                 scriptRoute = route === '/' ? '/index.js' : route + ".js";
-                script = document.createElement('script');
-
-                if ( true && 'noModule' in script) {
-                  script.type = 'module';
-                  scriptRoute = scriptRoute.replace(/\.js$/, '.module.js');
-                }
-
                 url = _this.assetPrefix + "/_next/static/" + encodeURIComponent(_this.buildId) + "/pages" + scriptRoute;
-                script.crossOrigin = "anonymous";
-                script.src = url;
 
-                script.onerror = function () {
-                  var error = new Error("Error loading script " + url);
-                  error.code = 'PAGE_LOAD_ERROR';
+                _this.loadScript(url, route, true);
 
-                  _this.pageRegisterEvents.emit(route, {
-                    error: error
-                  });
-                };
-
-                document.body.appendChild(script);
-
-              case 11:
+              case 6:
               case "end":
                 return _context.stop();
             }
           }
         }, _callee);
       }))();
+    }
+  }, {
+    key: "loadScript",
+    value: function loadScript(url, route, isPage) {
+      var _this5 = this;
+
+      var script = document.createElement('script');
+
+      if ( true && 'noModule' in script) {
+        script.type = 'module'; // Only page bundle scripts need to have .module added to url,
+        // dependencies already have it added during build manifest creation
+
+        if (isPage) url = url.replace(/\.js$/, '.module.js');
+      }
+
+      script.crossOrigin = "anonymous";
+      script.src = url;
+
+      script.onerror = function () {
+        var error = new Error("Error loading script " + url);
+        error.code = 'PAGE_LOAD_ERROR';
+
+        _this5.pageRegisterEvents.emit(route, {
+          error: error
+        });
+      };
+
+      document.body.appendChild(script);
     } // This method if called by the route code.
 
   }, {
     key: "registerPage",
     value: function registerPage(route, regFn) {
-      var _this5 = this;
+      var _this6 = this;
 
       var register = function register() {
         try {
@@ -1280,21 +1290,21 @@ function () {
               error = _regFn.error,
               page = _regFn.page;
 
-          _this5.pageCache[route] = {
+          _this6.pageCache[route] = {
             error: error,
             page: page
           };
 
-          _this5.pageRegisterEvents.emit(route, {
+          _this6.pageRegisterEvents.emit(route, {
             error: error,
             page: page
           });
         } catch (error) {
-          _this5.pageCache[route] = {
+          _this6.pageCache[route] = {
             error: error
           };
 
-          _this5.pageRegisterEvents.emit(route, {
+          _this6.pageRegisterEvents.emit(route, {
             error: error
           });
         }
@@ -1306,17 +1316,21 @@ function () {
     }
   }, {
     key: "prefetch",
-    value: function prefetch(route) {
+    value: function prefetch(route, isDependency) {
       var _this2 = this;
 
       return (0, _asyncToGenerator2["default"])(
       /*#__PURE__*/
       _regenerator["default"].mark(function _callee2() {
-        var scriptRoute, link;
+        var scriptRoute, url, cn;
         return _regenerator["default"].wrap(function _callee2$(_context2) {
           while (1) {
             switch (_context2.prev = _context2.next) {
               case 0:
+                _context2.next = 2;
+                return _this2.promisedBuildId;
+
+              case 2:
                 route = _this2.normalizeRoute(route);
                 scriptRoute = (route === '/' ? '/index' : route) + ".js";
 
@@ -1324,57 +1338,72 @@ function () {
                   scriptRoute = scriptRoute.replace(/\.js$/, '.module.js');
                 }
 
-                if (!(_this2.prefetchCache.has(scriptRoute) || document.getElementById("__NEXT_PAGE__" + route))) {
-                  _context2.next = 5;
+                url = isDependency ? route : _this2.assetPrefix + "/_next/static/" + encodeURIComponent(_this2.buildId) + "/pages" + scriptRoute; // n.b. If preload is not supported, we fall back to `loadPage` which has
+                // its own deduping mechanism.
+
+                if (!(document.querySelector("link[rel=\"preload\"][href^=\"" + url + "\"]") || document.getElementById("__NEXT_PAGE__" + route))) {
+                  _context2.next = 8;
                   break;
                 }
 
                 return _context2.abrupt("return");
 
-              case 5:
-                _this2.prefetchCache.add(scriptRoute); // Inspired by quicklink, license: https://github.com/GoogleChromeLabs/quicklink/blob/master/LICENSE
-                // Don't prefetch if the user is on 2G / Don't prefetch if Save-Data is enabled
-
-
-                if (!('connection' in navigator)) {
-                  _context2.next = 9;
+              case 8:
+                if (!(cn = navigator.connection)) {
+                  _context2.next = 11;
                   break;
                 }
 
-                if (!((navigator.connection.effectiveType || '').indexOf('2g') !== -1 || navigator.connection.saveData)) {
-                  _context2.next = 9;
+                if (!((cn.effectiveType || '').indexOf('2g') !== -1 || cn.saveData)) {
+                  _context2.next = 11;
                   break;
                 }
 
                 return _context2.abrupt("return");
 
-              case 9:
+              case 11:
+                if (true) {
+                  _context2.next = 17;
+                  break;
+                }
+
+                ;
+                _context2.next = 15;
+                return _this2.getDependencies(route);
+
+              case 15:
+                _context2.t0 = function (url) {
+                  _this2.prefetch(url, true);
+                };
+
+                _context2.sent.forEach(_context2.t0);
+
+              case 17:
                 if (!hasPreload) {
-                  _context2.next = 19;
+                  _context2.next = 20;
                   break;
                 }
 
-                _context2.next = 12;
-                return _this2.promisedBuildId;
+                preloadScript(url);
+                return _context2.abrupt("return");
+
+              case 20:
+                if (!isDependency) {
+                  _context2.next = 22;
+                  break;
+                }
 
-              case 12:
-                link = document.createElement('link');
-                link.rel = 'preload';
-                link.crossOrigin = "anonymous";
-                link.href = _this2.assetPrefix + "/_next/static/" + encodeURIComponent(_this2.buildId) + "/pages" + scriptRoute;
-                link.as = 'script';
-                document.head.appendChild(link);
                 return _context2.abrupt("return");
 
-              case 19:
+              case 22:
                 if (!(document.readyState === 'complete')) {
-                  _context2.next = 23;
+                  _context2.next = 26;
                   break;
                 }
 
                 return _context2.abrupt("return", _this2.loadPage(route)["catch"](function () {}));
 
-              case 23:
+              case 26:
                 return _context2.abrupt("return", new _promise["default"](function (resolve) {
                   window.addEventListener('load', function () {
                     _this2.loadPage(route).then(function () {
@@ -1385,7 +1414,7 @@ function () {
                   });
                 }));
 
-              case 24:
+              case 27:
               case "end":
                 return _context2.stop();
             }
@@ -1393,18 +1422,6 @@ function () {
         }, _callee2);
       }))();
     }
-  }, {
-    key: "clearCache",
-    value: function clearCache(route) {
-      route = this.normalizeRoute(route);
-      delete this.pageCache[route];
-      delete this.loadingRoutes[route];
-      var script = document.getElementById("__NEXT_PAGE__" + route);
-
-      if (script) {
-        script.parentNode.removeChild(script);
-      }
-    }
   }]);
   return PageLoader;
 }();
Diff for commons.js
@@ -1244,6 +1244,8 @@ function formatWithValidation(url, options) {
 }
 
 exports.formatWithValidation = formatWithValidation;
+exports.SUPPORTS_PERFORMANCE = typeof performance !== 'undefined';
+exports.SUPPORTS_PERFORMANCE_USER_TIMING = exports.SUPPORTS_PERFORMANCE && typeof performance.mark === 'function' && typeof performance.measure === 'function';
 
 /***/ }),
 
@@ -3196,8 +3198,13 @@ function () {
       var _this2 = this;
 
       return new _promise["default"](function (resolve, reject) {
-        // If url and as provided as an object representation,
+        // marking route changes as a navigation start entry
+        if (utils_1.SUPPORTS_PERFORMANCE_USER_TIMING) {
+          performance.mark('routeChange');
+        } // If url and as provided as an object representation,
         // we'll format them into the string version here.
+
+
         var url = typeof _url === 'object' ? utils_1.formatWithValidation(_url) : _url;
         var as = typeof _as === 'object' ? utils_1.formatWithValidation(_as) : _as; // Add the ending slash to the paths. So, we can serve the
         // "<page>/index.html" directly for the SSR page.
@@ -3225,7 +3232,14 @@ function () {
 
         var _url_1$parse = url_1.parse(url, true),
             pathname = _url_1$parse.pathname,
-            query = _url_1$parse.query; // If asked to change the current URL we should reload the current page
+            query = _url_1$parse.query,
+            protocol = _url_1$parse.protocol;
+
+        if (!pathname || protocol) {
+          if (false) {}
+
+          return resolve(false);
+        } // If asked to change the current URL we should reload the current page
         // (not location.reload() but reload getInitialProps and other Next.js stuffs)
         // We also need to set the method = replaceState always
         // as this should not go into the history (That's how browsers work)
@@ -3342,11 +3356,6 @@ function () {
           };
 
           _this3.getInitialProps(Component, ctx).then(function (props) {
-            // if data is inlined during prerender it is a string
-            if (props && typeof props.pageProps === 'string') {
-              props.pageProps = JSON.parse(props.pageProps);
-            }
-
             routeInfo.props = props;
             _this3.components[route] = routeInfo;
             resolve(routeInfo);
@@ -3499,12 +3508,18 @@ function () {
       var _this4 = this;
 
       return new _promise["default"](function (resolve, reject) {
-        // Prefetch is not supported in development mode because it would trigger on-demand-entries
-        if (false) {}
-
         var _url_1$parse3 = url_1.parse(url),
-            pathname = _url_1$parse3.pathname; // @ts-ignore pathname is always defined
+            pathname = _url_1$parse3.pathname,
+            protocol = _url_1$parse3.protocol;
+
+        if (!pathname || protocol) {
+          if (false) {}
 
+          return;
+        } // Prefetch is not supported in development mode because it would trigger on-demand-entries
+
+
+        if (false) {} // @ts-ignore pathname is always defined
 
         var route = toRoute(pathname);
 
@@ -3570,7 +3585,7 @@ function () {
       var _getInitialProps = (0, _asyncToGenerator2["default"])(
       /*#__PURE__*/
       _regenerator["default"].mark(function _callee2(Component, ctx) {
-        var cancelled, cancel, App, props, err;
+        var cancelled, cancel, App, props, url, res, err;
         return _regenerator["default"].wrap(function _callee2$(_context2) {
           while (1) {
             switch (_context2.prev = _context2.next) {
@@ -3583,7 +3598,59 @@ function () {
 
                 this.clc = cancel;
                 App = this.components['/_app'].Component;
-                _context2.next = 6;
+
+                if (!Component.__NEXT_PRERENDER) {
+                  _context2.next = 20;
+                  break;
+                }
+
+                url = url_1.format({
+                  pathname: ctx.asPath,
+                  query: ctx.query
+                });
+                _context2.next = 8;
+                return fetch(url, {
+                  headers: {
+                    'content-type': 'application/json'
+                  }
+                });
+
+              case 8:
+                res = _context2.sent;
+
+                if (!res.ok) {
+                  _context2.next = 15;
+                  break;
+                }
+
+                _context2.next = 12;
+                return res.json()["catch"](function (err) {
+                  return {
+                    error: err.message
+                  };
+                });
+
+              case 12:
+                _context2.t0 = _context2.sent;
+                _context2.next = 16;
+                break;
+
+              case 15:
+                _context2.t0 = {
+                  error: 'failed to load prerender',
+                  statusCode: res.status
+                };
+
+              case 16:
+                _context2.t1 = _context2.t0;
+                props = {
+                  pageProps: _context2.t1
+                };
+                _context2.next = 23;
+                break;
+
+              case 20:
+                _context2.next = 22;
                 return utils_1.loadGetInitialProps(App, {
                   AppTree: this._wrapApp(App),
                   Component: Component,
@@ -3591,15 +3658,16 @@ function () {
                   ctx: ctx
                 });
 
-              case 6:
+              case 22:
                 props = _context2.sent;
 
+              case 23:
                 if (cancel === this.clc) {
                   this.clc = null;
                 }
 
                 if (!cancelled) {
-                  _context2.next = 12;
+                  _context2.next = 28;
                   break;
                 }
 
@@ -3607,10 +3675,10 @@ function () {
                 err.cancelled = true;
                 throw err;
 
-              case 12:
+              case 28:
                 return _context2.abrupt("return", props);
 
-              case 13:
+              case 29:
               case "end":
                 return _context2.stop();
             }
@@ -6691,8 +6759,7 @@ var singletonRouter = {
   }
 }; // Create public properties and methods of the router in the singletonRouter
 
-var urlPropertyFields = ['pathname', 'route', 'query', 'asPath'];
-var propertyFields = ['components'];
+var urlPropertyFields = ['pathname', 'route', 'query', 'asPath', 'components'];
 var routerEvents = ['routeChangeStart', 'beforeHistoryChange', 'routeChangeComplete', 'routeChangeError', 'hashChangeStart', 'hashChangeComplete'];
 var coreMethodFields = ['push', 'replace', 'reload', 'back', 'prefetch', 'beforePopState']; // Events is a static property on the router, the router doesn't have to be initialized to use it
 
@@ -6701,7 +6768,7 @@ var coreMethodFields = ['push', 'replace', 'reload', 'back', 'prefetch', 'before
     return _router2["default"].events;
   }
 });
-propertyFields.concat(urlPropertyFields).forEach(function (field) {
+urlPropertyFields.forEach(function (field) {
   // Here we need to use Object.defineProperty because, we need to return
   // the property assigned to the actual router
   // The value might get changed as we change routes and this is the
@@ -6800,17 +6867,6 @@ function makePublicRouterInstance(router) {
 
 
   instance.events = _router2["default"].events;
-  propertyFields.forEach(function (field) {
-    // Here we need to use Object.defineProperty because, we need to return
-    // the property assigned to the actual router
-    // The value might get changed as we change routes and this is the
-    // proper way to access it
-    (0, _defineProperty["default"])(instance, field, {
-      get: function get() {
-        return _router[field];
-      }
-    });
-  });
   coreMethodFields.forEach(function (field) {
     instance[field] = function () {
       return _router[field].apply(_router, arguments);
Diff for webpack.js
@@ -10,7 +10,7 @@
 /******/ 		var moduleId, chunkId, i = 0, resolves = [];
 /******/ 		for(;i < chunkIds.length; i++) {
 /******/ 			chunkId = chunkIds[i];
-/******/ 			if(installedChunks[chunkId]) {
+/******/ 			if(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {
 /******/ 				resolves.push(installedChunks[chunkId][0]);
 /******/ 			}
 /******/ 			installedChunks[chunkId] = 0;
Diff for mainModern.js
@@ -1,20 +1,5 @@
 (window["webpackJsonp"] = window["webpackJsonp"] || []).push([[8],{
 
-/***/ "+iuc":
-/***/ (function(module, exports, __webpack_require__) {
-
-__webpack_require__("wgeU");
-__webpack_require__("FlQf");
-__webpack_require__("bBy9");
-__webpack_require__("B9jh");
-__webpack_require__("dL40");
-__webpack_require__("xvv9");
-__webpack_require__("V+O7");
-module.exports = __webpack_require__("WEpk").Set;
-
-
-/***/ }),
-
 /***/ "+oT+":
 /***/ (function(module, exports, __webpack_require__) {
 
@@ -69,28 +54,6 @@ __webpack_require__("cHUd")('Map');
 
 /***/ }),
 
-/***/ "B9jh":
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-var strong = __webpack_require__("Wu5q");
-var validate = __webpack_require__("n3ko");
-var SET = 'Set';
-
-// 23.2 Set Objects
-module.exports = __webpack_require__("raTm")(SET, function (get) {
-  return function Set() { return get(this, arguments.length > 0 ? arguments[0] : undefined); };
-}, {
-  // 23.2.3.1 Set.prototype.add(value)
-  add: function add(value) {
-    return strong.def(validate(this, SET), value = value === 0 ? 0 : value, value);
-  }
-}, strong);
-
-
-/***/ }),
-
 /***/ "BMP1":
 /***/ (function(module, exports, __webpack_require__) {
 
@@ -495,13 +458,30 @@ function () {
         });
       }
     });
-    render({
+    const renderCtx = {
       App,
       Component,
       props,
       err: initialErr,
       emitter
-    });
+    };
+    render(renderCtx);
+
+    if (window.__NEXT_DATA__.skeleton && Component.getInitialProps) {
+      const appCtx = {
+        router,
+        AppTree: wrapApp(App),
+        Component: Component,
+        ctx: {
+          pathname: page,
+          asPath,
+          query
+        }
+      };
+      props.pageProps = (yield App.getInitialProps(appCtx)).pageProps;
+      render(renderCtx);
+    }
+
     return emitter;
   });
 
@@ -582,14 +562,48 @@ function _renderError() {
 let isInitialRender = typeof _reactDom.default.hydrate === 'function';
 
 function renderReactElement(reactEl, domEl) {
-  // The check for `.hydrate` is there to support React alternatives like preact
+  // mark start of hydrate/render
+  if (_utils.SUPPORTS_PERFORMANCE_USER_TIMING) {
+    performance.mark('beforeRender');
+  } // The check for `.hydrate` is there to support React alternatives like preact
+
+
   if (isInitialRender) {
-    _reactDom.default.hydrate(reactEl, domEl);
+    _reactDom.default.hydrate(reactEl, domEl, markHydrateComplete);
 
     isInitialRender = false;
   } else {
-    _reactDom.default.render(reactEl, domEl);
+    _reactDom.default.render(reactEl, domEl, markRenderComplete);
+  }
+}
+
+function markHydrateComplete() {
+  if (!_utils.SUPPORTS_PERFORMANCE_USER_TIMING) return;
+  performance.mark('afterHydrate'); // mark end of hydration
+
+  performance.measure('Next.js-before-hydration', null, 'beforeRender');
+  performance.measure('Next.js-hydration', 'beforeRender', 'afterHydrate');
+  clearMarks();
+}
+
+function markRenderComplete() {
+  if (!_utils.SUPPORTS_PERFORMANCE_USER_TIMING) return;
+  performance.mark('afterRender'); // mark end of render
+
+  const navStartEntries = performance.getEntriesByName('routeChange', 'mark');
+
+  if (!navStartEntries.length) {
+    return;
   }
+
+  performance.measure('Next.js-route-change-to-render', navStartEntries[0].name, 'beforeRender');
+  performance.measure('Next.js-render', 'beforeRender', 'afterRender');
+  clearMarks();
+}
+
+function clearMarks() {
+  performance.clearMarks();
+  performance.clearMeasures();
 }
 
 function AppContainer(_ref4) {
@@ -712,15 +726,6 @@ module.exports = __webpack_require__("WEpk").Map;
 
 /***/ }),
 
-/***/ "V+O7":
-/***/ (function(module, exports, __webpack_require__) {
-
-// https://tc39.github.io/proposal-setmap-offrom/#sec-set.from
-__webpack_require__("aPfg")('Set');
-
-
-/***/ }),
-
 /***/ "XLbu":
 /***/ (function(module, exports, __webpack_require__) {
 
@@ -775,17 +780,6 @@ exports.DataManager = DataManager;
 
 /***/ }),
 
-/***/ "dL40":
-/***/ (function(module, exports, __webpack_require__) {
-
-// https://github.com/DavidBruant/Map-Set.prototype.toJSON
-var $export = __webpack_require__("Y7ZC");
-
-$export($export.P + $export.R, 'Set', { toJSON: __webpack_require__("8iia")('Set') });
-
-
-/***/ }),
-
 /***/ "dVTT":
 /***/ (function(module, exports, __webpack_require__) {
 
@@ -861,22 +855,6 @@ exports.DataManagerContext = React.createContext(null);
 
 /***/ }),
 
-/***/ "ttDY":
-/***/ (function(module, exports, __webpack_require__) {
-
-module.exports = __webpack_require__("+iuc");
-
-/***/ }),
-
-/***/ "xvv9":
-/***/ (function(module, exports, __webpack_require__) {
-
-// https://tc39.github.io/proposal-setmap-offrom/#sec-set.of
-__webpack_require__("cHUd")('Set');
-
-
-/***/ }),
-
 /***/ "zmvN":
 /***/ (function(module, exports, __webpack_require__) {
 
@@ -892,38 +870,46 @@ var _asyncToGenerator2 = _interopRequireDefault(__webpack_require__("+oT+"));
 
 var _promise = _interopRequireDefault(__webpack_require__("eVuF"));
 
-var _set = _interopRequireDefault(__webpack_require__("ttDY"));
-
 var _mitt = _interopRequireDefault(__webpack_require__("kiME"));
 
 var _unfetch = _interopRequireDefault(__webpack_require__("m/Gl"));
-/* global document */
-// smaller version of https://gist.github.com/igrigorik/a02f2359f3bc50ca7a9c
+/* global document, window */
 
 
-function supportsPreload(list) {
-  if (!list || !list.supports) {
-    return false;
-  }
-
+function supportsPreload(el) {
   try {
-    return list.supports('preload');
-  } catch (e) {
+    return el.relList.supports('preload');
+  } catch (_unused) {
     return false;
   }
 }
 
-const hasPreload = supportsPreload(document.createElement('link').relList);
+const hasPreload = supportsPreload(document.createElement('link'));
+
+function preloadScript(url) {
+  const link = document.createElement('link');
+  link.rel = 'preload';
+  link.crossOrigin = "anonymous";
+  link.href = url;
+  link.as = 'script';
+  document.head.appendChild(link);
+}
 
 class PageLoader {
   constructor(buildId, assetPrefix) {
     this.buildId = buildId;
     this.assetPrefix = assetPrefix;
     this.pageCache = {};
-    this.prefetchCache = new _set.default();
     this.pageRegisterEvents = (0, _mitt.default)();
     this.loadingRoutes = {};
     this.promisedBuildId = _promise.default.resolve();
+
+    if (false) {}
+  } // Returns a promise for the dependencies for a particular route
+
+
+  getDependencies(route) {
+    return this.promisedBuildManifest.then(man => man[route] && man[route].map(url => "/_next/" + url) || []);
   }
 
   normalizeRoute(route) {
@@ -972,12 +958,13 @@ class PageLoader {
 
       if (document.getElementById("__NEXT_PAGE__" + route)) {
         return;
-      } // Load the script if not asked to load yet.
-
+      }
 
       if (!this.loadingRoutes[route]) {
-        this.loadScript(route);
-        this.loadingRoutes[route] = true;
+        if (false) {} else {
+          this.loadRoute(route);
+          this.loadingRoutes[route] = true;
+        }
       }
     });
   }
@@ -1002,35 +989,41 @@ class PageLoader {
     });
   }
 
-  loadScript(route) {
+  loadRoute(route) {
     var _this = this;
 
     return (0, _asyncToGenerator2.default)(function* () {
       yield _this.promisedBuildId;
       route = _this.normalizeRoute(route);
       let scriptRoute = route === '/' ? '/index.js' : route + ".js";
-      const script = document.createElement('script');
+      const url = _this.assetPrefix + "/_next/static/" + encodeURIComponent(_this.buildId) + "/pages" + scriptRoute;
 
-      if ( true && 'noModule' in script) {
-        script.type = 'module';
-        scriptRoute = scriptRoute.replace(/\.js$/, '.module.js');
-      }
+      _this.loadScript(url, route, true);
+    })();
+  }
 
-      const url = _this.assetPrefix + "/_next/static/" + encodeURIComponent(_this.buildId) + "/pages" + scriptRoute;
-      script.crossOrigin = "anonymous";
-      script.src = url;
+  loadScript(url, route, isPage) {
+    const script = document.createElement('script');
 
-      script.onerror = () => {
-        const error = new Error("Error loading script " + url);
-        error.code = 'PAGE_LOAD_ERROR';
+    if ( true && 'noModule' in script) {
+      script.type = 'module'; // Only page bundle scripts need to have .module added to url,
+      // dependencies already have it added during build manifest creation
 
-        _this.pageRegisterEvents.emit(route, {
-          error
-        });
-      };
+      if (isPage) url = url.replace(/\.js$/, '.module.js');
+    }
 
-      document.body.appendChild(script);
-    })();
+    script.crossOrigin = "anonymous";
+    script.src = url;
+
+    script.onerror = () => {
+      const error = new Error("Error loading script " + url);
+      error.code = 'PAGE_LOAD_ERROR';
+      this.pageRegisterEvents.emit(route, {
+        error
+      });
+    };
+
+    document.body.appendChild(script);
   } // This method if called by the route code.
 
 
@@ -1064,10 +1057,11 @@ class PageLoader {
     register();
   }
 
-  prefetch(route) {
+  prefetch(route, isDependency) {
     var _this2 = this;
 
     return (0, _asyncToGenerator2.default)(function* () {
+      yield _this2.promisedBuildId;
       route = _this2.normalizeRoute(route);
       let scriptRoute = (route === '/' ? '/index' : route) + ".js";
 
@@ -1075,31 +1069,36 @@ class PageLoader {
         scriptRoute = scriptRoute.replace(/\.js$/, '.module.js');
       }
 
-      if (_this2.prefetchCache.has(scriptRoute) || document.getElementById("__NEXT_PAGE__" + route)) {
+      const url = isDependency ? route : _this2.assetPrefix + "/_next/static/" + encodeURIComponent(_this2.buildId) + "/pages" + scriptRoute; // n.b. If preload is not supported, we fall back to `loadPage` which has
+      // its own deduping mechanism.
+
+      if (document.querySelector("link[rel=\"preload\"][href^=\"" + url + "\"]") || document.getElementById("__NEXT_PAGE__" + route)) {
         return;
-      }
+      } // Inspired by quicklink, license: https://github.com/GoogleChromeLabs/quicklink/blob/master/LICENSE
 
-      _this2.prefetchCache.add(scriptRoute); // Inspired by quicklink, license: https://github.com/GoogleChromeLabs/quicklink/blob/master/LICENSE
-      // Don't prefetch if the user is on 2G / Don't prefetch if Save-Data is enabled
 
+      let cn;
 
-      if ('connection' in navigator) {
-        if ((navigator.connection.effectiveType || '').indexOf('2g') !== -1 || navigator.connection.saveData) {
+      if (cn = navigator.connection) {
+        // Don't prefetch if the user is on 2G or if Save-Data is enabled.
+        if ((cn.effectiveType || '').indexOf('2g') !== -1 || cn.saveData) {
           return;
         }
-      } // Feature detection is used to see if preload is supported
+      }
+
+      if (false) {} // Feature detection is used to see if preload is supported
       // If not fall back to loading script tags before the page is loaded
       // https://caniuse.com/#feat=link-rel-preload
 
 
       if (hasPreload) {
-        yield _this2.promisedBuildId;
-        const link = document.createElement('link');
-        link.rel = 'preload';
-        link.crossOrigin = "anonymous";
-        link.href = _this2.assetPrefix + "/_next/static/" + encodeURIComponent(_this2.buildId) + "/pages" + scriptRoute;
-        link.as = 'script';
-        document.head.appendChild(link);
+        preloadScript(url);
+        return;
+      }
+
+      if (isDependency) {
+        // loadPage will automatically handle depencies, so no need to
+        // preload them manually
         return;
       }
 
@@ -1115,17 +1114,6 @@ class PageLoader {
     })();
   }
 
-  clearCache(route) {
-    route = this.normalizeRoute(route);
-    delete this.pageCache[route];
-    delete this.loadingRoutes[route];
-    const script = document.getElementById("__NEXT_PAGE__" + route);
-
-    if (script) {
-      script.parentNode.removeChild(script);
-    }
-  }
-
 }
 
 exports.default = PageLoader;
Diff for commonsModern.js
@@ -763,6 +763,8 @@ function formatWithValidation(url, options) {
 }
 
 exports.formatWithValidation = formatWithValidation;
+exports.SUPPORTS_PERFORMANCE = typeof performance !== 'undefined';
+exports.SUPPORTS_PERFORMANCE_USER_TIMING = exports.SUPPORTS_PERFORMANCE && typeof performance.mark === 'function' && typeof performance.measure === 'function';
 
 /***/ }),
 
@@ -2677,8 +2679,13 @@ class Router {
 
   change(method, _url, _as, options) {
     return new _promise.default((resolve, reject) => {
-      // If url and as provided as an object representation,
+      // marking route changes as a navigation start entry
+      if (utils_1.SUPPORTS_PERFORMANCE_USER_TIMING) {
+        performance.mark('routeChange');
+      } // If url and as provided as an object representation,
       // we'll format them into the string version here.
+
+
       const url = typeof _url === 'object' ? utils_1.formatWithValidation(_url) : _url;
       let as = typeof _as === 'object' ? utils_1.formatWithValidation(_as) : _as; // Add the ending slash to the paths. So, we can serve the
       // "<page>/index.html" directly for the SSR page.
@@ -2702,13 +2709,21 @@ class Router {
 
       const {
         pathname,
-        query
-      } = url_1.parse(url, true); // If asked to change the current URL we should reload the current page
+        query,
+        protocol
+      } = url_1.parse(url, true);
+
+      if (!pathname || protocol) {
+        if (false) {}
+
+        return resolve(false);
+      } // If asked to change the current URL we should reload the current page
       // (not location.reload() but reload getInitialProps and other Next.js stuffs)
       // We also need to set the method = replaceState always
       // as this should not go into the history (That's how browsers work)
       // We should compare the new asPath to the current asPath, not the url
 
+
       if (!this.urlIsNew(as)) {
         method = 'replaceState';
       } // @ts-ignore pathname is always a string
@@ -2815,11 +2830,6 @@ class Router {
           asPath: as
         };
         this.getInitialProps(Component, ctx).then(props => {
-          // if data is inlined during prerender it is a string
-          if (props && typeof props.pageProps === 'string') {
-            props.pageProps = JSON.parse(props.pageProps);
-          }
-
           routeInfo.props = props;
           this.components[route] = routeInfo;
           resolve(routeInfo);
@@ -2952,11 +2962,19 @@ class Router {
 
   prefetch(url) {
     return new _promise.default((resolve, reject) => {
-      // Prefetch is not supported in development mode because it would trigger on-demand-entries
-      if (false) {}
       const {
-        pathname
-      } = url_1.parse(url); // @ts-ignore pathname is always defined
+        pathname,
+        protocol
+      } = url_1.parse(url);
+
+      if (!pathname || protocol) {
+        if (false) {}
+
+        return;
+      } // Prefetch is not supported in development mode because it would trigger on-demand-entries
+
+
+      if (false) {} // @ts-ignore pathname is always defined
 
       const route = toRoute(pathname);
       this.pageLoader.prefetch(route).then(resolve, reject);
@@ -2996,12 +3014,34 @@ class Router {
     const {
       Component: App
     } = this.components['/_app'];
-    const props = await utils_1.loadGetInitialProps(App, {
-      AppTree: this._wrapApp(App),
-      Component,
-      router: this,
-      ctx
-    });
+    let props;
+
+    if (Component.__NEXT_PRERENDER) {
+      const url = url_1.format({
+        pathname: ctx.asPath,
+        query: ctx.query
+      });
+      const res = await fetch(url, {
+        headers: {
+          'content-type': 'application/json'
+        }
+      });
+      props = {
+        pageProps: res.ok ? await res.json().catch(err => ({
+          error: err.message
+        })) : {
+          error: 'failed to load prerender',
+          statusCode: res.status
+        }
+      };
+    } else {
+      props = await utils_1.loadGetInitialProps(App, {
+        AppTree: this._wrapApp(App),
+        Component,
+        router: this,
+        ctx
+      });
+    }
 
     if (cancel === this.clc) {
       this.clc = null;
@@ -4870,8 +4910,7 @@ const singletonRouter = {
 
 }; // Create public properties and methods of the router in the singletonRouter
 
-const urlPropertyFields = ['pathname', 'route', 'query', 'asPath'];
-const propertyFields = ['components'];
+const urlPropertyFields = ['pathname', 'route', 'query', 'asPath', 'components'];
 const routerEvents = ['routeChangeStart', 'beforeHistoryChange', 'routeChangeComplete', 'routeChangeError', 'hashChangeStart', 'hashChangeComplete'];
 const coreMethodFields = ['push', 'replace', 'reload', 'back', 'prefetch', 'beforePopState']; // Events is a static property on the router, the router doesn't have to be initialized to use it
 
@@ -4881,7 +4920,7 @@ const coreMethodFields = ['push', 'replace', 'reload', 'back', 'prefetch', 'befo
   }
 
 });
-propertyFields.concat(urlPropertyFields).forEach(field => {
+urlPropertyFields.forEach(field => {
   // Here we need to use Object.defineProperty because, we need to return
   // the property assigned to the actual router
   // The value might get changed as we change routes and this is the
@@ -4977,18 +5016,6 @@ function makePublicRouterInstance(router) {
 
 
   instance.events = _router2.default.events;
-  propertyFields.forEach(field => {
-    // Here we need to use Object.defineProperty because, we need to return
-    // the property assigned to the actual router
-    // The value might get changed as we change routes and this is the
-    // proper way to access it
-    (0, _defineProperty.default)(instance, field, {
-      get() {
-        return _router[field];
-      }
-
-    });
-  });
   coreMethodFields.forEach(field => {
     instance[field] = function () {
       return _router[field](...arguments);
Diff for webpackModern.js
@@ -10,7 +10,7 @@
 /******/ 		var moduleId, chunkId, i = 0, resolves = [];
 /******/ 		for(;i < chunkIds.length; i++) {
 /******/ 			chunkId = chunkIds[i];
-/******/ 			if(installedChunks[chunkId]) {
+/******/ 			if(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {
 /******/ 				resolves.push(installedChunks[chunkId][0]);
 /******/ 			}
 /******/ 			installedChunks[chunkId] = 0;

Please sign in to comment.