Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial SSG fallback handling #10424

Merged
merged 22 commits into from Feb 7, 2020
Merged

Conversation

ijjk
Copy link
Member

@ijjk ijjk commented Feb 5, 2020

This adds initial support for rendering a loading state when either:

  • the page wasn't pre-rendered and is visited directly
  • or during a client transition while the page's data is being fetched and we didn't have cached page data available

The currently discussed way to tell if the page should render the loading state is whether the page's props are present or not, although we might iterate on this more later to make it more explicit

While serving the fallback when a page was visited directly without a cached version being available we immediately kick off a request for the data once the page is loaded and then once the page is hydrated and the data is available we render the page with the data

Ref: #9524

@ijjk ijjk added this to the 9.2.x milestone Feb 5, 2020
@ijjk
Copy link
Member Author

ijjk commented Feb 5, 2020

Stats from current PR

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 13.7s 13.8s ⚠️ +36ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +4.74 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.18 kB ⚠️ +66 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..c4ea.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..3c9e.js gzip N/A 13.7 kB N/A
Overall change 67.4 kB 67.5 kB ⚠️ +127 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.17 kB ⚠️ +47 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB 12.4 kB ⚠️ +46 B
framework.HA..dule.js gzip 39.1 kB 39.1 kB
Overall change 62 kB 62.1 kB ⚠️ +93 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Rendered Page Sizes Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
index.html gzip 1.02 kB 1.03 kB ⚠️ +14 B
link.html gzip 1.03 kB 1.04 kB ⚠️ +14 B
withRouter.html gzip 1.01 kB 1.03 kB ⚠️ +16 B
Overall change 3.06 kB 3.11 kB ⚠️ +44 B

Diffs

Diff for link.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.e0fd321a071c55a8a04d.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.85a73a2fe9d1d2db1940.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.e0fd321a071c55a8a04d.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.287186bb8b7aa738fab4.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.e94b0dc6fb879057a02a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.287186bb8b7aa738fab4.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for index.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.e0fd321a071c55a8a04d.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.85a73a2fe9d1d2db1940.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.e0fd321a071c55a8a04d.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.287186bb8b7aa738fab4.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.e94b0dc6fb879057a02a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.287186bb8b7aa738fab4.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for main-HASH.module.js
@@ -284,11 +284,22 @@ class Container extends _react.default.Component {
   componentDidMount() {
     this.scrollToHash();
 
-    if (false) {} // If page was exported and has a querystring
+    if (false) {} // call router.replace to trigger data fetching while
+    // the fallback is shown
+
+
+    if (data.isFallback) {
+      router.replace({
+        pathname: page,
+        query: (0, _extends2.default)({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))
+      }, asPath, {
+        _h: 1
+      });
+    } // If page was exported and has a querystring
     // If it's a dynamic route or has a querystring
 
 
-    if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+    if (!data.isFallback && router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
       // update query on mount for exported pages
       router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2.default)({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
         // WARNING: `_h` is an internal option for handing Next.js
@@ -411,6 +422,12 @@ var _default = async function _default(_temp) {
   };
 
   if (true) {
+    // kick off static data request now so it's in the cache
+    // when we re-render post-hydration
+    if (data.isFallback) {
+      router._getStaticData(asPath).catch(() => {});
+    }
+
     render(renderCtx);
     return emitter;
   }
Diff for main-HASH.js
@@ -379,11 +379,22 @@ function (_react$default$Compon) {
     value: function componentDidMount() {
       this.scrollToHash();
 
-      if (false) {} // If page was exported and has a querystring
+      if (false) {} // call router.replace to trigger data fetching while
+      // the fallback is shown
+
+
+      if (data.isFallback) {
+        router.replace({
+          pathname: page,
+          query: (0, _extends2["default"])({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))
+        }, asPath, {
+          _h: 1
+        });
+      } // If page was exported and has a querystring
       // If it's a dynamic route or has a querystring
 
 
-      if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+      if (!data.isFallback && router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
         // update query on mount for exported pages
         router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2["default"])({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
           // WARNING: `_h` is an internal option for handing Next.js
@@ -543,12 +554,18 @@ var _default = function _default(_temp) {
 
           if (false) {}
 
+          // kick off static data request now so it's in the cache
+          // when we re-render post-hydration
+          if (data.isFallback) {
+            router._getStaticData(asPath)["catch"](function () {});
+          }
+
           render(renderCtx);
           return _context.abrupt("return", emitter);
 
-        case 32:
+        case 33:
           if (true) {
-            _context.next = 34;
+            _context.next = 35;
             break;
           }
 
@@ -558,7 +575,7 @@ var _default = function _default(_temp) {
             renderCtx: renderCtx
           });
 
-        case 34:
+        case 35:
         case "end":
           return _context.stop();
       }
Diff for de003c3a9d30..4d.module.js
@@ -1433,10 +1433,10 @@ module.exports = __webpack_require__("aW7e");
 
 var _Object$keys = __webpack_require__("pLtp");
 
-var _Object$assign = __webpack_require__("Qetd");
-
 var _Promise = __webpack_require__("eVuF");
 
+var _Object$assign = __webpack_require__("Qetd");
+
 var _Object$defineProperty = __webpack_require__("hfKm");
 
 var __importDefault = this && this.__importDefault || function (mod) {
@@ -1554,7 +1554,7 @@ class Router {
 
     this._getStaticData = asPath => {
       var pathname = prepareRoute(url_1.parse(asPath).pathname);
-      return  true && this.sdc[pathname] ? _Promise.resolve(this.sdc[pathname]) : fetchNextData(pathname, null, data => this.sdc[pathname] = data);
+      return  true && this.sdc[pathname] ? this.sdc[pathname] : fetchNextData(pathname, null, data => this.sdc[pathname] = data);
     };
 
     this._getServerData = asPath => {
@@ -1585,7 +1585,6 @@ class Router {
       Component: App
     }; // Backwards compat for Router.router.events
     // TODO: Should be remove the following major version as it was never documented
-    // @ts-ignore backwards compatibility
 
     this.events = Router.events;
     this.pageLoader = pageLoader;
@@ -1735,8 +1734,7 @@ class Router {
 
       if (!this.urlIsNew(as)) {
         method = 'replaceState';
-      } // @ts-ignore pathname is always a string
-
+      }
 
       var route = toRoute(pathname);
       var {
@@ -1765,7 +1763,6 @@ class Router {
       }
 
       Router.events.emit('routeChangeStart', as); // If shallow is true and the route exists in the router cache we reuse the previous result
-      // @ts-ignore pathname is always a string
 
       this.getRouteInfo(route, pathname, query, as, shallow).then(routeInfo => {
         var {
@@ -1778,14 +1775,10 @@ class Router {
 
         Router.events.emit('beforeHistoryChange', as);
         this.changeState(method, url, addBasePath(as), options);
-        var hash = window.location.hash.substring(1);
-
-        if (false) { var appComp; } // @ts-ignore pathname is always defined
 
+        if (false) { var appComp; }
 
-        this.set(route, pathname, query, as, _Object$assign(_Object$assign({}, routeInfo), {
-          hash
-        }));
+        this.set(route, pathname, query, as, routeInfo);
 
         if (error) {
           Router.events.emit('routeChangeError', error, as);
@@ -1793,7 +1786,17 @@ class Router {
         }
 
         Router.events.emit('routeChangeComplete', as);
-        return resolve(true);
+
+        if (routeInfo.dataRes) {
+          return routeInfo.dataRes.then(routeInfo => {
+            this.set(route, pathname, query, as, routeInfo); // TODO: should we resolve when the fallback is rendered
+            // or when the data is returned and we render with data?
+
+            resolve(true);
+          }, reject);
+        } else {
+          return resolve(true);
+        }
       }, reject);
     });
   }
@@ -1837,16 +1840,31 @@ class Router {
 
       if (false) { var isValidElementType; }
 
-      return this._getData(() => Component.__N_SSG ? this._getStaticData(as) : Component.__N_SSP ? this._getServerData(as) : this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+      var isSSG = Component.__N_SSG;
+      var isSSP = Component.__N_SSP;
+
+      var handleData = props => {
+        routeInfo.props = props;
+        this.components[route] = routeInfo;
+        return routeInfo;
+      }; // if we have data in cache resolve with the data
+      // if not we we resolve with fallback routeInfo
+
+
+      if (isSSG || isSSP) {
+        var dataRes = isSSG ? this._getStaticData(as) : this._getServerData(as);
+        return _Promise.resolve(typeof dataRes.then !== 'function' ? handleData(dataRes) : _Object$assign(_Object$assign({}, routeInfo), {
+          props: {},
+          dataRes: this._getData(() => dataRes.then(props => handleData(props)))
+        }));
+      }
+
+      return this._getData(() => this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
       {
         pathname,
         query,
         asPath: as
-      })).then(props => {
-        routeInfo.props = props;
-        this.components[route] = routeInfo;
-        return routeInfo;
-      });
+      })).then(props => handleData(props));
     }).catch(err => {
       return new _Promise(resolve => {
         if (err.code === 'PAGE_LOAD_ERROR') {
@@ -1985,8 +2003,7 @@ class Router {
       } // Prefetch is not supported in development mode because it would trigger on-demand-entries
 
 
-      if (false) {} // @ts-ignore pathname is always defined
-
+      if (false) {}
 
       var route = toRoute(pathname);
       this.pageLoader.prefetch(route).then(resolve, reject);
Diff for de003c3a9d30..1d2db1940.js
@@ -1147,10 +1147,10 @@ var _slicedToArray = __webpack_require__("8+Nu");
 
 var _Object$keys = __webpack_require__("pLtp");
 
-var _Object$assign = __webpack_require__("Qetd");
-
 var _Promise = __webpack_require__("eVuF");
 
+var _Object$assign = __webpack_require__("Qetd");
+
 var _classCallCheck = __webpack_require__("/HRN");
 
 var _createClass = __webpack_require__("WaGi");
@@ -1278,7 +1278,7 @@ function () {
 
     this._getStaticData = function (asPath) {
       var pathname = prepareRoute(url_1.parse(asPath).pathname);
-      return  true && _this.sdc[pathname] ? _Promise.resolve(_this.sdc[pathname]) : fetchNextData(pathname, null, function (data) {
+      return  true && _this.sdc[pathname] ? _this.sdc[pathname] : fetchNextData(pathname, null, function (data) {
         return _this.sdc[pathname] = data;
       });
     };
@@ -1311,7 +1311,6 @@ function () {
       Component: App
     }; // Backwards compat for Router.router.events
     // TODO: Should be remove the following major version as it was never documented
-    // @ts-ignore backwards compatibility
 
     this.events = Router.events;
     this.pageLoader = pageLoader;
@@ -1467,8 +1466,7 @@ function () {
 
         if (!_this2.urlIsNew(as)) {
           method = 'replaceState';
-        } // @ts-ignore pathname is always a string
-
+        }
 
         var route = toRoute(pathname);
         var _options$shallow = options.shallow,
@@ -1498,7 +1496,6 @@ function () {
         }
 
         Router.events.emit('routeChangeStart', as); // If shallow is true and the route exists in the router cache we reuse the previous result
-        // @ts-ignore pathname is always a string
 
         _this2.getRouteInfo(route, pathname, query, as, shallow).then(function (routeInfo) {
           var error = routeInfo.error;
@@ -1511,14 +1508,9 @@ function () {
 
           _this2.changeState(method, url, addBasePath(as), options);
 
-          var hash = window.location.hash.substring(1);
+          if (false) { var appComp; }
 
-          if (false) { var appComp; } // @ts-ignore pathname is always defined
-
-
-          _this2.set(route, pathname, query, as, _Object$assign(_Object$assign({}, routeInfo), {
-            hash: hash
-          }));
+          _this2.set(route, pathname, query, as, routeInfo);
 
           if (error) {
             Router.events.emit('routeChangeError', error, as);
@@ -1526,7 +1518,18 @@ function () {
           }
 
           Router.events.emit('routeChangeComplete', as);
-          return resolve(true);
+
+          if (routeInfo.dataRes) {
+            return routeInfo.dataRes.then(function (routeInfo) {
+              _this2.set(route, pathname, query, as, routeInfo); // TODO: should we resolve when the fallback is rendered
+              // or when the data is returned and we render with data?
+
+
+              resolve(true);
+            }, reject);
+          } else {
+            return resolve(true);
+          }
         }, reject);
       });
     }
@@ -1574,17 +1577,38 @@ function () {
 
         if (false) { var _require, isValidElementType; }
 
+        var isSSG = Component.__N_SSG;
+        var isSSP = Component.__N_SSP;
+
+        var handleData = function handleData(props) {
+          routeInfo.props = props;
+          _this3.components[route] = routeInfo;
+          return routeInfo;
+        }; // if we have data in cache resolve with the data
+        // if not we we resolve with fallback routeInfo
+
+
+        if (isSSG || isSSP) {
+          var dataRes = isSSG ? _this3._getStaticData(as) : _this3._getServerData(as);
+          return _Promise.resolve(typeof dataRes.then !== 'function' ? handleData(dataRes) : _Object$assign(_Object$assign({}, routeInfo), {
+            props: {},
+            dataRes: _this3._getData(function () {
+              return dataRes.then(function (props) {
+                return handleData(props);
+              });
+            })
+          }));
+        }
+
         return _this3._getData(function () {
-          return Component.__N_SSG ? _this3._getStaticData(as) : Component.__N_SSP ? _this3._getServerData(as) : _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+          return _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
           {
             pathname: pathname,
             query: query,
             asPath: as
           });
         }).then(function (props) {
-          routeInfo.props = props;
-          _this3.components[route] = routeInfo;
-          return routeInfo;
+          return handleData(props);
         });
       })["catch"](function (err) {
         return new _Promise(function (resolve) {
@@ -1743,8 +1767,7 @@ function () {
         } // Prefetch is not supported in development mode because it would trigger on-demand-entries
 
 
-        if (false) {} // @ts-ignore pathname is always defined
-
+        if (false) {}
 
         var route = toRoute(pathname);
Diff for withRouter.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.e0fd321a071c55a8a04d.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.85a73a2fe9d1d2db1940.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.e0fd321a071c55a8a04d.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.287186bb8b7aa738fab4.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.e94b0dc6fb879057a02a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.287186bb8b7aa738fab4.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 14.2s 14.5s ⚠️ +271ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +4.74 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.18 kB ⚠️ +66 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..c4ea.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..3c9e.js gzip N/A 13.7 kB N/A
Overall change 67.4 kB 67.5 kB ⚠️ +127 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.17 kB ⚠️ +47 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB N/A N/A
framework.HA..dule.js gzip 39.1 kB 39.1 kB
de003c3a9d30..dule.js gzip N/A 12.4 kB N/A
Overall change 62 kB 62.1 kB ⚠️ +93 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Serverless bundles Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_error.js gzip 46.5 kB 46.6 kB ⚠️ +103 B
404.html gzip 1.43 kB 1.44 kB ⚠️ +13 B
hooks.html gzip 1.06 kB 1.07 kB ⚠️ +14 B
index.js gzip 46.5 kB 46.6 kB ⚠️ +95 B
link.js gzip 72 kB 72.3 kB ⚠️ +261 B
routerDirect.js gzip 70.3 kB 70.5 kB ⚠️ +242 B
withRouter.js gzip 70.1 kB 70.3 kB ⚠️ +248 B
Overall change 308 kB 309 kB ⚠️ +976 B

Commit: 99188d3

@ijjk
Copy link
Member Author

ijjk commented Feb 5, 2020

Stats from current PR

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 11.3s 11.3s -3ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +4.74 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.18 kB ⚠️ +66 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..c4ea.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..3c9e.js gzip N/A 13.7 kB N/A
Overall change 67.4 kB 67.5 kB ⚠️ +127 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.17 kB ⚠️ +47 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB 12.4 kB ⚠️ +46 B
framework.HA..dule.js gzip 39.1 kB 39.1 kB
Overall change 62 kB 62.1 kB ⚠️ +93 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Rendered Page Sizes Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
index.html gzip 1.02 kB 1.03 kB ⚠️ +14 B
link.html gzip 1.03 kB 1.04 kB ⚠️ +14 B
withRouter.html gzip 1.01 kB 1.03 kB ⚠️ +16 B
Overall change 3.06 kB 3.11 kB ⚠️ +44 B

Diffs

Diff for index.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.e0fd321a071c55a8a04d.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.85a73a2fe9d1d2db1940.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.e0fd321a071c55a8a04d.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.287186bb8b7aa738fab4.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.e94b0dc6fb879057a02a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.287186bb8b7aa738fab4.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for main-HASH.module.js
@@ -284,11 +284,22 @@ class Container extends _react.default.Component {
   componentDidMount() {
     this.scrollToHash();
 
-    if (false) {} // If page was exported and has a querystring
+    if (false) {} // call router.replace to trigger data fetching while
+    // the fallback is shown
+
+
+    if (data.isFallback) {
+      router.replace({
+        pathname: page,
+        query: (0, _extends2.default)({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))
+      }, asPath, {
+        _h: 1
+      });
+    } // If page was exported and has a querystring
     // If it's a dynamic route or has a querystring
 
 
-    if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+    if (!data.isFallback && router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
       // update query on mount for exported pages
       router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2.default)({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
         // WARNING: `_h` is an internal option for handing Next.js
@@ -411,6 +422,12 @@ var _default = async function _default(_temp) {
   };
 
   if (true) {
+    // kick off static data request now so it's in the cache
+    // when we re-render post-hydration
+    if (data.isFallback) {
+      router._getStaticData(asPath).catch(() => {});
+    }
+
     render(renderCtx);
     return emitter;
   }
Diff for main-HASH.js
@@ -379,11 +379,22 @@ function (_react$default$Compon) {
     value: function componentDidMount() {
       this.scrollToHash();
 
-      if (false) {} // If page was exported and has a querystring
+      if (false) {} // call router.replace to trigger data fetching while
+      // the fallback is shown
+
+
+      if (data.isFallback) {
+        router.replace({
+          pathname: page,
+          query: (0, _extends2["default"])({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))
+        }, asPath, {
+          _h: 1
+        });
+      } // If page was exported and has a querystring
       // If it's a dynamic route or has a querystring
 
 
-      if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+      if (!data.isFallback && router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
         // update query on mount for exported pages
         router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2["default"])({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
           // WARNING: `_h` is an internal option for handing Next.js
@@ -543,12 +554,18 @@ var _default = function _default(_temp) {
 
           if (false) {}
 
+          // kick off static data request now so it's in the cache
+          // when we re-render post-hydration
+          if (data.isFallback) {
+            router._getStaticData(asPath)["catch"](function () {});
+          }
+
           render(renderCtx);
           return _context.abrupt("return", emitter);
 
-        case 32:
+        case 33:
           if (true) {
-            _context.next = 34;
+            _context.next = 35;
             break;
           }
 
@@ -558,7 +575,7 @@ var _default = function _default(_temp) {
             renderCtx: renderCtx
           });
 
-        case 34:
+        case 35:
         case "end":
           return _context.stop();
       }
Diff for de003c3a9d30..4d.module.js
@@ -1433,10 +1433,10 @@ module.exports = __webpack_require__("aW7e");
 
 var _Object$keys = __webpack_require__("pLtp");
 
-var _Object$assign = __webpack_require__("Qetd");
-
 var _Promise = __webpack_require__("eVuF");
 
+var _Object$assign = __webpack_require__("Qetd");
+
 var _Object$defineProperty = __webpack_require__("hfKm");
 
 var __importDefault = this && this.__importDefault || function (mod) {
@@ -1554,7 +1554,7 @@ class Router {
 
     this._getStaticData = asPath => {
       var pathname = prepareRoute(url_1.parse(asPath).pathname);
-      return  true && this.sdc[pathname] ? _Promise.resolve(this.sdc[pathname]) : fetchNextData(pathname, null, data => this.sdc[pathname] = data);
+      return  true && this.sdc[pathname] ? this.sdc[pathname] : fetchNextData(pathname, null, data => this.sdc[pathname] = data);
     };
 
     this._getServerData = asPath => {
@@ -1585,7 +1585,6 @@ class Router {
       Component: App
     }; // Backwards compat for Router.router.events
     // TODO: Should be remove the following major version as it was never documented
-    // @ts-ignore backwards compatibility
 
     this.events = Router.events;
     this.pageLoader = pageLoader;
@@ -1735,8 +1734,7 @@ class Router {
 
       if (!this.urlIsNew(as)) {
         method = 'replaceState';
-      } // @ts-ignore pathname is always a string
-
+      }
 
       var route = toRoute(pathname);
       var {
@@ -1765,7 +1763,6 @@ class Router {
       }
 
       Router.events.emit('routeChangeStart', as); // If shallow is true and the route exists in the router cache we reuse the previous result
-      // @ts-ignore pathname is always a string
 
       this.getRouteInfo(route, pathname, query, as, shallow).then(routeInfo => {
         var {
@@ -1778,14 +1775,10 @@ class Router {
 
         Router.events.emit('beforeHistoryChange', as);
         this.changeState(method, url, addBasePath(as), options);
-        var hash = window.location.hash.substring(1);
-
-        if (false) { var appComp; } // @ts-ignore pathname is always defined
 
+        if (false) { var appComp; }
 
-        this.set(route, pathname, query, as, _Object$assign(_Object$assign({}, routeInfo), {
-          hash
-        }));
+        this.set(route, pathname, query, as, routeInfo);
 
         if (error) {
           Router.events.emit('routeChangeError', error, as);
@@ -1793,7 +1786,17 @@ class Router {
         }
 
         Router.events.emit('routeChangeComplete', as);
-        return resolve(true);
+
+        if (routeInfo.dataRes) {
+          return routeInfo.dataRes.then(routeInfo => {
+            this.set(route, pathname, query, as, routeInfo); // TODO: should we resolve when the fallback is rendered
+            // or when the data is returned and we render with data?
+
+            resolve(true);
+          }, reject);
+        } else {
+          return resolve(true);
+        }
       }, reject);
     });
   }
@@ -1837,16 +1840,31 @@ class Router {
 
       if (false) { var isValidElementType; }
 
-      return this._getData(() => Component.__N_SSG ? this._getStaticData(as) : Component.__N_SSP ? this._getServerData(as) : this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+      var isSSG = Component.__N_SSG;
+      var isSSP = Component.__N_SSP;
+
+      var handleData = props => {
+        routeInfo.props = props;
+        this.components[route] = routeInfo;
+        return routeInfo;
+      }; // if we have data in cache resolve with the data
+      // if not we we resolve with fallback routeInfo
+
+
+      if (isSSG || isSSP) {
+        var dataRes = isSSG ? this._getStaticData(as) : this._getServerData(as);
+        return _Promise.resolve(typeof dataRes.then !== 'function' ? handleData(dataRes) : _Object$assign(_Object$assign({}, routeInfo), {
+          props: {},
+          dataRes: this._getData(() => dataRes.then(props => handleData(props)))
+        }));
+      }
+
+      return this._getData(() => this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
       {
         pathname,
         query,
         asPath: as
-      })).then(props => {
-        routeInfo.props = props;
-        this.components[route] = routeInfo;
-        return routeInfo;
-      });
+      })).then(props => handleData(props));
     }).catch(err => {
       return new _Promise(resolve => {
         if (err.code === 'PAGE_LOAD_ERROR') {
@@ -1985,8 +2003,7 @@ class Router {
       } // Prefetch is not supported in development mode because it would trigger on-demand-entries
 
 
-      if (false) {} // @ts-ignore pathname is always defined
-
+      if (false) {}
 
       var route = toRoute(pathname);
       this.pageLoader.prefetch(route).then(resolve, reject);
Diff for de003c3a9d30..1d2db1940.js
@@ -1147,10 +1147,10 @@ var _slicedToArray = __webpack_require__("8+Nu");
 
 var _Object$keys = __webpack_require__("pLtp");
 
-var _Object$assign = __webpack_require__("Qetd");
-
 var _Promise = __webpack_require__("eVuF");
 
+var _Object$assign = __webpack_require__("Qetd");
+
 var _classCallCheck = __webpack_require__("/HRN");
 
 var _createClass = __webpack_require__("WaGi");
@@ -1278,7 +1278,7 @@ function () {
 
     this._getStaticData = function (asPath) {
       var pathname = prepareRoute(url_1.parse(asPath).pathname);
-      return  true && _this.sdc[pathname] ? _Promise.resolve(_this.sdc[pathname]) : fetchNextData(pathname, null, function (data) {
+      return  true && _this.sdc[pathname] ? _this.sdc[pathname] : fetchNextData(pathname, null, function (data) {
         return _this.sdc[pathname] = data;
       });
     };
@@ -1311,7 +1311,6 @@ function () {
       Component: App
     }; // Backwards compat for Router.router.events
     // TODO: Should be remove the following major version as it was never documented
-    // @ts-ignore backwards compatibility
 
     this.events = Router.events;
     this.pageLoader = pageLoader;
@@ -1467,8 +1466,7 @@ function () {
 
         if (!_this2.urlIsNew(as)) {
           method = 'replaceState';
-        } // @ts-ignore pathname is always a string
-
+        }
 
         var route = toRoute(pathname);
         var _options$shallow = options.shallow,
@@ -1498,7 +1496,6 @@ function () {
         }
 
         Router.events.emit('routeChangeStart', as); // If shallow is true and the route exists in the router cache we reuse the previous result
-        // @ts-ignore pathname is always a string
 
         _this2.getRouteInfo(route, pathname, query, as, shallow).then(function (routeInfo) {
           var error = routeInfo.error;
@@ -1511,14 +1508,9 @@ function () {
 
           _this2.changeState(method, url, addBasePath(as), options);
 
-          var hash = window.location.hash.substring(1);
+          if (false) { var appComp; }
 
-          if (false) { var appComp; } // @ts-ignore pathname is always defined
-
-
-          _this2.set(route, pathname, query, as, _Object$assign(_Object$assign({}, routeInfo), {
-            hash: hash
-          }));
+          _this2.set(route, pathname, query, as, routeInfo);
 
           if (error) {
             Router.events.emit('routeChangeError', error, as);
@@ -1526,7 +1518,18 @@ function () {
           }
 
           Router.events.emit('routeChangeComplete', as);
-          return resolve(true);
+
+          if (routeInfo.dataRes) {
+            return routeInfo.dataRes.then(function (routeInfo) {
+              _this2.set(route, pathname, query, as, routeInfo); // TODO: should we resolve when the fallback is rendered
+              // or when the data is returned and we render with data?
+
+
+              resolve(true);
+            }, reject);
+          } else {
+            return resolve(true);
+          }
         }, reject);
       });
     }
@@ -1574,17 +1577,38 @@ function () {
 
         if (false) { var _require, isValidElementType; }
 
+        var isSSG = Component.__N_SSG;
+        var isSSP = Component.__N_SSP;
+
+        var handleData = function handleData(props) {
+          routeInfo.props = props;
+          _this3.components[route] = routeInfo;
+          return routeInfo;
+        }; // if we have data in cache resolve with the data
+        // if not we we resolve with fallback routeInfo
+
+
+        if (isSSG || isSSP) {
+          var dataRes = isSSG ? _this3._getStaticData(as) : _this3._getServerData(as);
+          return _Promise.resolve(typeof dataRes.then !== 'function' ? handleData(dataRes) : _Object$assign(_Object$assign({}, routeInfo), {
+            props: {},
+            dataRes: _this3._getData(function () {
+              return dataRes.then(function (props) {
+                return handleData(props);
+              });
+            })
+          }));
+        }
+
         return _this3._getData(function () {
-          return Component.__N_SSG ? _this3._getStaticData(as) : Component.__N_SSP ? _this3._getServerData(as) : _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+          return _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
           {
             pathname: pathname,
             query: query,
             asPath: as
           });
         }).then(function (props) {
-          routeInfo.props = props;
-          _this3.components[route] = routeInfo;
-          return routeInfo;
+          return handleData(props);
         });
       })["catch"](function (err) {
         return new _Promise(function (resolve) {
@@ -1743,8 +1767,7 @@ function () {
         } // Prefetch is not supported in development mode because it would trigger on-demand-entries
 
 
-        if (false) {} // @ts-ignore pathname is always defined
-
+        if (false) {}
 
         var route = toRoute(pathname);
Diff for link.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.e0fd321a071c55a8a04d.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.85a73a2fe9d1d2db1940.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.e0fd321a071c55a8a04d.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.287186bb8b7aa738fab4.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.e94b0dc6fb879057a02a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.287186bb8b7aa738fab4.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for withRouter.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.e0fd321a071c55a8a04d.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.85a73a2fe9d1d2db1940.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.e0fd321a071c55a8a04d.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.287186bb8b7aa738fab4.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.e94b0dc6fb879057a02a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.287186bb8b7aa738fab4.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 11.6s 11.8s ⚠️ +211ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +4.74 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.18 kB ⚠️ +66 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..c4ea.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..3c9e.js gzip N/A 13.7 kB N/A
Overall change 67.4 kB 67.5 kB ⚠️ +127 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.17 kB ⚠️ +47 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB N/A N/A
framework.HA..dule.js gzip 39.1 kB 39.1 kB
de003c3a9d30..dule.js gzip N/A 12.4 kB N/A
Overall change 62 kB 62.1 kB ⚠️ +93 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Serverless bundles Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_error.js gzip 46.5 kB 46.6 kB ⚠️ +103 B
404.html gzip 1.43 kB 1.44 kB ⚠️ +13 B
hooks.html gzip 1.06 kB 1.07 kB ⚠️ +14 B
index.js gzip 46.5 kB 46.6 kB ⚠️ +95 B
link.js gzip 72 kB 72.3 kB ⚠️ +261 B
routerDirect.js gzip 70.3 kB 70.5 kB ⚠️ +242 B
withRouter.js gzip 70.1 kB 70.3 kB ⚠️ +248 B
Overall change 308 kB 309 kB ⚠️ +976 B

Commit: 9a8e710

@ijjk
Copy link
Member Author

ijjk commented Feb 5, 2020

Stats from current PR

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 13.3s 13.2s -108ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +5.41 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.18 kB ⚠️ +66 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..b50f.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..3c9e.js gzip N/A 13.7 kB N/A
Overall change 67.3 kB 67.5 kB ⚠️ +143 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.17 kB ⚠️ +47 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB 12.4 kB ⚠️ +65 B
framework.HA..dule.js gzip 39.1 kB 39.1 kB
Overall change 61.9 kB 62.1 kB ⚠️ +112 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Rendered Page Sizes Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
index.html gzip 1.02 kB 1.03 kB ⚠️ +12 B
link.html gzip 1.03 kB 1.04 kB ⚠️ +10 B
withRouter.html gzip 1.02 kB 1.03 kB ⚠️ +13 B
Overall change 3.07 kB 3.11 kB ⚠️ +35 B

Diffs

Diff for index.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.287186bb8b7aa738fab4.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.e94b0dc6fb879057a02a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.287186bb8b7aa738fab4.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for main-HASH.module.js
@@ -284,11 +284,22 @@ class Container extends _react.default.Component {
   componentDidMount() {
     this.scrollToHash();
 
-    if (false) {} // If page was exported and has a querystring
+    if (false) {} // call router.replace to trigger data fetching while
+    // the fallback is shown
+
+
+    if (data.isFallback) {
+      router.replace({
+        pathname: page,
+        query: (0, _extends2.default)({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))
+      }, asPath, {
+        _h: 1
+      });
+    } // If page was exported and has a querystring
     // If it's a dynamic route or has a querystring
 
 
-    if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+    if (!data.isFallback && router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
       // update query on mount for exported pages
       router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2.default)({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
         // WARNING: `_h` is an internal option for handing Next.js
@@ -411,6 +422,12 @@ var _default = async function _default(_temp) {
   };
 
   if (true) {
+    // kick off static data request now so it's in the cache
+    // when we re-render post-hydration
+    if (data.isFallback) {
+      router._getStaticData(asPath).catch(() => {});
+    }
+
     render(renderCtx);
     return emitter;
   }
Diff for main-HASH.js
@@ -379,11 +379,22 @@ function (_react$default$Compon) {
     value: function componentDidMount() {
       this.scrollToHash();
 
-      if (false) {} // If page was exported and has a querystring
+      if (false) {} // call router.replace to trigger data fetching while
+      // the fallback is shown
+
+
+      if (data.isFallback) {
+        router.replace({
+          pathname: page,
+          query: (0, _extends2["default"])({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))
+        }, asPath, {
+          _h: 1
+        });
+      } // If page was exported and has a querystring
       // If it's a dynamic route or has a querystring
 
 
-      if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+      if (!data.isFallback && router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
         // update query on mount for exported pages
         router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2["default"])({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
           // WARNING: `_h` is an internal option for handing Next.js
@@ -543,12 +554,18 @@ var _default = function _default(_temp) {
 
           if (false) {}
 
+          // kick off static data request now so it's in the cache
+          // when we re-render post-hydration
+          if (data.isFallback) {
+            router._getStaticData(asPath)["catch"](function () {});
+          }
+
           render(renderCtx);
           return _context.abrupt("return", emitter);
 
-        case 32:
+        case 33:
           if (true) {
-            _context.next = 34;
+            _context.next = 35;
             break;
           }
 
@@ -558,7 +575,7 @@ var _default = function _default(_temp) {
             renderCtx: renderCtx
           });
 
-        case 34:
+        case 35:
         case "end":
           return _context.stop();
       }
Diff for de003c3a9d30..29.module.js
@@ -1433,10 +1433,10 @@ module.exports = __webpack_require__("aW7e");
 
 var _Object$keys = __webpack_require__("pLtp");
 
-var _Object$assign = __webpack_require__("Qetd");
-
 var _Promise = __webpack_require__("eVuF");
 
+var _Object$assign = __webpack_require__("Qetd");
+
 var _Object$defineProperty = __webpack_require__("hfKm");
 
 var __importDefault = this && this.__importDefault || function (mod) {
@@ -1554,7 +1554,7 @@ class Router {
 
     this._getStaticData = asPath => {
       var pathname = prepareRoute(url_1.parse(asPath).pathname);
-      return  true && this.sdc[pathname] ? _Promise.resolve(this.sdc[pathname]) : fetchNextData(pathname, null, data => this.sdc[pathname] = data);
+      return  true && this.sdc[pathname] ? this.sdc[pathname] : fetchNextData(pathname, null, data => this.sdc[pathname] = data);
     };
 
     this._getServerData = asPath => {
@@ -1786,7 +1786,17 @@ class Router {
         }
 
         Router.events.emit('routeChangeComplete', as);
-        return resolve(true);
+
+        if (routeInfo.dataRes) {
+          return routeInfo.dataRes.then(routeInfo => {
+            this.set(route, pathname, query, as, routeInfo); // TODO: should we resolve when the fallback is rendered
+            // or when the data is returned and we render with data?
+
+            resolve(true);
+          }, reject);
+        } else {
+          return resolve(true);
+        }
       }, reject);
     });
   }
@@ -1830,16 +1840,31 @@ class Router {
 
       if (false) { var isValidElementType; }
 
-      return this._getData(() => Component.__N_SSG ? this._getStaticData(as) : Component.__N_SSP ? this._getServerData(as) : this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+      var isSSG = Component.__N_SSG;
+      var isSSP = Component.__N_SSP;
+
+      var handleData = props => {
+        routeInfo.props = props;
+        this.components[route] = routeInfo;
+        return routeInfo;
+      }; // if we have data in cache resolve with the data
+      // if not we we resolve with fallback routeInfo
+
+
+      if (isSSG || isSSP) {
+        var dataRes = isSSG ? this._getStaticData(as) : this._getServerData(as);
+        return _Promise.resolve(typeof dataRes.then !== 'function' ? handleData(dataRes) : _Object$assign(_Object$assign({}, routeInfo), {
+          props: {},
+          dataRes: this._getData(() => dataRes.then(props => handleData(props)))
+        }));
+      }
+
+      return this._getData(() => this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
       {
         pathname,
         query,
         asPath: as
-      })).then(props => {
-        routeInfo.props = props;
-        this.components[route] = routeInfo;
-        return routeInfo;
-      });
+      })).then(props => handleData(props));
     }).catch(err => {
       return new _Promise(resolve => {
         if (err.code === 'PAGE_LOAD_ERROR') {
Diff for de003c3a9d30..686f3d49e.js
@@ -1147,10 +1147,10 @@ var _slicedToArray = __webpack_require__("8+Nu");
 
 var _Object$keys = __webpack_require__("pLtp");
 
-var _Object$assign = __webpack_require__("Qetd");
-
 var _Promise = __webpack_require__("eVuF");
 
+var _Object$assign = __webpack_require__("Qetd");
+
 var _classCallCheck = __webpack_require__("/HRN");
 
 var _createClass = __webpack_require__("WaGi");
@@ -1278,7 +1278,7 @@ function () {
 
     this._getStaticData = function (asPath) {
       var pathname = prepareRoute(url_1.parse(asPath).pathname);
-      return  true && _this.sdc[pathname] ? _Promise.resolve(_this.sdc[pathname]) : fetchNextData(pathname, null, function (data) {
+      return  true && _this.sdc[pathname] ? _this.sdc[pathname] : fetchNextData(pathname, null, function (data) {
         return _this.sdc[pathname] = data;
       });
     };
@@ -1518,7 +1518,18 @@ function () {
           }
 
           Router.events.emit('routeChangeComplete', as);
-          return resolve(true);
+
+          if (routeInfo.dataRes) {
+            return routeInfo.dataRes.then(function (routeInfo) {
+              _this2.set(route, pathname, query, as, routeInfo); // TODO: should we resolve when the fallback is rendered
+              // or when the data is returned and we render with data?
+
+
+              resolve(true);
+            }, reject);
+          } else {
+            return resolve(true);
+          }
         }, reject);
       });
     }
@@ -1566,17 +1577,38 @@ function () {
 
         if (false) { var _require, isValidElementType; }
 
+        var isSSG = Component.__N_SSG;
+        var isSSP = Component.__N_SSP;
+
+        var handleData = function handleData(props) {
+          routeInfo.props = props;
+          _this3.components[route] = routeInfo;
+          return routeInfo;
+        }; // if we have data in cache resolve with the data
+        // if not we we resolve with fallback routeInfo
+
+
+        if (isSSG || isSSP) {
+          var dataRes = isSSG ? _this3._getStaticData(as) : _this3._getServerData(as);
+          return _Promise.resolve(typeof dataRes.then !== 'function' ? handleData(dataRes) : _Object$assign(_Object$assign({}, routeInfo), {
+            props: {},
+            dataRes: _this3._getData(function () {
+              return dataRes.then(function (props) {
+                return handleData(props);
+              });
+            })
+          }));
+        }
+
         return _this3._getData(function () {
-          return Component.__N_SSG ? _this3._getStaticData(as) : Component.__N_SSP ? _this3._getServerData(as) : _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+          return _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
           {
             pathname: pathname,
             query: query,
             asPath: as
           });
         }).then(function (props) {
-          routeInfo.props = props;
-          _this3.components[route] = routeInfo;
-          return routeInfo;
+          return handleData(props);
         });
       })["catch"](function (err) {
         return new _Promise(function (resolve) {
Diff for link.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.287186bb8b7aa738fab4.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.e94b0dc6fb879057a02a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.287186bb8b7aa738fab4.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for withRouter.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.287186bb8b7aa738fab4.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.e94b0dc6fb879057a02a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.287186bb8b7aa738fab4.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 13.5s 13.8s ⚠️ +321ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +5.41 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.18 kB ⚠️ +66 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..b50f.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..3c9e.js gzip N/A 13.7 kB N/A
Overall change 67.3 kB 67.5 kB ⚠️ +143 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.17 kB ⚠️ +47 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB N/A N/A
framework.HA..dule.js gzip 39.1 kB 39.1 kB
de003c3a9d30..dule.js gzip N/A 12.4 kB N/A
Overall change 61.9 kB 62.1 kB ⚠️ +112 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Serverless bundles Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_error.js gzip 46.5 kB 46.6 kB ⚠️ +100 B
404.html gzip 1.43 kB 1.44 kB ⚠️ +11 B
hooks.html gzip 1.07 kB 1.07 kB ⚠️ +9 B
index.js gzip 46.5 kB 46.6 kB ⚠️ +92 B
link.js gzip 72 kB 72.3 kB ⚠️ +316 B
routerDirect.js gzip 70.2 kB 70.5 kB ⚠️ +298 B
withRouter.js gzip 70 kB 70.3 kB ⚠️ +299 B
Overall change 308 kB 309 kB ⚠️ +1.13 kB

Commit: 0e0d4f9

@ijjk
Copy link
Member Author

ijjk commented Feb 5, 2020

Stats from current PR

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 11.7s 12s ⚠️ +301ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +6.8 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.18 kB ⚠️ +66 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..b50f.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..79d1.js gzip N/A 13.7 kB N/A
Overall change 67.3 kB 67.5 kB ⚠️ +192 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.17 kB ⚠️ +47 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB 12.5 kB ⚠️ +119 B
framework.HA..dule.js gzip 39.1 kB 39.1 kB
Overall change 61.9 kB 62.1 kB ⚠️ +166 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Rendered Page Sizes Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
index.html gzip 1.02 kB 1.03 kB ⚠️ +12 B
link.html gzip 1.03 kB 1.04 kB ⚠️ +10 B
withRouter.html gzip 1.02 kB 1.03 kB ⚠️ +13 B
Overall change 3.07 kB 3.11 kB ⚠️ +35 B

Diffs

Diff for link.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.274b54332303ac77f61a.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c66c3cb3d27c8e68369.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.274b54332303ac77f61a.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for index.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.274b54332303ac77f61a.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c66c3cb3d27c8e68369.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.274b54332303ac77f61a.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for main-HASH.module.js
@@ -284,11 +284,22 @@ class Container extends _react.default.Component {
   componentDidMount() {
     this.scrollToHash();
 
-    if (false) {} // If page was exported and has a querystring
+    if (false) {} // call router.replace to trigger data fetching while
+    // the fallback is shown
+
+
+    if (data.isFallback) {
+      router.replace({
+        pathname: page,
+        query: (0, _extends2.default)({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))
+      }, asPath, {
+        _h: 1
+      });
+    } // If page was exported and has a querystring
     // If it's a dynamic route or has a querystring
 
 
-    if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+    if (!data.isFallback && router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
       // update query on mount for exported pages
       router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2.default)({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
         // WARNING: `_h` is an internal option for handing Next.js
@@ -411,6 +422,12 @@ var _default = async function _default(_temp) {
   };
 
   if (true) {
+    // kick off static data request now so it's in the cache
+    // when we re-render post-hydration
+    if (data.isFallback) {
+      router._getStaticData(asPath).catch(() => {});
+    }
+
     render(renderCtx);
     return emitter;
   }
Diff for main-HASH.js
@@ -379,11 +379,22 @@ function (_react$default$Compon) {
     value: function componentDidMount() {
       this.scrollToHash();
 
-      if (false) {} // If page was exported and has a querystring
+      if (false) {} // call router.replace to trigger data fetching while
+      // the fallback is shown
+
+
+      if (data.isFallback) {
+        router.replace({
+          pathname: page,
+          query: (0, _extends2["default"])({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))
+        }, asPath, {
+          _h: 1
+        });
+      } // If page was exported and has a querystring
       // If it's a dynamic route or has a querystring
 
 
-      if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+      if (!data.isFallback && router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
         // update query on mount for exported pages
         router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2["default"])({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
           // WARNING: `_h` is an internal option for handing Next.js
@@ -543,12 +554,18 @@ var _default = function _default(_temp) {
 
           if (false) {}
 
+          // kick off static data request now so it's in the cache
+          // when we re-render post-hydration
+          if (data.isFallback) {
+            router._getStaticData(asPath)["catch"](function () {});
+          }
+
           render(renderCtx);
           return _context.abrupt("return", emitter);
 
-        case 32:
+        case 33:
           if (true) {
-            _context.next = 34;
+            _context.next = 35;
             break;
           }
 
@@ -558,7 +575,7 @@ var _default = function _default(_temp) {
             renderCtx: renderCtx
           });
 
-        case 34:
+        case 35:
         case "end":
           return _context.stop();
       }
Diff for de003c3a9d30..29.module.js
@@ -1433,10 +1433,10 @@ module.exports = __webpack_require__("aW7e");
 
 var _Object$keys = __webpack_require__("pLtp");
 
-var _Object$assign = __webpack_require__("Qetd");
-
 var _Promise = __webpack_require__("eVuF");
 
+var _Object$assign = __webpack_require__("Qetd");
+
 var _Object$defineProperty = __webpack_require__("hfKm");
 
 var __importDefault = this && this.__importDefault || function (mod) {
@@ -1554,7 +1554,7 @@ class Router {
 
     this._getStaticData = asPath => {
       var pathname = prepareRoute(url_1.parse(asPath).pathname);
-      return  true && this.sdc[pathname] ? _Promise.resolve(this.sdc[pathname]) : fetchNextData(pathname, null, data => this.sdc[pathname] = data);
+      return  true && this.sdc[pathname] ? this.sdc[pathname] : fetchNextData(pathname, null, data => this.sdc[pathname] = data);
     };
 
     this._getServerData = asPath => {
@@ -1778,15 +1778,39 @@ class Router {
 
         if (false) { var appComp; }
 
-        this.set(route, pathname, query, as, routeInfo);
+        var doRouteChange = (routeInfo, emit) => {
+          this.set(route, pathname, query, as, routeInfo);
 
-        if (error) {
-          Router.events.emit('routeChangeError', error, as);
-          throw error;
-        }
+          if (emit) {
+            if (error) {
+              Router.events.emit('routeChangeError', error, as);
+              throw error;
+            }
 
-        Router.events.emit('routeChangeComplete', as);
-        return resolve(true);
+            Router.events.emit('routeChangeComplete', as);
+            resolve(true);
+          }
+        };
+
+        if (routeInfo.dataRes) {
+          var dataRes = routeInfo.dataRes; // race loading state timeout with data response
+          // if loading state wins we leave it for 50 ms even if data
+          // is 1ms after loading state timeout
+
+          _Promise.race([new _Promise(resolve => setTimeout(() => resolve(false), 110)), dataRes]).then(data => {
+            if (!data) {
+              // data didn't win the race, show fallback
+              doRouteChange(routeInfo, false);
+            }
+
+            return dataRes;
+          }).then(finalData => {
+            // render with the data and complete route change
+            doRouteChange(finalData, true);
+          }, reject);
+        } else {
+          doRouteChange(routeInfo, true);
+        }
       }, reject);
     });
   }
@@ -1830,16 +1854,31 @@ class Router {
 
       if (false) { var isValidElementType; }
 
-      return this._getData(() => Component.__N_SSG ? this._getStaticData(as) : Component.__N_SSP ? this._getServerData(as) : this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+      var isSSG = Component.__N_SSG;
+      var isSSP = Component.__N_SSP;
+
+      var handleData = props => {
+        routeInfo.props = props;
+        this.components[route] = routeInfo;
+        return routeInfo;
+      }; // if we have data in cache resolve with the data
+      // if not we we resolve with fallback routeInfo
+
+
+      if (isSSG || isSSP) {
+        var dataRes = isSSG ? this._getStaticData(as) : this._getServerData(as);
+        return _Promise.resolve(typeof dataRes.then !== 'function' ? handleData(dataRes) : _Object$assign(_Object$assign({}, routeInfo), {
+          props: {},
+          dataRes: this._getData(() => dataRes.then(props => handleData(props)))
+        }));
+      }
+
+      return this._getData(() => this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
       {
         pathname,
         query,
         asPath: as
-      })).then(props => {
-        routeInfo.props = props;
-        this.components[route] = routeInfo;
-        return routeInfo;
-      });
+      })).then(props => handleData(props));
     }).catch(err => {
       return new _Promise(resolve => {
         if (err.code === 'PAGE_LOAD_ERROR') {
Diff for de003c3a9d30..686f3d49e.js
@@ -1147,10 +1147,10 @@ var _slicedToArray = __webpack_require__("8+Nu");
 
 var _Object$keys = __webpack_require__("pLtp");
 
-var _Object$assign = __webpack_require__("Qetd");
-
 var _Promise = __webpack_require__("eVuF");
 
+var _Object$assign = __webpack_require__("Qetd");
+
 var _classCallCheck = __webpack_require__("/HRN");
 
 var _createClass = __webpack_require__("WaGi");
@@ -1278,7 +1278,7 @@ function () {
 
     this._getStaticData = function (asPath) {
       var pathname = prepareRoute(url_1.parse(asPath).pathname);
-      return  true && _this.sdc[pathname] ? _Promise.resolve(_this.sdc[pathname]) : fetchNextData(pathname, null, function (data) {
+      return  true && _this.sdc[pathname] ? _this.sdc[pathname] : fetchNextData(pathname, null, function (data) {
         return _this.sdc[pathname] = data;
       });
     };
@@ -1510,15 +1510,43 @@ function () {
 
           if (false) { var appComp; }
 
-          _this2.set(route, pathname, query, as, routeInfo);
+          var doRouteChange = function doRouteChange(routeInfo, emit) {
+            _this2.set(route, pathname, query, as, routeInfo);
 
-          if (error) {
-            Router.events.emit('routeChangeError', error, as);
-            throw error;
-          }
+            if (emit) {
+              if (error) {
+                Router.events.emit('routeChangeError', error, as);
+                throw error;
+              }
 
-          Router.events.emit('routeChangeComplete', as);
-          return resolve(true);
+              Router.events.emit('routeChangeComplete', as);
+              resolve(true);
+            }
+          };
+
+          if (routeInfo.dataRes) {
+            var dataRes = routeInfo.dataRes; // race loading state timeout with data response
+            // if loading state wins we leave it for 50 ms even if data
+            // is 1ms after loading state timeout
+
+            _Promise.race([new _Promise(function (resolve) {
+              return setTimeout(function () {
+                return resolve(false);
+              }, 110);
+            }), dataRes]).then(function (data) {
+              if (!data) {
+                // data didn't win the race, show fallback
+                doRouteChange(routeInfo, false);
+              }
+
+              return dataRes;
+            }).then(function (finalData) {
+              // render with the data and complete route change
+              doRouteChange(finalData, true);
+            }, reject);
+          } else {
+            doRouteChange(routeInfo, true);
+          }
         }, reject);
       });
     }
@@ -1566,17 +1594,38 @@ function () {
 
         if (false) { var _require, isValidElementType; }
 
+        var isSSG = Component.__N_SSG;
+        var isSSP = Component.__N_SSP;
+
+        var handleData = function handleData(props) {
+          routeInfo.props = props;
+          _this3.components[route] = routeInfo;
+          return routeInfo;
+        }; // if we have data in cache resolve with the data
+        // if not we we resolve with fallback routeInfo
+
+
+        if (isSSG || isSSP) {
+          var dataRes = isSSG ? _this3._getStaticData(as) : _this3._getServerData(as);
+          return _Promise.resolve(typeof dataRes.then !== 'function' ? handleData(dataRes) : _Object$assign(_Object$assign({}, routeInfo), {
+            props: {},
+            dataRes: _this3._getData(function () {
+              return dataRes.then(function (props) {
+                return handleData(props);
+              });
+            })
+          }));
+        }
+
         return _this3._getData(function () {
-          return Component.__N_SSG ? _this3._getStaticData(as) : Component.__N_SSP ? _this3._getServerData(as) : _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+          return _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
           {
             pathname: pathname,
             query: query,
             asPath: as
           });
         }).then(function (props) {
-          routeInfo.props = props;
-          _this3.components[route] = routeInfo;
-          return routeInfo;
+          return handleData(props);
         });
       })["catch"](function (err) {
         return new _Promise(function (resolve) {
Diff for withRouter.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.274b54332303ac77f61a.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c66c3cb3d27c8e68369.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.274b54332303ac77f61a.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 12.1s 12.4s ⚠️ +318ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +6.8 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.18 kB ⚠️ +66 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..b50f.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..79d1.js gzip N/A 13.7 kB N/A
Overall change 67.3 kB 67.5 kB ⚠️ +192 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.17 kB ⚠️ +47 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB N/A N/A
framework.HA..dule.js gzip 39.1 kB 39.1 kB
de003c3a9d30..dule.js gzip N/A 12.5 kB N/A
Overall change 61.9 kB 62.1 kB ⚠️ +166 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Serverless bundles Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_error.js gzip 46.5 kB 46.6 kB ⚠️ +101 B
404.html gzip 1.43 kB 1.44 kB ⚠️ +10 B
hooks.html gzip 1.07 kB 1.07 kB ⚠️ +9 B
index.js gzip 46.5 kB 46.6 kB ⚠️ +92 B
link.js gzip 72 kB 72.5 kB ⚠️ +491 B
routerDirect.js gzip 70.2 kB 70.7 kB ⚠️ +475 B
withRouter.js gzip 70 kB 70.5 kB ⚠️ +472 B
Overall change 308 kB 309 kB ⚠️ +1.65 kB

Commit: 4dc3f7f

@ijjk
Copy link
Member Author

ijjk commented Feb 5, 2020

Stats from current PR

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 11.2s 11.1s -135ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +6.8 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.18 kB ⚠️ +66 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..b50f.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..79d1.js gzip N/A 13.7 kB N/A
Overall change 67.3 kB 67.5 kB ⚠️ +192 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.17 kB ⚠️ +47 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB 12.5 kB ⚠️ +119 B
framework.HA..dule.js gzip 39.1 kB 39.1 kB
Overall change 61.9 kB 62.1 kB ⚠️ +166 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Rendered Page Sizes Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
index.html gzip 1.02 kB 1.03 kB ⚠️ +12 B
link.html gzip 1.03 kB 1.04 kB ⚠️ +10 B
withRouter.html gzip 1.02 kB 1.03 kB ⚠️ +13 B
Overall change 3.07 kB 3.11 kB ⚠️ +35 B

Diffs

Diff for link.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.274b54332303ac77f61a.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c66c3cb3d27c8e68369.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.274b54332303ac77f61a.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for main-HASH.module.js
@@ -284,11 +284,22 @@ class Container extends _react.default.Component {
   componentDidMount() {
     this.scrollToHash();
 
-    if (false) {} // If page was exported and has a querystring
+    if (false) {} // call router.replace to trigger data fetching while
+    // the fallback is shown
+
+
+    if (data.isFallback) {
+      router.replace({
+        pathname: page,
+        query: (0, _extends2.default)({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))
+      }, asPath, {
+        _h: 1
+      });
+    } // If page was exported and has a querystring
     // If it's a dynamic route or has a querystring
 
 
-    if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+    if (!data.isFallback && router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
       // update query on mount for exported pages
       router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2.default)({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
         // WARNING: `_h` is an internal option for handing Next.js
@@ -411,6 +422,12 @@ var _default = async function _default(_temp) {
   };
 
   if (true) {
+    // kick off static data request now so it's in the cache
+    // when we re-render post-hydration
+    if (data.isFallback) {
+      router._getStaticData(asPath).catch(() => {});
+    }
+
     render(renderCtx);
     return emitter;
   }
Diff for main-HASH.js
@@ -379,11 +379,22 @@ function (_react$default$Compon) {
     value: function componentDidMount() {
       this.scrollToHash();
 
-      if (false) {} // If page was exported and has a querystring
+      if (false) {} // call router.replace to trigger data fetching while
+      // the fallback is shown
+
+
+      if (data.isFallback) {
+        router.replace({
+          pathname: page,
+          query: (0, _extends2["default"])({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))
+        }, asPath, {
+          _h: 1
+        });
+      } // If page was exported and has a querystring
       // If it's a dynamic route or has a querystring
 
 
-      if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+      if (!data.isFallback && router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
         // update query on mount for exported pages
         router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2["default"])({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
           // WARNING: `_h` is an internal option for handing Next.js
@@ -543,12 +554,18 @@ var _default = function _default(_temp) {
 
           if (false) {}
 
+          // kick off static data request now so it's in the cache
+          // when we re-render post-hydration
+          if (data.isFallback) {
+            router._getStaticData(asPath)["catch"](function () {});
+          }
+
           render(renderCtx);
           return _context.abrupt("return", emitter);
 
-        case 32:
+        case 33:
           if (true) {
-            _context.next = 34;
+            _context.next = 35;
             break;
           }
 
@@ -558,7 +575,7 @@ var _default = function _default(_temp) {
             renderCtx: renderCtx
           });
 
-        case 34:
+        case 35:
         case "end":
           return _context.stop();
       }
Diff for de003c3a9d30..29.module.js
@@ -1433,10 +1433,10 @@ module.exports = __webpack_require__("aW7e");
 
 var _Object$keys = __webpack_require__("pLtp");
 
-var _Object$assign = __webpack_require__("Qetd");
-
 var _Promise = __webpack_require__("eVuF");
 
+var _Object$assign = __webpack_require__("Qetd");
+
 var _Object$defineProperty = __webpack_require__("hfKm");
 
 var __importDefault = this && this.__importDefault || function (mod) {
@@ -1554,7 +1554,7 @@ class Router {
 
     this._getStaticData = asPath => {
       var pathname = prepareRoute(url_1.parse(asPath).pathname);
-      return  true && this.sdc[pathname] ? _Promise.resolve(this.sdc[pathname]) : fetchNextData(pathname, null, data => this.sdc[pathname] = data);
+      return  true && this.sdc[pathname] ? this.sdc[pathname] : fetchNextData(pathname, null, data => this.sdc[pathname] = data);
     };
 
     this._getServerData = asPath => {
@@ -1778,15 +1778,39 @@ class Router {
 
         if (false) { var appComp; }
 
-        this.set(route, pathname, query, as, routeInfo);
+        var doRouteChange = (routeInfo, emit) => {
+          this.set(route, pathname, query, as, routeInfo);
 
-        if (error) {
-          Router.events.emit('routeChangeError', error, as);
-          throw error;
-        }
+          if (emit) {
+            if (error) {
+              Router.events.emit('routeChangeError', error, as);
+              throw error;
+            }
 
-        Router.events.emit('routeChangeComplete', as);
-        return resolve(true);
+            Router.events.emit('routeChangeComplete', as);
+            resolve(true);
+          }
+        };
+
+        if (routeInfo.dataRes) {
+          var dataRes = routeInfo.dataRes; // race loading state timeout with data response
+          // if loading state wins we leave it for 50 ms even if data
+          // is 1ms after loading state timeout
+
+          _Promise.race([new _Promise(resolve => setTimeout(() => resolve(false), 110)), dataRes]).then(data => {
+            if (!data) {
+              // data didn't win the race, show fallback
+              doRouteChange(routeInfo, false);
+            }
+
+            return dataRes;
+          }).then(finalData => {
+            // render with the data and complete route change
+            doRouteChange(finalData, true);
+          }, reject);
+        } else {
+          doRouteChange(routeInfo, true);
+        }
       }, reject);
     });
   }
@@ -1830,16 +1854,31 @@ class Router {
 
       if (false) { var isValidElementType; }
 
-      return this._getData(() => Component.__N_SSG ? this._getStaticData(as) : Component.__N_SSP ? this._getServerData(as) : this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+      var isSSG = Component.__N_SSG;
+      var isSSP = Component.__N_SSP;
+
+      var handleData = props => {
+        routeInfo.props = props;
+        this.components[route] = routeInfo;
+        return routeInfo;
+      }; // if we have data in cache resolve with the data
+      // if not we we resolve with fallback routeInfo
+
+
+      if (isSSG || isSSP) {
+        var dataRes = isSSG ? this._getStaticData(as) : this._getServerData(as);
+        return _Promise.resolve(typeof dataRes.then !== 'function' ? handleData(dataRes) : _Object$assign(_Object$assign({}, routeInfo), {
+          props: {},
+          dataRes: this._getData(() => dataRes.then(props => handleData(props)))
+        }));
+      }
+
+      return this._getData(() => this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
       {
         pathname,
         query,
         asPath: as
-      })).then(props => {
-        routeInfo.props = props;
-        this.components[route] = routeInfo;
-        return routeInfo;
-      });
+      })).then(props => handleData(props));
     }).catch(err => {
       return new _Promise(resolve => {
         if (err.code === 'PAGE_LOAD_ERROR') {
Diff for de003c3a9d30..686f3d49e.js
@@ -1147,10 +1147,10 @@ var _slicedToArray = __webpack_require__("8+Nu");
 
 var _Object$keys = __webpack_require__("pLtp");
 
-var _Object$assign = __webpack_require__("Qetd");
-
 var _Promise = __webpack_require__("eVuF");
 
+var _Object$assign = __webpack_require__("Qetd");
+
 var _classCallCheck = __webpack_require__("/HRN");
 
 var _createClass = __webpack_require__("WaGi");
@@ -1278,7 +1278,7 @@ function () {
 
     this._getStaticData = function (asPath) {
       var pathname = prepareRoute(url_1.parse(asPath).pathname);
-      return  true && _this.sdc[pathname] ? _Promise.resolve(_this.sdc[pathname]) : fetchNextData(pathname, null, function (data) {
+      return  true && _this.sdc[pathname] ? _this.sdc[pathname] : fetchNextData(pathname, null, function (data) {
         return _this.sdc[pathname] = data;
       });
     };
@@ -1510,15 +1510,43 @@ function () {
 
           if (false) { var appComp; }
 
-          _this2.set(route, pathname, query, as, routeInfo);
+          var doRouteChange = function doRouteChange(routeInfo, emit) {
+            _this2.set(route, pathname, query, as, routeInfo);
 
-          if (error) {
-            Router.events.emit('routeChangeError', error, as);
-            throw error;
-          }
+            if (emit) {
+              if (error) {
+                Router.events.emit('routeChangeError', error, as);
+                throw error;
+              }
 
-          Router.events.emit('routeChangeComplete', as);
-          return resolve(true);
+              Router.events.emit('routeChangeComplete', as);
+              resolve(true);
+            }
+          };
+
+          if (routeInfo.dataRes) {
+            var dataRes = routeInfo.dataRes; // race loading state timeout with data response
+            // if loading state wins we leave it for 50 ms even if data
+            // is 1ms after loading state timeout
+
+            _Promise.race([new _Promise(function (resolve) {
+              return setTimeout(function () {
+                return resolve(false);
+              }, 110);
+            }), dataRes]).then(function (data) {
+              if (!data) {
+                // data didn't win the race, show fallback
+                doRouteChange(routeInfo, false);
+              }
+
+              return dataRes;
+            }).then(function (finalData) {
+              // render with the data and complete route change
+              doRouteChange(finalData, true);
+            }, reject);
+          } else {
+            doRouteChange(routeInfo, true);
+          }
         }, reject);
       });
     }
@@ -1566,17 +1594,38 @@ function () {
 
         if (false) { var _require, isValidElementType; }
 
+        var isSSG = Component.__N_SSG;
+        var isSSP = Component.__N_SSP;
+
+        var handleData = function handleData(props) {
+          routeInfo.props = props;
+          _this3.components[route] = routeInfo;
+          return routeInfo;
+        }; // if we have data in cache resolve with the data
+        // if not we we resolve with fallback routeInfo
+
+
+        if (isSSG || isSSP) {
+          var dataRes = isSSG ? _this3._getStaticData(as) : _this3._getServerData(as);
+          return _Promise.resolve(typeof dataRes.then !== 'function' ? handleData(dataRes) : _Object$assign(_Object$assign({}, routeInfo), {
+            props: {},
+            dataRes: _this3._getData(function () {
+              return dataRes.then(function (props) {
+                return handleData(props);
+              });
+            })
+          }));
+        }
+
         return _this3._getData(function () {
-          return Component.__N_SSG ? _this3._getStaticData(as) : Component.__N_SSP ? _this3._getServerData(as) : _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+          return _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
           {
             pathname: pathname,
             query: query,
             asPath: as
           });
         }).then(function (props) {
-          routeInfo.props = props;
-          _this3.components[route] = routeInfo;
-          return routeInfo;
+          return handleData(props);
         });
       })["catch"](function (err) {
         return new _Promise(function (resolve) {
Diff for index.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.274b54332303ac77f61a.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c66c3cb3d27c8e68369.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.274b54332303ac77f61a.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for withRouter.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.274b54332303ac77f61a.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c66c3cb3d27c8e68369.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.274b54332303ac77f61a.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 11.6s 11.7s ⚠️ +87ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +6.8 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.18 kB ⚠️ +66 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..b50f.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..79d1.js gzip N/A 13.7 kB N/A
Overall change 67.3 kB 67.5 kB ⚠️ +192 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.17 kB ⚠️ +47 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB N/A N/A
framework.HA..dule.js gzip 39.1 kB 39.1 kB
de003c3a9d30..dule.js gzip N/A 12.5 kB N/A
Overall change 61.9 kB 62.1 kB ⚠️ +166 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Serverless bundles Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_error.js gzip 46.5 kB 46.6 kB ⚠️ +101 B
404.html gzip 1.43 kB 1.44 kB ⚠️ +10 B
hooks.html gzip 1.07 kB 1.07 kB ⚠️ +9 B
index.js gzip 46.5 kB 46.6 kB ⚠️ +92 B
link.js gzip 72 kB 72.5 kB ⚠️ +491 B
routerDirect.js gzip 70.2 kB 70.7 kB ⚠️ +475 B
withRouter.js gzip 70 kB 70.5 kB ⚠️ +472 B
Overall change 308 kB 309 kB ⚠️ +1.65 kB

Commit: 778db98

@ijjk
Copy link
Member Author

ijjk commented Feb 5, 2020

Stats from current PR

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 11.3s 11.4s ⚠️ +43ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +6.55 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.18 kB ⚠️ +66 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..b50f.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..479a.js gzip N/A 13.7 kB N/A
Overall change 67.3 kB 67.5 kB ⚠️ +192 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.17 kB ⚠️ +47 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB 12.5 kB ⚠️ +119 B
framework.HA..dule.js gzip 39.1 kB 39.1 kB
Overall change 61.9 kB 62.1 kB ⚠️ +166 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Rendered Page Sizes Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
index.html gzip 1.02 kB 1.03 kB ⚠️ +13 B
link.html gzip 1.03 kB 1.04 kB ⚠️ +10 B
withRouter.html gzip 1.02 kB 1.03 kB ⚠️ +14 B
Overall change 3.07 kB 3.11 kB ⚠️ +37 B

Diffs

Diff for index.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.6803a145cf266c5985a7.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9d6541a3594af05db0bb.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.6803a145cf266c5985a7.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for main-HASH.module.js
@@ -284,11 +284,22 @@ class Container extends _react.default.Component {
   componentDidMount() {
     this.scrollToHash();
 
-    if (false) {} // If page was exported and has a querystring
+    if (false) {} // call router.replace to trigger data fetching while
+    // the fallback is shown
+
+
+    if (data.isFallback) {
+      router.replace({
+        pathname: page,
+        query: (0, _extends2.default)({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))
+      }, asPath, {
+        _h: 1
+      });
+    } // If page was exported and has a querystring
     // If it's a dynamic route or has a querystring
 
 
-    if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+    if (!data.isFallback && router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
       // update query on mount for exported pages
       router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2.default)({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
         // WARNING: `_h` is an internal option for handing Next.js
@@ -411,6 +422,12 @@ var _default = async function _default(_temp) {
   };
 
   if (true) {
+    // kick off static data request now so it's in the cache
+    // when we re-render post-hydration
+    if (data.isFallback) {
+      router._getStaticData(asPath).catch(() => {});
+    }
+
     render(renderCtx);
     return emitter;
   }
Diff for main-HASH.js
@@ -379,11 +379,22 @@ function (_react$default$Compon) {
     value: function componentDidMount() {
       this.scrollToHash();
 
-      if (false) {} // If page was exported and has a querystring
+      if (false) {} // call router.replace to trigger data fetching while
+      // the fallback is shown
+
+
+      if (data.isFallback) {
+        router.replace({
+          pathname: page,
+          query: (0, _extends2["default"])({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))
+        }, asPath, {
+          _h: 1
+        });
+      } // If page was exported and has a querystring
       // If it's a dynamic route or has a querystring
 
 
-      if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+      if (!data.isFallback && router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
         // update query on mount for exported pages
         router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2["default"])({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
           // WARNING: `_h` is an internal option for handing Next.js
@@ -543,12 +554,18 @@ var _default = function _default(_temp) {
 
           if (false) {}
 
+          // kick off static data request now so it's in the cache
+          // when we re-render post-hydration
+          if (data.isFallback) {
+            router._getStaticData(asPath)["catch"](function () {});
+          }
+
           render(renderCtx);
           return _context.abrupt("return", emitter);
 
-        case 32:
+        case 33:
           if (true) {
-            _context.next = 34;
+            _context.next = 35;
             break;
           }
 
@@ -558,7 +575,7 @@ var _default = function _default(_temp) {
             renderCtx: renderCtx
           });
 
-        case 34:
+        case 35:
         case "end":
           return _context.stop();
       }
Diff for de003c3a9d30..29.module.js
@@ -1433,10 +1433,10 @@ module.exports = __webpack_require__("aW7e");
 
 var _Object$keys = __webpack_require__("pLtp");
 
-var _Object$assign = __webpack_require__("Qetd");
-
 var _Promise = __webpack_require__("eVuF");
 
+var _Object$assign = __webpack_require__("Qetd");
+
 var _Object$defineProperty = __webpack_require__("hfKm");
 
 var __importDefault = this && this.__importDefault || function (mod) {
@@ -1554,7 +1554,7 @@ class Router {
 
     this._getStaticData = asPath => {
       var pathname = prepareRoute(url_1.parse(asPath).pathname);
-      return  true && this.sdc[pathname] ? _Promise.resolve(this.sdc[pathname]) : fetchNextData(pathname, null, data => this.sdc[pathname] = data);
+      return  true && this.sdc[pathname] ? this.sdc[pathname] : fetchNextData(pathname, null, data => this.sdc[pathname] = data);
     };
 
     this._getServerData = asPath => {
@@ -1778,15 +1778,37 @@ class Router {
 
         if (false) { var appComp; }
 
-        this.set(route, pathname, query, as, routeInfo);
+        var doRouteChange = (routeInfo, emit) => {
+          this.set(route, pathname, query, as, routeInfo);
 
-        if (error) {
-          Router.events.emit('routeChangeError', error, as);
-          throw error;
-        }
+          if (emit) {
+            if (error) {
+              Router.events.emit('routeChangeError', error, as);
+              throw error;
+            }
 
-        Router.events.emit('routeChangeComplete', as);
-        return resolve(true);
+            Router.events.emit('routeChangeComplete', as);
+            resolve(true);
+          }
+        };
+
+        if (routeInfo.dataRes) {
+          var dataRes = routeInfo.dataRes; // race loading state timeout with data response
+
+          _Promise.race([new _Promise(resolve => setTimeout(() => resolve(false), 110)), dataRes]).then(data => {
+            if (!data) {
+              // data didn't win the race, show fallback
+              doRouteChange(routeInfo, false);
+            }
+
+            return dataRes;
+          }).then(finalData => {
+            // render with the data and complete route change
+            doRouteChange(finalData, true);
+          }, reject);
+        } else {
+          doRouteChange(routeInfo, true);
+        }
       }, reject);
     });
   }
@@ -1830,16 +1852,31 @@ class Router {
 
       if (false) { var isValidElementType; }
 
-      return this._getData(() => Component.__N_SSG ? this._getStaticData(as) : Component.__N_SSP ? this._getServerData(as) : this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+      var isSSG = Component.__N_SSG;
+      var isSSP = Component.__N_SSP;
+
+      var handleData = props => {
+        routeInfo.props = props;
+        this.components[route] = routeInfo;
+        return routeInfo;
+      }; // if we have data in cache resolve with the data
+      // if not we we resolve with fallback routeInfo
+
+
+      if (isSSG || isSSP) {
+        var dataRes = isSSG ? this._getStaticData(as) : this._getServerData(as);
+        return _Promise.resolve(typeof dataRes.then !== 'function' ? handleData(dataRes) : _Object$assign(_Object$assign({}, routeInfo), {
+          props: {},
+          dataRes: this._getData(() => dataRes.then(props => handleData(props)))
+        }));
+      }
+
+      return this._getData(() => this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
       {
         pathname,
         query,
         asPath: as
-      })).then(props => {
-        routeInfo.props = props;
-        this.components[route] = routeInfo;
-        return routeInfo;
-      });
+      })).then(props => handleData(props));
     }).catch(err => {
       return new _Promise(resolve => {
         if (err.code === 'PAGE_LOAD_ERROR') {
Diff for de003c3a9d30..686f3d49e.js
@@ -1147,10 +1147,10 @@ var _slicedToArray = __webpack_require__("8+Nu");
 
 var _Object$keys = __webpack_require__("pLtp");
 
-var _Object$assign = __webpack_require__("Qetd");
-
 var _Promise = __webpack_require__("eVuF");
 
+var _Object$assign = __webpack_require__("Qetd");
+
 var _classCallCheck = __webpack_require__("/HRN");
 
 var _createClass = __webpack_require__("WaGi");
@@ -1278,7 +1278,7 @@ function () {
 
     this._getStaticData = function (asPath) {
       var pathname = prepareRoute(url_1.parse(asPath).pathname);
-      return  true && _this.sdc[pathname] ? _Promise.resolve(_this.sdc[pathname]) : fetchNextData(pathname, null, function (data) {
+      return  true && _this.sdc[pathname] ? _this.sdc[pathname] : fetchNextData(pathname, null, function (data) {
         return _this.sdc[pathname] = data;
       });
     };
@@ -1510,15 +1510,41 @@ function () {
 
           if (false) { var appComp; }
 
-          _this2.set(route, pathname, query, as, routeInfo);
+          var doRouteChange = function doRouteChange(routeInfo, emit) {
+            _this2.set(route, pathname, query, as, routeInfo);
 
-          if (error) {
-            Router.events.emit('routeChangeError', error, as);
-            throw error;
-          }
+            if (emit) {
+              if (error) {
+                Router.events.emit('routeChangeError', error, as);
+                throw error;
+              }
 
-          Router.events.emit('routeChangeComplete', as);
-          return resolve(true);
+              Router.events.emit('routeChangeComplete', as);
+              resolve(true);
+            }
+          };
+
+          if (routeInfo.dataRes) {
+            var dataRes = routeInfo.dataRes; // race loading state timeout with data response
+
+            _Promise.race([new _Promise(function (resolve) {
+              return setTimeout(function () {
+                return resolve(false);
+              }, 110);
+            }), dataRes]).then(function (data) {
+              if (!data) {
+                // data didn't win the race, show fallback
+                doRouteChange(routeInfo, false);
+              }
+
+              return dataRes;
+            }).then(function (finalData) {
+              // render with the data and complete route change
+              doRouteChange(finalData, true);
+            }, reject);
+          } else {
+            doRouteChange(routeInfo, true);
+          }
         }, reject);
       });
     }
@@ -1566,17 +1592,38 @@ function () {
 
         if (false) { var _require, isValidElementType; }
 
+        var isSSG = Component.__N_SSG;
+        var isSSP = Component.__N_SSP;
+
+        var handleData = function handleData(props) {
+          routeInfo.props = props;
+          _this3.components[route] = routeInfo;
+          return routeInfo;
+        }; // if we have data in cache resolve with the data
+        // if not we we resolve with fallback routeInfo
+
+
+        if (isSSG || isSSP) {
+          var dataRes = isSSG ? _this3._getStaticData(as) : _this3._getServerData(as);
+          return _Promise.resolve(typeof dataRes.then !== 'function' ? handleData(dataRes) : _Object$assign(_Object$assign({}, routeInfo), {
+            props: {},
+            dataRes: _this3._getData(function () {
+              return dataRes.then(function (props) {
+                return handleData(props);
+              });
+            })
+          }));
+        }
+
         return _this3._getData(function () {
-          return Component.__N_SSG ? _this3._getStaticData(as) : Component.__N_SSP ? _this3._getServerData(as) : _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+          return _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
           {
             pathname: pathname,
             query: query,
             asPath: as
           });
         }).then(function (props) {
-          routeInfo.props = props;
-          _this3.components[route] = routeInfo;
-          return routeInfo;
+          return handleData(props);
         });
       })["catch"](function (err) {
         return new _Promise(function (resolve) {
Diff for link.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.6803a145cf266c5985a7.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9d6541a3594af05db0bb.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.6803a145cf266c5985a7.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for withRouter.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.6803a145cf266c5985a7.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9d6541a3594af05db0bb.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.6803a145cf266c5985a7.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 11.6s 12.2s ⚠️ +653ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +6.55 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.18 kB ⚠️ +66 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..b50f.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..479a.js gzip N/A 13.7 kB N/A
Overall change 67.3 kB 67.5 kB ⚠️ +192 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.17 kB ⚠️ +47 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB N/A N/A
framework.HA..dule.js gzip 39.1 kB 39.1 kB
de003c3a9d30..dule.js gzip N/A 12.5 kB N/A
Overall change 61.9 kB 62.1 kB ⚠️ +166 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Serverless bundles Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_error.js gzip 46.5 kB 46.6 kB ⚠️ +100 B
404.html gzip 1.43 kB 1.45 kB ⚠️ +12 B
hooks.html gzip 1.07 kB 1.07 kB ⚠️ +9 B
index.js gzip 46.5 kB 46.6 kB ⚠️ +91 B
link.js gzip 72 kB 72.4 kB ⚠️ +450 B
routerDirect.js gzip 70.2 kB 70.6 kB ⚠️ +426 B
withRouter.js gzip 70 kB 70.4 kB ⚠️ +432 B
Overall change 308 kB 309 kB ⚠️ +1.52 kB

Commit: 591b4a0

@ijjk
Copy link
Member Author

ijjk commented Feb 5, 2020

Stats from current PR

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 13.2s 13.3s ⚠️ +108ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +6.75 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.18 kB ⚠️ +66 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..b50f.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..9aa3.js gzip N/A 13.7 kB N/A
Overall change 67.3 kB 67.5 kB ⚠️ +195 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.17 kB ⚠️ +47 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB 12.5 kB ⚠️ +119 B
framework.HA..dule.js gzip 39.1 kB 39.1 kB
Overall change 61.9 kB 62.1 kB ⚠️ +166 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Rendered Page Sizes Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
index.html gzip 1.02 kB 1.03 kB ⚠️ +10 B
link.html gzip 1.03 kB 1.04 kB ⚠️ +8 B
withRouter.html gzip 1.02 kB 1.03 kB ⚠️ +11 B
Overall change 3.07 kB 3.1 kB ⚠️ +29 B

Diffs

Diff for index.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.800e2531cee4c9c783e6.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.52bdb9a42710fb5a7793.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.800e2531cee4c9c783e6.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for main-HASH.module.js
@@ -284,11 +284,22 @@ class Container extends _react.default.Component {
   componentDidMount() {
     this.scrollToHash();
 
-    if (false) {} // If page was exported and has a querystring
+    if (false) {} // call router.replace to trigger data fetching while
+    // the fallback is shown
+
+
+    if (data.isFallback) {
+      router.replace({
+        pathname: page,
+        query: (0, _extends2.default)({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))
+      }, asPath, {
+        _h: 1
+      });
+    } // If page was exported and has a querystring
     // If it's a dynamic route or has a querystring
 
 
-    if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+    if (!data.isFallback && router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
       // update query on mount for exported pages
       router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2.default)({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
         // WARNING: `_h` is an internal option for handing Next.js
@@ -411,6 +422,12 @@ var _default = async function _default(_temp) {
   };
 
   if (true) {
+    // kick off static data request now so it's in the cache
+    // when we re-render post-hydration
+    if (data.isFallback) {
+      router._getStaticData(asPath).catch(() => {});
+    }
+
     render(renderCtx);
     return emitter;
   }
Diff for main-HASH.js
@@ -379,11 +379,22 @@ function (_react$default$Compon) {
     value: function componentDidMount() {
       this.scrollToHash();
 
-      if (false) {} // If page was exported and has a querystring
+      if (false) {} // call router.replace to trigger data fetching while
+      // the fallback is shown
+
+
+      if (data.isFallback) {
+        router.replace({
+          pathname: page,
+          query: (0, _extends2["default"])({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))
+        }, asPath, {
+          _h: 1
+        });
+      } // If page was exported and has a querystring
       // If it's a dynamic route or has a querystring
 
 
-      if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+      if (!data.isFallback && router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
         // update query on mount for exported pages
         router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2["default"])({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
           // WARNING: `_h` is an internal option for handing Next.js
@@ -543,12 +554,18 @@ var _default = function _default(_temp) {
 
           if (false) {}
 
+          // kick off static data request now so it's in the cache
+          // when we re-render post-hydration
+          if (data.isFallback) {
+            router._getStaticData(asPath)["catch"](function () {});
+          }
+
           render(renderCtx);
           return _context.abrupt("return", emitter);
 
-        case 32:
+        case 33:
           if (true) {
-            _context.next = 34;
+            _context.next = 35;
             break;
           }
 
@@ -558,7 +575,7 @@ var _default = function _default(_temp) {
             renderCtx: renderCtx
           });
 
-        case 34:
+        case 35:
         case "end":
           return _context.stop();
       }
Diff for de003c3a9d30..29.module.js
@@ -1433,10 +1433,10 @@ module.exports = __webpack_require__("aW7e");
 
 var _Object$keys = __webpack_require__("pLtp");
 
-var _Object$assign = __webpack_require__("Qetd");
-
 var _Promise = __webpack_require__("eVuF");
 
+var _Object$assign = __webpack_require__("Qetd");
+
 var _Object$defineProperty = __webpack_require__("hfKm");
 
 var __importDefault = this && this.__importDefault || function (mod) {
@@ -1554,7 +1554,7 @@ class Router {
 
     this._getStaticData = asPath => {
       var pathname = prepareRoute(url_1.parse(asPath).pathname);
-      return  true && this.sdc[pathname] ? _Promise.resolve(this.sdc[pathname]) : fetchNextData(pathname, null, data => this.sdc[pathname] = data);
+      return  true && this.sdc[pathname] ? this.sdc[pathname] : fetchNextData(pathname, null, data => this.sdc[pathname] = data);
     };
 
     this._getServerData = asPath => {
@@ -1765,28 +1765,52 @@ class Router {
       Router.events.emit('routeChangeStart', as); // If shallow is true and the route exists in the router cache we reuse the previous result
 
       this.getRouteInfo(route, pathname, query, as, shallow).then(routeInfo => {
-        var {
-          error
-        } = routeInfo;
+        var doRouteChange = (routeInfo, emit) => {
+          var {
+            error
+          } = routeInfo;
 
-        if (error && error.cancelled) {
-          return resolve(false);
-        }
+          if (error && error.cancelled) {
+            return resolve(false);
+          }
 
-        Router.events.emit('beforeHistoryChange', as);
-        this.changeState(method, url, addBasePath(as), options);
+          if (emit) {
+            Router.events.emit('beforeHistoryChange', as);
+            this.changeState(method, url, addBasePath(as), options);
 
-        if (false) { var appComp; }
+            if (false) { var appComp; }
+          }
 
-        this.set(route, pathname, query, as, routeInfo);
+          this.set(route, pathname, query, as, routeInfo);
 
-        if (error) {
-          Router.events.emit('routeChangeError', error, as);
-          throw error;
-        }
+          if (emit) {
+            if (error) {
+              Router.events.emit('routeChangeError', error, as);
+              throw error;
+            }
 
-        Router.events.emit('routeChangeComplete', as);
-        return resolve(true);
+            Router.events.emit('routeChangeComplete', as);
+            resolve(true);
+          }
+        };
+
+        if (routeInfo.dataRes) {
+          var dataRes = routeInfo.dataRes; // race loading state timeout with data response
+
+          _Promise.race([new _Promise(resolve => setTimeout(() => resolve(false), 110)), dataRes]).then(data => {
+            if (!data) {
+              // data didn't win the race, show fallback
+              doRouteChange(routeInfo, false);
+            }
+
+            return dataRes;
+          }).then(finalData => {
+            // render with the data and complete route change
+            doRouteChange(finalData, true);
+          }, reject);
+        } else {
+          doRouteChange(routeInfo, true);
+        }
       }, reject);
     });
   }
@@ -1830,16 +1854,31 @@ class Router {
 
       if (false) { var isValidElementType; }
 
-      return this._getData(() => Component.__N_SSG ? this._getStaticData(as) : Component.__N_SSP ? this._getServerData(as) : this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+      var isSSG = Component.__N_SSG;
+      var isSSP = Component.__N_SSP;
+
+      var handleData = props => {
+        routeInfo.props = props;
+        this.components[route] = routeInfo;
+        return routeInfo;
+      }; // if we have data in cache resolve with the data
+      // if not we we resolve with fallback routeInfo
+
+
+      if (isSSG || isSSP) {
+        var dataRes = isSSG ? this._getStaticData(as) : this._getServerData(as);
+        return _Promise.resolve(typeof dataRes.then !== 'function' ? handleData(dataRes) : _Object$assign(_Object$assign({}, routeInfo), {
+          props: {},
+          dataRes: this._getData(() => dataRes.then(props => handleData(props)))
+        }));
+      }
+
+      return this._getData(() => this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
       {
         pathname,
         query,
         asPath: as
-      })).then(props => {
-        routeInfo.props = props;
-        this.components[route] = routeInfo;
-        return routeInfo;
-      });
+      })).then(props => handleData(props));
     }).catch(err => {
       return new _Promise(resolve => {
         if (err.code === 'PAGE_LOAD_ERROR') {
Diff for de003c3a9d30..686f3d49e.js
@@ -1147,10 +1147,10 @@ var _slicedToArray = __webpack_require__("8+Nu");
 
 var _Object$keys = __webpack_require__("pLtp");
 
-var _Object$assign = __webpack_require__("Qetd");
-
 var _Promise = __webpack_require__("eVuF");
 
+var _Object$assign = __webpack_require__("Qetd");
+
 var _classCallCheck = __webpack_require__("/HRN");
 
 var _createClass = __webpack_require__("WaGi");
@@ -1278,7 +1278,7 @@ function () {
 
     this._getStaticData = function (asPath) {
       var pathname = prepareRoute(url_1.parse(asPath).pathname);
-      return  true && _this.sdc[pathname] ? _Promise.resolve(_this.sdc[pathname]) : fetchNextData(pathname, null, function (data) {
+      return  true && _this.sdc[pathname] ? _this.sdc[pathname] : fetchNextData(pathname, null, function (data) {
         return _this.sdc[pathname] = data;
       });
     };
@@ -1498,27 +1498,55 @@ function () {
         Router.events.emit('routeChangeStart', as); // If shallow is true and the route exists in the router cache we reuse the previous result
 
         _this2.getRouteInfo(route, pathname, query, as, shallow).then(function (routeInfo) {
-          var error = routeInfo.error;
+          var doRouteChange = function doRouteChange(routeInfo, emit) {
+            var error = routeInfo.error;
 
-          if (error && error.cancelled) {
-            return resolve(false);
-          }
+            if (error && error.cancelled) {
+              return resolve(false);
+            }
 
-          Router.events.emit('beforeHistoryChange', as);
+            if (emit) {
+              Router.events.emit('beforeHistoryChange', as);
 
-          _this2.changeState(method, url, addBasePath(as), options);
+              _this2.changeState(method, url, addBasePath(as), options);
+
+              if (false) { var appComp; }
+            }
 
-          if (false) { var appComp; }
+            _this2.set(route, pathname, query, as, routeInfo);
 
-          _this2.set(route, pathname, query, as, routeInfo);
+            if (emit) {
+              if (error) {
+                Router.events.emit('routeChangeError', error, as);
+                throw error;
+              }
 
-          if (error) {
-            Router.events.emit('routeChangeError', error, as);
-            throw error;
-          }
+              Router.events.emit('routeChangeComplete', as);
+              resolve(true);
+            }
+          };
 
-          Router.events.emit('routeChangeComplete', as);
-          return resolve(true);
+          if (routeInfo.dataRes) {
+            var dataRes = routeInfo.dataRes; // race loading state timeout with data response
+
+            _Promise.race([new _Promise(function (resolve) {
+              return setTimeout(function () {
+                return resolve(false);
+              }, 110);
+            }), dataRes]).then(function (data) {
+              if (!data) {
+                // data didn't win the race, show fallback
+                doRouteChange(routeInfo, false);
+              }
+
+              return dataRes;
+            }).then(function (finalData) {
+              // render with the data and complete route change
+              doRouteChange(finalData, true);
+            }, reject);
+          } else {
+            doRouteChange(routeInfo, true);
+          }
         }, reject);
       });
     }
@@ -1566,17 +1594,38 @@ function () {
 
         if (false) { var _require, isValidElementType; }
 
+        var isSSG = Component.__N_SSG;
+        var isSSP = Component.__N_SSP;
+
+        var handleData = function handleData(props) {
+          routeInfo.props = props;
+          _this3.components[route] = routeInfo;
+          return routeInfo;
+        }; // if we have data in cache resolve with the data
+        // if not we we resolve with fallback routeInfo
+
+
+        if (isSSG || isSSP) {
+          var dataRes = isSSG ? _this3._getStaticData(as) : _this3._getServerData(as);
+          return _Promise.resolve(typeof dataRes.then !== 'function' ? handleData(dataRes) : _Object$assign(_Object$assign({}, routeInfo), {
+            props: {},
+            dataRes: _this3._getData(function () {
+              return dataRes.then(function (props) {
+                return handleData(props);
+              });
+            })
+          }));
+        }
+
         return _this3._getData(function () {
-          return Component.__N_SSG ? _this3._getStaticData(as) : Component.__N_SSP ? _this3._getServerData(as) : _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+          return _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
           {
             pathname: pathname,
             query: query,
             asPath: as
           });
         }).then(function (props) {
-          routeInfo.props = props;
-          _this3.components[route] = routeInfo;
-          return routeInfo;
+          return handleData(props);
         });
       })["catch"](function (err) {
         return new _Promise(function (resolve) {
Diff for link.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.800e2531cee4c9c783e6.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.52bdb9a42710fb5a7793.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.800e2531cee4c9c783e6.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for withRouter.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.800e2531cee4c9c783e6.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.52bdb9a42710fb5a7793.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.800e2531cee4c9c783e6.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 14.3s 13.8s -448ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +6.75 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.18 kB ⚠️ +66 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..b50f.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..9aa3.js gzip N/A 13.7 kB N/A
Overall change 67.3 kB 67.5 kB ⚠️ +195 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.17 kB ⚠️ +47 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB N/A N/A
framework.HA..dule.js gzip 39.1 kB 39.1 kB
de003c3a9d30..dule.js gzip N/A 12.5 kB N/A
Overall change 61.9 kB 62.1 kB ⚠️ +166 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Serverless bundles Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_error.js gzip 46.5 kB 46.6 kB ⚠️ +102 B
404.html gzip 1.43 kB 1.44 kB ⚠️ +10 B
hooks.html gzip 1.07 kB 1.07 kB ⚠️ +9 B
index.js gzip 46.5 kB 46.6 kB ⚠️ +93 B
link.js gzip 72 kB 72.4 kB ⚠️ +464 B
routerDirect.js gzip 70.2 kB 70.6 kB ⚠️ +437 B
withRouter.js gzip 70 kB 70.5 kB ⚠️ +444 B
Overall change 308 kB 309 kB ⚠️ +1.56 kB

Commit: efd508b

@ijjk
Copy link
Member Author

ijjk commented Feb 5, 2020

Stats from current PR

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 11.9s 12.1s ⚠️ +118ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +6.58 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.18 kB ⚠️ +66 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..b50f.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..9aa3.js gzip N/A 13.7 kB N/A
Overall change 67.3 kB 67.5 kB ⚠️ +195 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.17 kB ⚠️ +47 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB 12.5 kB ⚠️ +119 B
framework.HA..dule.js gzip 39.1 kB 39.1 kB
Overall change 61.9 kB 62.1 kB ⚠️ +166 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Rendered Page Sizes Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
index.html gzip 1.02 kB 1.03 kB ⚠️ +10 B
link.html gzip 1.03 kB 1.04 kB ⚠️ +8 B
withRouter.html gzip 1.02 kB 1.03 kB ⚠️ +11 B
Overall change 3.07 kB 3.1 kB ⚠️ +29 B

Diffs

Diff for index.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.800e2531cee4c9c783e6.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.52bdb9a42710fb5a7793.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.800e2531cee4c9c783e6.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for main-HASH.module.js
@@ -284,11 +284,22 @@ class Container extends _react.default.Component {
   componentDidMount() {
     this.scrollToHash();
 
-    if (false) {} // If page was exported and has a querystring
+    if (false) {} // call router.replace to trigger data fetching while
+    // the fallback is shown
+
+
+    if (data.isFallback) {
+      router.replace({
+        pathname: page,
+        query: (0, _extends2.default)({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))
+      }, asPath, {
+        _h: 1
+      });
+    } // If page was exported and has a querystring
     // If it's a dynamic route or has a querystring
 
 
-    if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+    if (!data.isFallback && router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
       // update query on mount for exported pages
       router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2.default)({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
         // WARNING: `_h` is an internal option for handing Next.js
@@ -411,6 +422,12 @@ var _default = async function _default(_temp) {
   };
 
   if (true) {
+    // kick off static data request now so it's in the cache
+    // when we re-render post-hydration
+    if (data.isFallback) {
+      router._getStaticData(asPath).catch(() => {});
+    }
+
     render(renderCtx);
     return emitter;
   }
Diff for main-HASH.js
@@ -379,11 +379,22 @@ function (_react$default$Compon) {
     value: function componentDidMount() {
       this.scrollToHash();
 
-      if (false) {} // If page was exported and has a querystring
+      if (false) {} // call router.replace to trigger data fetching while
+      // the fallback is shown
+
+
+      if (data.isFallback) {
+        router.replace({
+          pathname: page,
+          query: (0, _extends2["default"])({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))
+        }, asPath, {
+          _h: 1
+        });
+      } // If page was exported and has a querystring
       // If it's a dynamic route or has a querystring
 
 
-      if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+      if (!data.isFallback && router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
         // update query on mount for exported pages
         router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2["default"])({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
           // WARNING: `_h` is an internal option for handing Next.js
@@ -543,12 +554,18 @@ var _default = function _default(_temp) {
 
           if (false) {}
 
+          // kick off static data request now so it's in the cache
+          // when we re-render post-hydration
+          if (data.isFallback) {
+            router._getStaticData(asPath)["catch"](function () {});
+          }
+
           render(renderCtx);
           return _context.abrupt("return", emitter);
 
-        case 32:
+        case 33:
           if (true) {
-            _context.next = 34;
+            _context.next = 35;
             break;
           }
 
@@ -558,7 +575,7 @@ var _default = function _default(_temp) {
             renderCtx: renderCtx
           });
 
-        case 34:
+        case 35:
         case "end":
           return _context.stop();
       }
Diff for de003c3a9d30..29.module.js
@@ -1433,10 +1433,10 @@ module.exports = __webpack_require__("aW7e");
 
 var _Object$keys = __webpack_require__("pLtp");
 
-var _Object$assign = __webpack_require__("Qetd");
-
 var _Promise = __webpack_require__("eVuF");
 
+var _Object$assign = __webpack_require__("Qetd");
+
 var _Object$defineProperty = __webpack_require__("hfKm");
 
 var __importDefault = this && this.__importDefault || function (mod) {
@@ -1554,7 +1554,7 @@ class Router {
 
     this._getStaticData = asPath => {
       var pathname = prepareRoute(url_1.parse(asPath).pathname);
-      return  true && this.sdc[pathname] ? _Promise.resolve(this.sdc[pathname]) : fetchNextData(pathname, null, data => this.sdc[pathname] = data);
+      return  true && this.sdc[pathname] ? this.sdc[pathname] : fetchNextData(pathname, null, data => this.sdc[pathname] = data);
     };
 
     this._getServerData = asPath => {
@@ -1765,28 +1765,52 @@ class Router {
       Router.events.emit('routeChangeStart', as); // If shallow is true and the route exists in the router cache we reuse the previous result
 
       this.getRouteInfo(route, pathname, query, as, shallow).then(routeInfo => {
-        var {
-          error
-        } = routeInfo;
+        var doRouteChange = (routeInfo, emit) => {
+          var {
+            error
+          } = routeInfo;
 
-        if (error && error.cancelled) {
-          return resolve(false);
-        }
+          if (error && error.cancelled) {
+            return resolve(false);
+          }
 
-        Router.events.emit('beforeHistoryChange', as);
-        this.changeState(method, url, addBasePath(as), options);
+          if (emit) {
+            Router.events.emit('beforeHistoryChange', as);
+            this.changeState(method, url, addBasePath(as), options);
 
-        if (false) { var appComp; }
+            if (false) { var appComp; }
+          }
 
-        this.set(route, pathname, query, as, routeInfo);
+          this.set(route, pathname, query, as, routeInfo);
 
-        if (error) {
-          Router.events.emit('routeChangeError', error, as);
-          throw error;
-        }
+          if (emit) {
+            if (error) {
+              Router.events.emit('routeChangeError', error, as);
+              throw error;
+            }
 
-        Router.events.emit('routeChangeComplete', as);
-        return resolve(true);
+            Router.events.emit('routeChangeComplete', as);
+            resolve(true);
+          }
+        };
+
+        if (routeInfo.dataRes) {
+          var dataRes = routeInfo.dataRes; // race loading state timeout with data response
+
+          _Promise.race([new _Promise(resolve => setTimeout(() => resolve(false), 110)), dataRes]).then(data => {
+            if (!data) {
+              // data didn't win the race, show fallback
+              doRouteChange(routeInfo, false);
+            }
+
+            return dataRes;
+          }).then(finalData => {
+            // render with the data and complete route change
+            doRouteChange(finalData, true);
+          }, reject);
+        } else {
+          doRouteChange(routeInfo, true);
+        }
       }, reject);
     });
   }
@@ -1830,16 +1854,31 @@ class Router {
 
       if (false) { var isValidElementType; }
 
-      return this._getData(() => Component.__N_SSG ? this._getStaticData(as) : Component.__N_SSP ? this._getServerData(as) : this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+      var isSSG = Component.__N_SSG;
+      var isSSP = Component.__N_SSP;
+
+      var handleData = props => {
+        routeInfo.props = props;
+        this.components[route] = routeInfo;
+        return routeInfo;
+      }; // if we have data in cache resolve with the data
+      // if not we we resolve with fallback routeInfo
+
+
+      if (isSSG || isSSP) {
+        var dataRes = isSSG ? this._getStaticData(as) : this._getServerData(as);
+        return _Promise.resolve(typeof dataRes.then !== 'function' ? handleData(dataRes) : _Object$assign(_Object$assign({}, routeInfo), {
+          props: {},
+          dataRes: this._getData(() => dataRes.then(props => handleData(props)))
+        }));
+      }
+
+      return this._getData(() => this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
       {
         pathname,
         query,
         asPath: as
-      })).then(props => {
-        routeInfo.props = props;
-        this.components[route] = routeInfo;
-        return routeInfo;
-      });
+      })).then(props => handleData(props));
     }).catch(err => {
       return new _Promise(resolve => {
         if (err.code === 'PAGE_LOAD_ERROR') {
Diff for de003c3a9d30..686f3d49e.js
@@ -1147,10 +1147,10 @@ var _slicedToArray = __webpack_require__("8+Nu");
 
 var _Object$keys = __webpack_require__("pLtp");
 
-var _Object$assign = __webpack_require__("Qetd");
-
 var _Promise = __webpack_require__("eVuF");
 
+var _Object$assign = __webpack_require__("Qetd");
+
 var _classCallCheck = __webpack_require__("/HRN");
 
 var _createClass = __webpack_require__("WaGi");
@@ -1278,7 +1278,7 @@ function () {
 
     this._getStaticData = function (asPath) {
       var pathname = prepareRoute(url_1.parse(asPath).pathname);
-      return  true && _this.sdc[pathname] ? _Promise.resolve(_this.sdc[pathname]) : fetchNextData(pathname, null, function (data) {
+      return  true && _this.sdc[pathname] ? _this.sdc[pathname] : fetchNextData(pathname, null, function (data) {
         return _this.sdc[pathname] = data;
       });
     };
@@ -1498,27 +1498,55 @@ function () {
         Router.events.emit('routeChangeStart', as); // If shallow is true and the route exists in the router cache we reuse the previous result
 
         _this2.getRouteInfo(route, pathname, query, as, shallow).then(function (routeInfo) {
-          var error = routeInfo.error;
+          var doRouteChange = function doRouteChange(routeInfo, emit) {
+            var error = routeInfo.error;
 
-          if (error && error.cancelled) {
-            return resolve(false);
-          }
+            if (error && error.cancelled) {
+              return resolve(false);
+            }
 
-          Router.events.emit('beforeHistoryChange', as);
+            if (emit) {
+              Router.events.emit('beforeHistoryChange', as);
 
-          _this2.changeState(method, url, addBasePath(as), options);
+              _this2.changeState(method, url, addBasePath(as), options);
+
+              if (false) { var appComp; }
+            }
 
-          if (false) { var appComp; }
+            _this2.set(route, pathname, query, as, routeInfo);
 
-          _this2.set(route, pathname, query, as, routeInfo);
+            if (emit) {
+              if (error) {
+                Router.events.emit('routeChangeError', error, as);
+                throw error;
+              }
 
-          if (error) {
-            Router.events.emit('routeChangeError', error, as);
-            throw error;
-          }
+              Router.events.emit('routeChangeComplete', as);
+              resolve(true);
+            }
+          };
 
-          Router.events.emit('routeChangeComplete', as);
-          return resolve(true);
+          if (routeInfo.dataRes) {
+            var dataRes = routeInfo.dataRes; // race loading state timeout with data response
+
+            _Promise.race([new _Promise(function (resolve) {
+              return setTimeout(function () {
+                return resolve(false);
+              }, 110);
+            }), dataRes]).then(function (data) {
+              if (!data) {
+                // data didn't win the race, show fallback
+                doRouteChange(routeInfo, false);
+              }
+
+              return dataRes;
+            }).then(function (finalData) {
+              // render with the data and complete route change
+              doRouteChange(finalData, true);
+            }, reject);
+          } else {
+            doRouteChange(routeInfo, true);
+          }
         }, reject);
       });
     }
@@ -1566,17 +1594,38 @@ function () {
 
         if (false) { var _require, isValidElementType; }
 
+        var isSSG = Component.__N_SSG;
+        var isSSP = Component.__N_SSP;
+
+        var handleData = function handleData(props) {
+          routeInfo.props = props;
+          _this3.components[route] = routeInfo;
+          return routeInfo;
+        }; // if we have data in cache resolve with the data
+        // if not we we resolve with fallback routeInfo
+
+
+        if (isSSG || isSSP) {
+          var dataRes = isSSG ? _this3._getStaticData(as) : _this3._getServerData(as);
+          return _Promise.resolve(typeof dataRes.then !== 'function' ? handleData(dataRes) : _Object$assign(_Object$assign({}, routeInfo), {
+            props: {},
+            dataRes: _this3._getData(function () {
+              return dataRes.then(function (props) {
+                return handleData(props);
+              });
+            })
+          }));
+        }
+
         return _this3._getData(function () {
-          return Component.__N_SSG ? _this3._getStaticData(as) : Component.__N_SSP ? _this3._getServerData(as) : _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+          return _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
           {
             pathname: pathname,
             query: query,
             asPath: as
           });
         }).then(function (props) {
-          routeInfo.props = props;
-          _this3.components[route] = routeInfo;
-          return routeInfo;
+          return handleData(props);
         });
       })["catch"](function (err) {
         return new _Promise(function (resolve) {
Diff for link.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.800e2531cee4c9c783e6.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.52bdb9a42710fb5a7793.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.800e2531cee4c9c783e6.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for withRouter.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.800e2531cee4c9c783e6.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.52bdb9a42710fb5a7793.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.800e2531cee4c9c783e6.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 12.7s 12.3s -343ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +6.58 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.18 kB ⚠️ +66 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..b50f.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..9aa3.js gzip N/A 13.7 kB N/A
Overall change 67.3 kB 67.5 kB ⚠️ +195 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.17 kB ⚠️ +47 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB N/A N/A
framework.HA..dule.js gzip 39.1 kB 39.1 kB
de003c3a9d30..dule.js gzip N/A 12.5 kB N/A
Overall change 61.9 kB 62.1 kB ⚠️ +166 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Serverless bundles Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_error.js gzip 46.5 kB 46.6 kB ⚠️ +102 B
404.html gzip 1.43 kB 1.44 kB ⚠️ +10 B
hooks.html gzip 1.07 kB 1.07 kB ⚠️ +9 B
index.js gzip 46.5 kB 46.6 kB ⚠️ +93 B
link.js gzip 72 kB 72.4 kB ⚠️ +463 B
routerDirect.js gzip 70.2 kB 70.7 kB ⚠️ +437 B
withRouter.js gzip 70 kB 70.5 kB ⚠️ +444 B
Overall change 308 kB 309 kB ⚠️ +1.56 kB

Commit: 524f4b0

@ijjk
Copy link
Member Author

ijjk commented Feb 7, 2020

Stats from current PR

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 11.3s 11.8s ⚠️ +492ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +6.42 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.18 kB ⚠️ +66 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..b50f.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..a598.js gzip N/A 13.7 kB N/A
Overall change 67.3 kB 67.5 kB ⚠️ +182 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.17 kB ⚠️ +47 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB 12.5 kB ⚠️ +99 B
framework.HA..dule.js gzip 39.1 kB 39.1 kB
Overall change 61.9 kB 62.1 kB ⚠️ +146 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Rendered Page Sizes Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
index.html gzip 1.02 kB 1.03 kB ⚠️ +12 B
link.html gzip 1.03 kB 1.04 kB ⚠️ +10 B
withRouter.html gzip 1.02 kB 1.03 kB ⚠️ +12 B
Overall change 3.07 kB 3.11 kB ⚠️ +34 B

Diffs

Diff for link.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.155e738e9232d2fd6ba9.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.03a6da80bbac368d615e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.155e738e9232d2fd6ba9.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for index.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.155e738e9232d2fd6ba9.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.03a6da80bbac368d615e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.155e738e9232d2fd6ba9.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for main-HASH.module.js
@@ -284,11 +284,22 @@ class Container extends _react.default.Component {
   componentDidMount() {
     this.scrollToHash();
 
-    if (false) {} // If page was exported and has a querystring
+    if (false) {} // call router.replace to trigger data fetching while
+    // the fallback is shown
+
+
+    if (data.isFallback) {
+      router.replace({
+        pathname: page,
+        query: (0, _extends2.default)({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))
+      }, asPath, {
+        _h: 1
+      });
+    } // If page was exported and has a querystring
     // If it's a dynamic route or has a querystring
 
 
-    if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+    if (!data.isFallback && router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
       // update query on mount for exported pages
       router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2.default)({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
         // WARNING: `_h` is an internal option for handing Next.js
@@ -411,6 +422,12 @@ var _default = async function _default(_temp) {
   };
 
   if (true) {
+    // kick off static data request now so it's in the cache
+    // when we re-render post-hydration
+    if (data.isFallback) {
+      router._getStaticData(asPath).catch(() => {});
+    }
+
     render(renderCtx);
     return emitter;
   }
Diff for main-HASH.js
@@ -379,11 +379,22 @@ function (_react$default$Compon) {
     value: function componentDidMount() {
       this.scrollToHash();
 
-      if (false) {} // If page was exported and has a querystring
+      if (false) {} // call router.replace to trigger data fetching while
+      // the fallback is shown
+
+
+      if (data.isFallback) {
+        router.replace({
+          pathname: page,
+          query: (0, _extends2["default"])({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))
+        }, asPath, {
+          _h: 1
+        });
+      } // If page was exported and has a querystring
       // If it's a dynamic route or has a querystring
 
 
-      if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+      if (!data.isFallback && router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
         // update query on mount for exported pages
         router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2["default"])({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
           // WARNING: `_h` is an internal option for handing Next.js
@@ -543,12 +554,18 @@ var _default = function _default(_temp) {
 
           if (false) {}
 
+          // kick off static data request now so it's in the cache
+          // when we re-render post-hydration
+          if (data.isFallback) {
+            router._getStaticData(asPath)["catch"](function () {});
+          }
+
           render(renderCtx);
           return _context.abrupt("return", emitter);
 
-        case 32:
+        case 33:
           if (true) {
-            _context.next = 34;
+            _context.next = 35;
             break;
           }
 
@@ -558,7 +575,7 @@ var _default = function _default(_temp) {
             renderCtx: renderCtx
           });
 
-        case 34:
+        case 35:
         case "end":
           return _context.stop();
       }
Diff for de003c3a9d30..29.module.js
@@ -1765,28 +1765,52 @@ class Router {
       Router.events.emit('routeChangeStart', as); // If shallow is true and the route exists in the router cache we reuse the previous result
 
       this.getRouteInfo(route, pathname, query, as, shallow).then(routeInfo => {
-        var {
-          error
-        } = routeInfo;
+        var doRouteChange = (routeInfo, emit) => {
+          var {
+            error
+          } = routeInfo;
 
-        if (error && error.cancelled) {
-          return resolve(false);
-        }
+          if (error && error.cancelled) {
+            return resolve(false);
+          }
 
-        Router.events.emit('beforeHistoryChange', as);
-        this.changeState(method, url, addBasePath(as), options);
+          Router.events.emit('beforeHistoryChange', as);
+          this.changeState(method, url, addBasePath(as), options);
 
-        if (false) { var appComp; }
+          if (false) { var appComp; }
 
-        this.set(route, pathname, query, as, routeInfo);
+          this.set(route, pathname, query, as, routeInfo);
 
-        if (error) {
-          Router.events.emit('routeChangeError', error, as);
-          throw error;
-        }
+          if (emit) {
+            if (error) {
+              Router.events.emit('routeChangeError', error, as);
+              throw error;
+            }
 
-        Router.events.emit('routeChangeComplete', as);
-        return resolve(true);
+            Router.events.emit('routeChangeComplete', as);
+            resolve(true);
+          }
+        };
+
+        if (routeInfo.dataRes) {
+          var dataRes = routeInfo.dataRes; // to prevent a flash of the fallback page we delay showing it for
+          // 110ms and race the timeout with the data response. If the data
+          // beats the timeout we skip showing the fallback
+
+          _Promise.race([new _Promise(resolve => setTimeout(() => resolve(false), 110)), dataRes]).then(data => {
+            if (!data) {
+              // data didn't win the race, show fallback
+              doRouteChange(routeInfo, false);
+            }
+
+            return dataRes;
+          }).then(finalData => {
+            // render with the data and complete route change
+            doRouteChange(finalData, true);
+          }, reject);
+        } else {
+          doRouteChange(routeInfo, true);
+        }
       }, reject);
     });
   }
@@ -1830,16 +1854,29 @@ class Router {
 
       if (false) { var isValidElementType; }
 
-      return this._getData(() => Component.__N_SSG ? this._getStaticData(as) : Component.__N_SSP ? this._getServerData(as) : this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+      var isSSG = Component.__N_SSG;
+      var isSSP = Component.__N_SSP;
+
+      var handleData = props => {
+        routeInfo.props = props;
+        this.components[route] = routeInfo;
+        return routeInfo;
+      }; // resolve with fallback routeInfo and promise for data
+
+
+      if (isSSG || isSSP) {
+        return _Promise.resolve(_Object$assign(_Object$assign({}, routeInfo), {
+          props: {},
+          dataRes: this._getData(() => (isSSG ? this._getStaticData(as) : this._getServerData(as)).then(props => handleData(props)))
+        }));
+      }
+
+      return this._getData(() => this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
       {
         pathname,
         query,
         asPath: as
-      })).then(props => {
-        routeInfo.props = props;
-        this.components[route] = routeInfo;
-        return routeInfo;
-      });
+      })).then(props => handleData(props));
     }).catch(err => {
       return new _Promise(resolve => {
         if (err.code === 'PAGE_LOAD_ERROR') {
Diff for de003c3a9d30..686f3d49e.js
@@ -1498,27 +1498,55 @@ function () {
         Router.events.emit('routeChangeStart', as); // If shallow is true and the route exists in the router cache we reuse the previous result
 
         _this2.getRouteInfo(route, pathname, query, as, shallow).then(function (routeInfo) {
-          var error = routeInfo.error;
+          var doRouteChange = function doRouteChange(routeInfo, emit) {
+            var error = routeInfo.error;
 
-          if (error && error.cancelled) {
-            return resolve(false);
-          }
+            if (error && error.cancelled) {
+              return resolve(false);
+            }
 
-          Router.events.emit('beforeHistoryChange', as);
+            Router.events.emit('beforeHistoryChange', as);
 
-          _this2.changeState(method, url, addBasePath(as), options);
+            _this2.changeState(method, url, addBasePath(as), options);
 
-          if (false) { var appComp; }
+            if (false) { var appComp; }
 
-          _this2.set(route, pathname, query, as, routeInfo);
+            _this2.set(route, pathname, query, as, routeInfo);
 
-          if (error) {
-            Router.events.emit('routeChangeError', error, as);
-            throw error;
-          }
+            if (emit) {
+              if (error) {
+                Router.events.emit('routeChangeError', error, as);
+                throw error;
+              }
 
-          Router.events.emit('routeChangeComplete', as);
-          return resolve(true);
+              Router.events.emit('routeChangeComplete', as);
+              resolve(true);
+            }
+          };
+
+          if (routeInfo.dataRes) {
+            var dataRes = routeInfo.dataRes; // to prevent a flash of the fallback page we delay showing it for
+            // 110ms and race the timeout with the data response. If the data
+            // beats the timeout we skip showing the fallback
+
+            _Promise.race([new _Promise(function (resolve) {
+              return setTimeout(function () {
+                return resolve(false);
+              }, 110);
+            }), dataRes]).then(function (data) {
+              if (!data) {
+                // data didn't win the race, show fallback
+                doRouteChange(routeInfo, false);
+              }
+
+              return dataRes;
+            }).then(function (finalData) {
+              // render with the data and complete route change
+              doRouteChange(finalData, true);
+            }, reject);
+          } else {
+            doRouteChange(routeInfo, true);
+          }
         }, reject);
       });
     }
@@ -1566,17 +1594,36 @@ function () {
 
         if (false) { var _require, isValidElementType; }
 
+        var isSSG = Component.__N_SSG;
+        var isSSP = Component.__N_SSP;
+
+        var handleData = function handleData(props) {
+          routeInfo.props = props;
+          _this3.components[route] = routeInfo;
+          return routeInfo;
+        }; // resolve with fallback routeInfo and promise for data
+
+
+        if (isSSG || isSSP) {
+          return _Promise.resolve(_Object$assign(_Object$assign({}, routeInfo), {
+            props: {},
+            dataRes: _this3._getData(function () {
+              return (isSSG ? _this3._getStaticData(as) : _this3._getServerData(as)).then(function (props) {
+                return handleData(props);
+              });
+            })
+          }));
+        }
+
         return _this3._getData(function () {
-          return Component.__N_SSG ? _this3._getStaticData(as) : Component.__N_SSP ? _this3._getServerData(as) : _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+          return _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
           {
             pathname: pathname,
             query: query,
             asPath: as
           });
         }).then(function (props) {
-          routeInfo.props = props;
-          _this3.components[route] = routeInfo;
-          return routeInfo;
+          return handleData(props);
         });
       })["catch"](function (err) {
         return new _Promise(function (resolve) {
Diff for withRouter.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.155e738e9232d2fd6ba9.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.03a6da80bbac368d615e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.155e738e9232d2fd6ba9.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-c5e38e4e5d8628191101.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-8c9c5447a6a20d8a05e5.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 11.7s 12.2s ⚠️ +519ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +6.42 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.18 kB ⚠️ +66 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..b50f.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..a598.js gzip N/A 13.7 kB N/A
Overall change 67.3 kB 67.5 kB ⚠️ +182 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.17 kB ⚠️ +47 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB N/A N/A
framework.HA..dule.js gzip 39.1 kB 39.1 kB
de003c3a9d30..dule.js gzip N/A 12.5 kB N/A
Overall change 61.9 kB 62.1 kB ⚠️ +146 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Serverless bundles Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_error.js gzip 46.5 kB 46.6 kB ⚠️ +100 B
404.html gzip 1.43 kB 1.45 kB ⚠️ +12 B
hooks.html gzip 1.07 kB 1.07 kB ⚠️ +9 B
index.js gzip 46.5 kB 46.6 kB ⚠️ +90 B
link.js gzip 72 kB 72.5 kB ⚠️ +470 B
routerDirect.js gzip 70.2 kB 70.7 kB ⚠️ +449 B
withRouter.js gzip 70 kB 70.5 kB ⚠️ +454 B
Overall change 308 kB 309 kB ⚠️ +1.58 kB

Commit: cebfcbc

packages/next/client/index.js Outdated Show resolved Hide resolved
packages/next/client/index.js Outdated Show resolved Hide resolved
@ijjk
Copy link
Member Author

ijjk commented Feb 7, 2020

Stats from current PR

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 10.9s 11.1s ⚠️ +148ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +7.35 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.19 kB ⚠️ +71 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..b50f.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..e781.js gzip N/A 13.8 kB N/A
Overall change 67.3 kB 67.6 kB ⚠️ +227 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.18 kB ⚠️ +60 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB 12.5 kB ⚠️ +149 B
framework.HA..dule.js gzip 39.1 kB 39.1 kB
Overall change 61.9 kB 62.1 kB ⚠️ +209 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Rendered Page Sizes Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
index.html gzip 1.02 kB 1.03 kB ⚠️ +12 B
link.html gzip 1.03 kB 1.04 kB ⚠️ +11 B
withRouter.html gzip 1.02 kB 1.03 kB ⚠️ +13 B
Overall change 3.07 kB 3.11 kB ⚠️ +36 B

Diffs

Diff for index.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-f3c133a2cdd3696a91f1.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.94ffdad0a29f46cabb19.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-4d0e0a957f75fa22dc91.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-f3c133a2cdd3696a91f1.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for main-HASH.module.js
@@ -240,8 +240,12 @@ var {
   buildId,
   assetPrefix,
   runtimeConfig,
-  dynamicIds
+  dynamicIds,
+  isFallback
 } = data;
+
+var fallbackDataPromise = _Promise.resolve();
+
 var prefix = assetPrefix || ''; // With dynamic assetPrefix it's no longer possible to set assetPrefix at the build time
 // So, this is how we do it in the client side at runtime
 
@@ -284,20 +288,25 @@ class Container extends _react.default.Component {
   componentDidMount() {
     this.scrollToHash();
 
-    if (false) {} // If page was exported and has a querystring
-    // If it's a dynamic route or has a querystring
-
-
-    if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
-      // update query on mount for exported pages
-      router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2.default)({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
-        // WARNING: `_h` is an internal option for handing Next.js
-        // client-side hydration. Your app should _never_ use this property.
-        // It may change at any time without notice.
-        _h: 1,
-        shallow: true
-      });
-    }
+    if (false) {} // wait for fallbackDataPromise so we don't kick off an extra
+    // request if one is pending
+
+
+    fallbackDataPromise.then(() => {
+      // If page was exported and has a querystring
+      // If it's a dynamic route or has a querystring
+      // if it's a fallback page
+      if (router.isSsr && (isFallback || data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+        // update query on mount for exported pages
+        router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2.default)({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
+          // WARNING: `_h` is an internal option for handing Next.js
+          // client-side hydration. Your app should _never_ use this property.
+          // It may change at any time without notice.
+          _h: 1,
+          shallow: !isFallback
+        });
+      }
+    });
 
     if (undefined) {
       window.__NEXT_HYDRATED = true;
@@ -411,6 +420,12 @@ var _default = async function _default(_temp) {
   };
 
   if (true) {
+    // kick off static data request now so it's in the cache
+    // when we re-render post-hydration
+    if (data.isFallback) {
+      fallbackDataPromise = router._getStaticData(asPath).catch(() => {});
+    }
+
     render(renderCtx);
     return emitter;
   }
Diff for main-HASH.js
@@ -320,7 +320,11 @@ var props = data.props,
     buildId = data.buildId,
     assetPrefix = data.assetPrefix,
     runtimeConfig = data.runtimeConfig,
-    dynamicIds = data.dynamicIds;
+    dynamicIds = data.dynamicIds,
+    isFallback = data.isFallback;
+
+var fallbackDataPromise = _Promise.resolve();
+
 var prefix = assetPrefix || ''; // With dynamic assetPrefix it's no longer possible to set assetPrefix at the build time
 // So, this is how we do it in the client side at runtime
 
@@ -379,20 +383,25 @@ function (_react$default$Compon) {
     value: function componentDidMount() {
       this.scrollToHash();
 
-      if (false) {} // If page was exported and has a querystring
-      // If it's a dynamic route or has a querystring
-
-
-      if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
-        // update query on mount for exported pages
-        router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2["default"])({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
-          // WARNING: `_h` is an internal option for handing Next.js
-          // client-side hydration. Your app should _never_ use this property.
-          // It may change at any time without notice.
-          _h: 1,
-          shallow: true
-        });
-      }
+      if (false) {} // wait for fallbackDataPromise so we don't kick off an extra
+      // request if one is pending
+
+
+      fallbackDataPromise.then(function () {
+        // If page was exported and has a querystring
+        // If it's a dynamic route or has a querystring
+        // if it's a fallback page
+        if (router.isSsr && (isFallback || data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+          // update query on mount for exported pages
+          router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2["default"])({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
+            // WARNING: `_h` is an internal option for handing Next.js
+            // client-side hydration. Your app should _never_ use this property.
+            // It may change at any time without notice.
+            _h: 1,
+            shallow: !isFallback
+          });
+        }
+      });
 
       if (undefined) {
         window.__NEXT_HYDRATED = true;
@@ -543,12 +552,18 @@ var _default = function _default(_temp) {
 
           if (false) {}
 
+          // kick off static data request now so it's in the cache
+          // when we re-render post-hydration
+          if (data.isFallback) {
+            fallbackDataPromise = router._getStaticData(asPath)["catch"](function () {});
+          }
+
           render(renderCtx);
           return _context.abrupt("return", emitter);
 
-        case 32:
+        case 33:
           if (true) {
-            _context.next = 34;
+            _context.next = 35;
             break;
           }
 
@@ -558,7 +573,7 @@ var _default = function _default(_temp) {
             renderCtx: renderCtx
           });
 
-        case 34:
+        case 35:
         case "end":
           return _context.stop();
       }
Diff for de003c3a9d30..29.module.js
@@ -1480,16 +1480,14 @@ var fetchNextData = (pathname, query, cb) => {
     query
   })).then(res => {
     if (!res.ok) {
-      throw new Error("Failed to load static props");
+      var error = new Error("Failed to load static props");
+      error.statusCode = res.status;
+      throw error;
     }
 
     return res.json();
   }).then(data => {
     return cb ? cb(data) : data;
-  }).catch(err => {
-    ;
-    err.code = 'PAGE_LOAD_ERROR';
-    throw err;
   });
 };
 
@@ -1765,28 +1763,57 @@ class Router {
       Router.events.emit('routeChangeStart', as); // If shallow is true and the route exists in the router cache we reuse the previous result
 
       this.getRouteInfo(route, pathname, query, as, shallow).then(routeInfo => {
-        var {
-          error
-        } = routeInfo;
+        var emitHistory = false;
 
-        if (error && error.cancelled) {
-          return resolve(false);
-        }
+        var doRouteChange = (routeInfo, complete) => {
+          var {
+            error
+          } = routeInfo;
 
-        Router.events.emit('beforeHistoryChange', as);
-        this.changeState(method, url, addBasePath(as), options);
+          if (error && error.cancelled) {
+            return resolve(false);
+          }
 
-        if (false) { var appComp; }
+          if (!emitHistory) {
+            emitHistory = true;
+            Router.events.emit('beforeHistoryChange', as);
+            this.changeState(method, url, addBasePath(as), options);
+          }
 
-        this.set(route, pathname, query, as, routeInfo);
+          if (false) { var appComp; }
 
-        if (error) {
-          Router.events.emit('routeChangeError', error, as);
-          throw error;
-        }
+          this.set(route, pathname, query, as, routeInfo);
 
-        Router.events.emit('routeChangeComplete', as);
-        return resolve(true);
+          if (complete) {
+            if (error) {
+              Router.events.emit('routeChangeError', error, as);
+              throw error;
+            }
+
+            Router.events.emit('routeChangeComplete', as);
+            resolve(true);
+          }
+        };
+
+        if (routeInfo.dataRes) {
+          var dataRes = routeInfo.dataRes; // to prevent a flash of the fallback page we delay showing it for
+          // 110ms and race the timeout with the data response. If the data
+          // beats the timeout we skip showing the fallback
+
+          _Promise.race([new _Promise(resolve => setTimeout(() => resolve(false), 110)), dataRes]).then(data => {
+            if (!data) {
+              // data didn't win the race, show fallback
+              doRouteChange(routeInfo, false);
+            }
+
+            return dataRes;
+          }).then(finalData => {
+            // render with the data and complete route change
+            doRouteChange(finalData, true);
+          }, reject);
+        } else {
+          doRouteChange(routeInfo, true);
+        }
       }, reject);
     });
   }
@@ -1830,16 +1857,40 @@ class Router {
 
       if (false) { var isValidElementType; }
 
-      return this._getData(() => Component.__N_SSG ? this._getStaticData(as) : Component.__N_SSP ? this._getServerData(as) : this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+      var isSSG = Component.__N_SSG;
+      var isSSP = Component.__N_SSP;
+
+      var handleData = props => {
+        routeInfo.props = props;
+        this.components[route] = routeInfo;
+        return routeInfo;
+      }; // resolve with fallback routeInfo and promise for data
+
+
+      if (isSSG || isSSP) {
+        var dataMethod = () => isSSG ? this._getStaticData(as) : this._getServerData(as);
+
+        var retry = error => {
+          if (error.statusCode === 404) {
+            throw error;
+          }
+
+          return dataMethod();
+        };
+
+        return _Promise.resolve(_Object$assign(_Object$assign({}, routeInfo), {
+          props: {},
+          dataRes: this._getData(() => dataMethod() // we retry for data twice unless we get a 404
+          .catch(retry).catch(retry).then(props => handleData(props)))
+        }));
+      }
+
+      return this._getData(() => this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
       {
         pathname,
         query,
         asPath: as
-      })).then(props => {
-        routeInfo.props = props;
-        this.components[route] = routeInfo;
-        return routeInfo;
-      });
+      })).then(props => handleData(props));
     }).catch(err => {
       return new _Promise(resolve => {
         if (err.code === 'PAGE_LOAD_ERROR') {
Diff for de003c3a9d30..686f3d49e.js
@@ -1200,16 +1200,14 @@ var fetchNextData = function fetchNextData(pathname, query, cb) {
     query: query
   })).then(function (res) {
     if (!res.ok) {
-      throw new Error("Failed to load static props");
+      var error = new Error("Failed to load static props");
+      error.statusCode = res.status;
+      throw error;
     }
 
     return res.json();
   }).then(function (data) {
     return cb ? cb(data) : data;
-  })["catch"](function (err) {
-    ;
-    err.code = 'PAGE_LOAD_ERROR';
-    throw err;
   });
 };
 
@@ -1498,27 +1496,60 @@ function () {
         Router.events.emit('routeChangeStart', as); // If shallow is true and the route exists in the router cache we reuse the previous result
 
         _this2.getRouteInfo(route, pathname, query, as, shallow).then(function (routeInfo) {
-          var error = routeInfo.error;
+          var emitHistory = false;
 
-          if (error && error.cancelled) {
-            return resolve(false);
-          }
+          var doRouteChange = function doRouteChange(routeInfo, complete) {
+            var error = routeInfo.error;
 
-          Router.events.emit('beforeHistoryChange', as);
+            if (error && error.cancelled) {
+              return resolve(false);
+            }
 
-          _this2.changeState(method, url, addBasePath(as), options);
+            if (!emitHistory) {
+              emitHistory = true;
+              Router.events.emit('beforeHistoryChange', as);
 
-          if (false) { var appComp; }
+              _this2.changeState(method, url, addBasePath(as), options);
+            }
 
-          _this2.set(route, pathname, query, as, routeInfo);
+            if (false) { var appComp; }
 
-          if (error) {
-            Router.events.emit('routeChangeError', error, as);
-            throw error;
-          }
+            _this2.set(route, pathname, query, as, routeInfo);
 
-          Router.events.emit('routeChangeComplete', as);
-          return resolve(true);
+            if (complete) {
+              if (error) {
+                Router.events.emit('routeChangeError', error, as);
+                throw error;
+              }
+
+              Router.events.emit('routeChangeComplete', as);
+              resolve(true);
+            }
+          };
+
+          if (routeInfo.dataRes) {
+            var dataRes = routeInfo.dataRes; // to prevent a flash of the fallback page we delay showing it for
+            // 110ms and race the timeout with the data response. If the data
+            // beats the timeout we skip showing the fallback
+
+            _Promise.race([new _Promise(function (resolve) {
+              return setTimeout(function () {
+                return resolve(false);
+              }, 110);
+            }), dataRes]).then(function (data) {
+              if (!data) {
+                // data didn't win the race, show fallback
+                doRouteChange(routeInfo, false);
+              }
+
+              return dataRes;
+            }).then(function (finalData) {
+              // render with the data and complete route change
+              doRouteChange(finalData, true);
+            }, reject);
+          } else {
+            doRouteChange(routeInfo, true);
+          }
         }, reject);
       });
     }
@@ -1566,17 +1597,49 @@ function () {
 
         if (false) { var _require, isValidElementType; }
 
+        var isSSG = Component.__N_SSG;
+        var isSSP = Component.__N_SSP;
+
+        var handleData = function handleData(props) {
+          routeInfo.props = props;
+          _this3.components[route] = routeInfo;
+          return routeInfo;
+        }; // resolve with fallback routeInfo and promise for data
+
+
+        if (isSSG || isSSP) {
+          var dataMethod = function dataMethod() {
+            return isSSG ? _this3._getStaticData(as) : _this3._getServerData(as);
+          };
+
+          var retry = function retry(error) {
+            if (error.statusCode === 404) {
+              throw error;
+            }
+
+            return dataMethod();
+          };
+
+          return _Promise.resolve(_Object$assign(_Object$assign({}, routeInfo), {
+            props: {},
+            dataRes: _this3._getData(function () {
+              return dataMethod() // we retry for data twice unless we get a 404
+              ["catch"](retry)["catch"](retry).then(function (props) {
+                return handleData(props);
+              });
+            })
+          }));
+        }
+
         return _this3._getData(function () {
-          return Component.__N_SSG ? _this3._getStaticData(as) : Component.__N_SSP ? _this3._getServerData(as) : _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+          return _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
           {
             pathname: pathname,
             query: query,
             asPath: as
           });
         }).then(function (props) {
-          routeInfo.props = props;
-          _this3.components[route] = routeInfo;
-          return routeInfo;
+          return handleData(props);
         });
       })["catch"](function (err) {
         return new _Promise(function (resolve) {
Diff for link.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-f3c133a2cdd3696a91f1.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.94ffdad0a29f46cabb19.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-4d0e0a957f75fa22dc91.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-f3c133a2cdd3696a91f1.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for withRouter.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-f3c133a2cdd3696a91f1.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.94ffdad0a29f46cabb19.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-4d0e0a957f75fa22dc91.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-f3c133a2cdd3696a91f1.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 11.5s 11.5s -24ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +7.35 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.19 kB ⚠️ +71 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..b50f.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..e781.js gzip N/A 13.8 kB N/A
Overall change 67.3 kB 67.6 kB ⚠️ +227 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.18 kB ⚠️ +60 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB N/A N/A
framework.HA..dule.js gzip 39.1 kB 39.1 kB
de003c3a9d30..dule.js gzip N/A 12.5 kB N/A
Overall change 61.9 kB 62.1 kB ⚠️ +209 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Serverless bundles Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_error.js gzip 46.5 kB 46.6 kB ⚠️ +101 B
404.html gzip 1.43 kB 1.45 kB ⚠️ +12 B
hooks.html gzip 1.07 kB 1.08 kB ⚠️ +11 B
index.js gzip 46.5 kB 46.6 kB ⚠️ +93 B
link.js gzip 72 kB 72.6 kB ⚠️ +583 B
routerDirect.js gzip 70.2 kB 70.8 kB ⚠️ +560 B
withRouter.js gzip 70 kB 70.6 kB ⚠️ +562 B
Overall change 308 kB 310 kB ⚠️ +1.92 kB

Commit: 66e7e51

@ijjk
Copy link
Member Author

ijjk commented Feb 7, 2020

Stats from current PR

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 9.6s 9.8s ⚠️ +182ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +7.17 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.13 kB ⚠️ +16 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..b50f.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..e781.js gzip N/A 13.8 kB N/A
Overall change 67.3 kB 67.5 kB ⚠️ +172 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.13 kB ⚠️ +14 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB 12.5 kB ⚠️ +149 B
framework.HA..dule.js gzip 39.1 kB 39.1 kB
Overall change 61.9 kB 62.1 kB ⚠️ +163 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Rendered Page Sizes Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
index.html gzip 1.02 kB 1.03 kB ⚠️ +13 B
link.html gzip 1.03 kB 1.04 kB ⚠️ +10 B
withRouter.html gzip 1.02 kB 1.03 kB ⚠️ +13 B
Overall change 3.07 kB 3.11 kB ⚠️ +36 B

Diffs

Diff for index.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-68b2787ed48eca9ea0a4.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.94ffdad0a29f46cabb19.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-92a5af642b825be192be.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-68b2787ed48eca9ea0a4.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for main-HASH.module.js
@@ -240,7 +240,8 @@ var {
   buildId,
   assetPrefix,
   runtimeConfig,
-  dynamicIds
+  dynamicIds,
+  isFallback
 } = data;
 var prefix = assetPrefix || ''; // With dynamic assetPrefix it's no longer possible to set assetPrefix at the build time
 // So, this is how we do it in the client side at runtime
@@ -286,16 +287,17 @@ class Container extends _react.default.Component {
 
     if (false) {} // If page was exported and has a querystring
     // If it's a dynamic route or has a querystring
+    // if it's a fallback page
 
 
-    if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+    if (router.isSsr && (isFallback || data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
       // update query on mount for exported pages
       router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2.default)({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
         // WARNING: `_h` is an internal option for handing Next.js
         // client-side hydration. Your app should _never_ use this property.
         // It may change at any time without notice.
         _h: 1,
-        shallow: true
+        shallow: !isFallback
       });
     }
Diff for main-HASH.js
@@ -320,7 +320,8 @@ var props = data.props,
     buildId = data.buildId,
     assetPrefix = data.assetPrefix,
     runtimeConfig = data.runtimeConfig,
-    dynamicIds = data.dynamicIds;
+    dynamicIds = data.dynamicIds,
+    isFallback = data.isFallback;
 var prefix = assetPrefix || ''; // With dynamic assetPrefix it's no longer possible to set assetPrefix at the build time
 // So, this is how we do it in the client side at runtime
 
@@ -381,16 +382,17 @@ function (_react$default$Compon) {
 
       if (false) {} // If page was exported and has a querystring
       // If it's a dynamic route or has a querystring
+      // if it's a fallback page
 
 
-      if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+      if (router.isSsr && (isFallback || data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
         // update query on mount for exported pages
         router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2["default"])({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
           // WARNING: `_h` is an internal option for handing Next.js
           // client-side hydration. Your app should _never_ use this property.
           // It may change at any time without notice.
           _h: 1,
-          shallow: true
+          shallow: !isFallback
         });
       }
Diff for de003c3a9d30..29.module.js
@@ -1480,16 +1480,14 @@ var fetchNextData = (pathname, query, cb) => {
     query
   })).then(res => {
     if (!res.ok) {
-      throw new Error("Failed to load static props");
+      var error = new Error("Failed to load static props");
+      error.statusCode = res.status;
+      throw error;
     }
 
     return res.json();
   }).then(data => {
     return cb ? cb(data) : data;
-  }).catch(err => {
-    ;
-    err.code = 'PAGE_LOAD_ERROR';
-    throw err;
   });
 };
 
@@ -1765,28 +1763,57 @@ class Router {
       Router.events.emit('routeChangeStart', as); // If shallow is true and the route exists in the router cache we reuse the previous result
 
       this.getRouteInfo(route, pathname, query, as, shallow).then(routeInfo => {
-        var {
-          error
-        } = routeInfo;
+        var emitHistory = false;
 
-        if (error && error.cancelled) {
-          return resolve(false);
-        }
+        var doRouteChange = (routeInfo, complete) => {
+          var {
+            error
+          } = routeInfo;
 
-        Router.events.emit('beforeHistoryChange', as);
-        this.changeState(method, url, addBasePath(as), options);
+          if (error && error.cancelled) {
+            return resolve(false);
+          }
 
-        if (false) { var appComp; }
+          if (!emitHistory) {
+            emitHistory = true;
+            Router.events.emit('beforeHistoryChange', as);
+            this.changeState(method, url, addBasePath(as), options);
+          }
 
-        this.set(route, pathname, query, as, routeInfo);
+          if (false) { var appComp; }
 
-        if (error) {
-          Router.events.emit('routeChangeError', error, as);
-          throw error;
-        }
+          this.set(route, pathname, query, as, routeInfo);
 
-        Router.events.emit('routeChangeComplete', as);
-        return resolve(true);
+          if (complete) {
+            if (error) {
+              Router.events.emit('routeChangeError', error, as);
+              throw error;
+            }
+
+            Router.events.emit('routeChangeComplete', as);
+            resolve(true);
+          }
+        };
+
+        if (routeInfo.dataRes) {
+          var dataRes = routeInfo.dataRes; // to prevent a flash of the fallback page we delay showing it for
+          // 110ms and race the timeout with the data response. If the data
+          // beats the timeout we skip showing the fallback
+
+          _Promise.race([new _Promise(resolve => setTimeout(() => resolve(false), 110)), dataRes]).then(data => {
+            if (!data) {
+              // data didn't win the race, show fallback
+              doRouteChange(routeInfo, false);
+            }
+
+            return dataRes;
+          }).then(finalData => {
+            // render with the data and complete route change
+            doRouteChange(finalData, true);
+          }, reject);
+        } else {
+          doRouteChange(routeInfo, true);
+        }
       }, reject);
     });
   }
@@ -1830,16 +1857,40 @@ class Router {
 
       if (false) { var isValidElementType; }
 
-      return this._getData(() => Component.__N_SSG ? this._getStaticData(as) : Component.__N_SSP ? this._getServerData(as) : this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+      var isSSG = Component.__N_SSG;
+      var isSSP = Component.__N_SSP;
+
+      var handleData = props => {
+        routeInfo.props = props;
+        this.components[route] = routeInfo;
+        return routeInfo;
+      }; // resolve with fallback routeInfo and promise for data
+
+
+      if (isSSG || isSSP) {
+        var dataMethod = () => isSSG ? this._getStaticData(as) : this._getServerData(as);
+
+        var retry = error => {
+          if (error.statusCode === 404) {
+            throw error;
+          }
+
+          return dataMethod();
+        };
+
+        return _Promise.resolve(_Object$assign(_Object$assign({}, routeInfo), {
+          props: {},
+          dataRes: this._getData(() => dataMethod() // we retry for data twice unless we get a 404
+          .catch(retry).catch(retry).then(props => handleData(props)))
+        }));
+      }
+
+      return this._getData(() => this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
       {
         pathname,
         query,
         asPath: as
-      })).then(props => {
-        routeInfo.props = props;
-        this.components[route] = routeInfo;
-        return routeInfo;
-      });
+      })).then(props => handleData(props));
     }).catch(err => {
       return new _Promise(resolve => {
         if (err.code === 'PAGE_LOAD_ERROR') {
Diff for de003c3a9d30..686f3d49e.js
@@ -1200,16 +1200,14 @@ var fetchNextData = function fetchNextData(pathname, query, cb) {
     query: query
   })).then(function (res) {
     if (!res.ok) {
-      throw new Error("Failed to load static props");
+      var error = new Error("Failed to load static props");
+      error.statusCode = res.status;
+      throw error;
     }
 
     return res.json();
   }).then(function (data) {
     return cb ? cb(data) : data;
-  })["catch"](function (err) {
-    ;
-    err.code = 'PAGE_LOAD_ERROR';
-    throw err;
   });
 };
 
@@ -1498,27 +1496,60 @@ function () {
         Router.events.emit('routeChangeStart', as); // If shallow is true and the route exists in the router cache we reuse the previous result
 
         _this2.getRouteInfo(route, pathname, query, as, shallow).then(function (routeInfo) {
-          var error = routeInfo.error;
+          var emitHistory = false;
 
-          if (error && error.cancelled) {
-            return resolve(false);
-          }
+          var doRouteChange = function doRouteChange(routeInfo, complete) {
+            var error = routeInfo.error;
 
-          Router.events.emit('beforeHistoryChange', as);
+            if (error && error.cancelled) {
+              return resolve(false);
+            }
 
-          _this2.changeState(method, url, addBasePath(as), options);
+            if (!emitHistory) {
+              emitHistory = true;
+              Router.events.emit('beforeHistoryChange', as);
 
-          if (false) { var appComp; }
+              _this2.changeState(method, url, addBasePath(as), options);
+            }
 
-          _this2.set(route, pathname, query, as, routeInfo);
+            if (false) { var appComp; }
 
-          if (error) {
-            Router.events.emit('routeChangeError', error, as);
-            throw error;
-          }
+            _this2.set(route, pathname, query, as, routeInfo);
 
-          Router.events.emit('routeChangeComplete', as);
-          return resolve(true);
+            if (complete) {
+              if (error) {
+                Router.events.emit('routeChangeError', error, as);
+                throw error;
+              }
+
+              Router.events.emit('routeChangeComplete', as);
+              resolve(true);
+            }
+          };
+
+          if (routeInfo.dataRes) {
+            var dataRes = routeInfo.dataRes; // to prevent a flash of the fallback page we delay showing it for
+            // 110ms and race the timeout with the data response. If the data
+            // beats the timeout we skip showing the fallback
+
+            _Promise.race([new _Promise(function (resolve) {
+              return setTimeout(function () {
+                return resolve(false);
+              }, 110);
+            }), dataRes]).then(function (data) {
+              if (!data) {
+                // data didn't win the race, show fallback
+                doRouteChange(routeInfo, false);
+              }
+
+              return dataRes;
+            }).then(function (finalData) {
+              // render with the data and complete route change
+              doRouteChange(finalData, true);
+            }, reject);
+          } else {
+            doRouteChange(routeInfo, true);
+          }
         }, reject);
       });
     }
@@ -1566,17 +1597,49 @@ function () {
 
         if (false) { var _require, isValidElementType; }
 
+        var isSSG = Component.__N_SSG;
+        var isSSP = Component.__N_SSP;
+
+        var handleData = function handleData(props) {
+          routeInfo.props = props;
+          _this3.components[route] = routeInfo;
+          return routeInfo;
+        }; // resolve with fallback routeInfo and promise for data
+
+
+        if (isSSG || isSSP) {
+          var dataMethod = function dataMethod() {
+            return isSSG ? _this3._getStaticData(as) : _this3._getServerData(as);
+          };
+
+          var retry = function retry(error) {
+            if (error.statusCode === 404) {
+              throw error;
+            }
+
+            return dataMethod();
+          };
+
+          return _Promise.resolve(_Object$assign(_Object$assign({}, routeInfo), {
+            props: {},
+            dataRes: _this3._getData(function () {
+              return dataMethod() // we retry for data twice unless we get a 404
+              ["catch"](retry)["catch"](retry).then(function (props) {
+                return handleData(props);
+              });
+            })
+          }));
+        }
+
         return _this3._getData(function () {
-          return Component.__N_SSG ? _this3._getStaticData(as) : Component.__N_SSP ? _this3._getServerData(as) : _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+          return _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
           {
             pathname: pathname,
             query: query,
             asPath: as
           });
         }).then(function (props) {
-          routeInfo.props = props;
-          _this3.components[route] = routeInfo;
-          return routeInfo;
+          return handleData(props);
         });
       })["catch"](function (err) {
         return new _Promise(function (resolve) {
Diff for link.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-68b2787ed48eca9ea0a4.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.94ffdad0a29f46cabb19.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-92a5af642b825be192be.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-68b2787ed48eca9ea0a4.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for withRouter.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-68b2787ed48eca9ea0a4.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.94ffdad0a29f46cabb19.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-92a5af642b825be192be.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-68b2787ed48eca9ea0a4.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 9.6s 10s ⚠️ +426ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +7.17 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.13 kB ⚠️ +16 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..b50f.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..e781.js gzip N/A 13.8 kB N/A
Overall change 67.3 kB 67.5 kB ⚠️ +172 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.13 kB ⚠️ +14 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB N/A N/A
framework.HA..dule.js gzip 39.1 kB 39.1 kB
de003c3a9d30..dule.js gzip N/A 12.5 kB N/A
Overall change 61.9 kB 62.1 kB ⚠️ +163 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Serverless bundles Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_error.js gzip 46.5 kB 46.6 kB ⚠️ +147 B
404.html gzip 1.43 kB 1.45 kB ⚠️ +13 B
hooks.html gzip 1.07 kB 1.08 kB ⚠️ +12 B
index.js gzip 46.5 kB 46.7 kB ⚠️ +143 B
link.js gzip 72 kB 72.6 kB ⚠️ +627 B
routerDirect.js gzip 70.2 kB 70.8 kB ⚠️ +605 B
withRouter.js gzip 70 kB 70.6 kB ⚠️ +607 B
Overall change 308 kB 310 kB ⚠️ +2.15 kB

Commit: e5db1bb

@ijjk
Copy link
Member Author

ijjk commented Feb 7, 2020

Stats from current PR

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 11s 11s ⚠️ +5ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +7.17 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.13 kB ⚠️ +16 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..b50f.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..e781.js gzip N/A 13.8 kB N/A
Overall change 67.3 kB 67.5 kB ⚠️ +172 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.13 kB ⚠️ +14 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB 12.5 kB ⚠️ +149 B
framework.HA..dule.js gzip 39.1 kB 39.1 kB
Overall change 61.9 kB 62.1 kB ⚠️ +163 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Rendered Page Sizes Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
index.html gzip 1.02 kB 1.03 kB ⚠️ +13 B
link.html gzip 1.03 kB 1.04 kB ⚠️ +10 B
withRouter.html gzip 1.02 kB 1.03 kB ⚠️ +13 B
Overall change 3.07 kB 3.11 kB ⚠️ +36 B

Diffs

Diff for index.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-68b2787ed48eca9ea0a4.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.94ffdad0a29f46cabb19.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-92a5af642b825be192be.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-68b2787ed48eca9ea0a4.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for main-HASH.module.js
@@ -240,7 +240,8 @@ var {
   buildId,
   assetPrefix,
   runtimeConfig,
-  dynamicIds
+  dynamicIds,
+  isFallback
 } = data;
 var prefix = assetPrefix || ''; // With dynamic assetPrefix it's no longer possible to set assetPrefix at the build time
 // So, this is how we do it in the client side at runtime
@@ -286,16 +287,17 @@ class Container extends _react.default.Component {
 
     if (false) {} // If page was exported and has a querystring
     // If it's a dynamic route or has a querystring
+    // if it's a fallback page
 
 
-    if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+    if (router.isSsr && (isFallback || data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
       // update query on mount for exported pages
       router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2.default)({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
         // WARNING: `_h` is an internal option for handing Next.js
         // client-side hydration. Your app should _never_ use this property.
         // It may change at any time without notice.
         _h: 1,
-        shallow: true
+        shallow: !isFallback
       });
     }
Diff for main-HASH.js
@@ -320,7 +320,8 @@ var props = data.props,
     buildId = data.buildId,
     assetPrefix = data.assetPrefix,
     runtimeConfig = data.runtimeConfig,
-    dynamicIds = data.dynamicIds;
+    dynamicIds = data.dynamicIds,
+    isFallback = data.isFallback;
 var prefix = assetPrefix || ''; // With dynamic assetPrefix it's no longer possible to set assetPrefix at the build time
 // So, this is how we do it in the client side at runtime
 
@@ -381,16 +382,17 @@ function (_react$default$Compon) {
 
       if (false) {} // If page was exported and has a querystring
       // If it's a dynamic route or has a querystring
+      // if it's a fallback page
 
 
-      if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+      if (router.isSsr && (isFallback || data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
         // update query on mount for exported pages
         router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2["default"])({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
           // WARNING: `_h` is an internal option for handing Next.js
           // client-side hydration. Your app should _never_ use this property.
           // It may change at any time without notice.
           _h: 1,
-          shallow: true
+          shallow: !isFallback
         });
       }
Diff for de003c3a9d30..29.module.js
@@ -1480,16 +1480,14 @@ var fetchNextData = (pathname, query, cb) => {
     query
   })).then(res => {
     if (!res.ok) {
-      throw new Error("Failed to load static props");
+      var error = new Error("Failed to load static props");
+      error.statusCode = res.status;
+      throw error;
     }
 
     return res.json();
   }).then(data => {
     return cb ? cb(data) : data;
-  }).catch(err => {
-    ;
-    err.code = 'PAGE_LOAD_ERROR';
-    throw err;
   });
 };
 
@@ -1765,28 +1763,57 @@ class Router {
       Router.events.emit('routeChangeStart', as); // If shallow is true and the route exists in the router cache we reuse the previous result
 
       this.getRouteInfo(route, pathname, query, as, shallow).then(routeInfo => {
-        var {
-          error
-        } = routeInfo;
+        var emitHistory = false;
 
-        if (error && error.cancelled) {
-          return resolve(false);
-        }
+        var doRouteChange = (routeInfo, complete) => {
+          var {
+            error
+          } = routeInfo;
 
-        Router.events.emit('beforeHistoryChange', as);
-        this.changeState(method, url, addBasePath(as), options);
+          if (error && error.cancelled) {
+            return resolve(false);
+          }
 
-        if (false) { var appComp; }
+          if (!emitHistory) {
+            emitHistory = true;
+            Router.events.emit('beforeHistoryChange', as);
+            this.changeState(method, url, addBasePath(as), options);
+          }
 
-        this.set(route, pathname, query, as, routeInfo);
+          if (false) { var appComp; }
 
-        if (error) {
-          Router.events.emit('routeChangeError', error, as);
-          throw error;
-        }
+          this.set(route, pathname, query, as, routeInfo);
 
-        Router.events.emit('routeChangeComplete', as);
-        return resolve(true);
+          if (complete) {
+            if (error) {
+              Router.events.emit('routeChangeError', error, as);
+              throw error;
+            }
+
+            Router.events.emit('routeChangeComplete', as);
+            resolve(true);
+          }
+        };
+
+        if (routeInfo.dataRes) {
+          var dataRes = routeInfo.dataRes; // to prevent a flash of the fallback page we delay showing it for
+          // 110ms and race the timeout with the data response. If the data
+          // beats the timeout we skip showing the fallback
+
+          _Promise.race([new _Promise(resolve => setTimeout(() => resolve(false), 110)), dataRes]).then(data => {
+            if (!data) {
+              // data didn't win the race, show fallback
+              doRouteChange(routeInfo, false);
+            }
+
+            return dataRes;
+          }).then(finalData => {
+            // render with the data and complete route change
+            doRouteChange(finalData, true);
+          }, reject);
+        } else {
+          doRouteChange(routeInfo, true);
+        }
       }, reject);
     });
   }
@@ -1830,16 +1857,40 @@ class Router {
 
       if (false) { var isValidElementType; }
 
-      return this._getData(() => Component.__N_SSG ? this._getStaticData(as) : Component.__N_SSP ? this._getServerData(as) : this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+      var isSSG = Component.__N_SSG;
+      var isSSP = Component.__N_SSP;
+
+      var handleData = props => {
+        routeInfo.props = props;
+        this.components[route] = routeInfo;
+        return routeInfo;
+      }; // resolve with fallback routeInfo and promise for data
+
+
+      if (isSSG || isSSP) {
+        var dataMethod = () => isSSG ? this._getStaticData(as) : this._getServerData(as);
+
+        var retry = error => {
+          if (error.statusCode === 404) {
+            throw error;
+          }
+
+          return dataMethod();
+        };
+
+        return _Promise.resolve(_Object$assign(_Object$assign({}, routeInfo), {
+          props: {},
+          dataRes: this._getData(() => dataMethod() // we retry for data twice unless we get a 404
+          .catch(retry).catch(retry).then(props => handleData(props)))
+        }));
+      }
+
+      return this._getData(() => this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
       {
         pathname,
         query,
         asPath: as
-      })).then(props => {
-        routeInfo.props = props;
-        this.components[route] = routeInfo;
-        return routeInfo;
-      });
+      })).then(props => handleData(props));
     }).catch(err => {
       return new _Promise(resolve => {
         if (err.code === 'PAGE_LOAD_ERROR') {
Diff for de003c3a9d30..686f3d49e.js
@@ -1200,16 +1200,14 @@ var fetchNextData = function fetchNextData(pathname, query, cb) {
     query: query
   })).then(function (res) {
     if (!res.ok) {
-      throw new Error("Failed to load static props");
+      var error = new Error("Failed to load static props");
+      error.statusCode = res.status;
+      throw error;
     }
 
     return res.json();
   }).then(function (data) {
     return cb ? cb(data) : data;
-  })["catch"](function (err) {
-    ;
-    err.code = 'PAGE_LOAD_ERROR';
-    throw err;
   });
 };
 
@@ -1498,27 +1496,60 @@ function () {
         Router.events.emit('routeChangeStart', as); // If shallow is true and the route exists in the router cache we reuse the previous result
 
         _this2.getRouteInfo(route, pathname, query, as, shallow).then(function (routeInfo) {
-          var error = routeInfo.error;
+          var emitHistory = false;
 
-          if (error && error.cancelled) {
-            return resolve(false);
-          }
+          var doRouteChange = function doRouteChange(routeInfo, complete) {
+            var error = routeInfo.error;
 
-          Router.events.emit('beforeHistoryChange', as);
+            if (error && error.cancelled) {
+              return resolve(false);
+            }
 
-          _this2.changeState(method, url, addBasePath(as), options);
+            if (!emitHistory) {
+              emitHistory = true;
+              Router.events.emit('beforeHistoryChange', as);
 
-          if (false) { var appComp; }
+              _this2.changeState(method, url, addBasePath(as), options);
+            }
 
-          _this2.set(route, pathname, query, as, routeInfo);
+            if (false) { var appComp; }
 
-          if (error) {
-            Router.events.emit('routeChangeError', error, as);
-            throw error;
-          }
+            _this2.set(route, pathname, query, as, routeInfo);
 
-          Router.events.emit('routeChangeComplete', as);
-          return resolve(true);
+            if (complete) {
+              if (error) {
+                Router.events.emit('routeChangeError', error, as);
+                throw error;
+              }
+
+              Router.events.emit('routeChangeComplete', as);
+              resolve(true);
+            }
+          };
+
+          if (routeInfo.dataRes) {
+            var dataRes = routeInfo.dataRes; // to prevent a flash of the fallback page we delay showing it for
+            // 110ms and race the timeout with the data response. If the data
+            // beats the timeout we skip showing the fallback
+
+            _Promise.race([new _Promise(function (resolve) {
+              return setTimeout(function () {
+                return resolve(false);
+              }, 110);
+            }), dataRes]).then(function (data) {
+              if (!data) {
+                // data didn't win the race, show fallback
+                doRouteChange(routeInfo, false);
+              }
+
+              return dataRes;
+            }).then(function (finalData) {
+              // render with the data and complete route change
+              doRouteChange(finalData, true);
+            }, reject);
+          } else {
+            doRouteChange(routeInfo, true);
+          }
         }, reject);
       });
     }
@@ -1566,17 +1597,49 @@ function () {
 
         if (false) { var _require, isValidElementType; }
 
+        var isSSG = Component.__N_SSG;
+        var isSSP = Component.__N_SSP;
+
+        var handleData = function handleData(props) {
+          routeInfo.props = props;
+          _this3.components[route] = routeInfo;
+          return routeInfo;
+        }; // resolve with fallback routeInfo and promise for data
+
+
+        if (isSSG || isSSP) {
+          var dataMethod = function dataMethod() {
+            return isSSG ? _this3._getStaticData(as) : _this3._getServerData(as);
+          };
+
+          var retry = function retry(error) {
+            if (error.statusCode === 404) {
+              throw error;
+            }
+
+            return dataMethod();
+          };
+
+          return _Promise.resolve(_Object$assign(_Object$assign({}, routeInfo), {
+            props: {},
+            dataRes: _this3._getData(function () {
+              return dataMethod() // we retry for data twice unless we get a 404
+              ["catch"](retry)["catch"](retry).then(function (props) {
+                return handleData(props);
+              });
+            })
+          }));
+        }
+
         return _this3._getData(function () {
-          return Component.__N_SSG ? _this3._getStaticData(as) : Component.__N_SSP ? _this3._getServerData(as) : _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+          return _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
           {
             pathname: pathname,
             query: query,
             asPath: as
           });
         }).then(function (props) {
-          routeInfo.props = props;
-          _this3.components[route] = routeInfo;
-          return routeInfo;
+          return handleData(props);
         });
       })["catch"](function (err) {
         return new _Promise(function (resolve) {
Diff for link.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-68b2787ed48eca9ea0a4.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.94ffdad0a29f46cabb19.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-92a5af642b825be192be.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-68b2787ed48eca9ea0a4.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for withRouter.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-68b2787ed48eca9ea0a4.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.94ffdad0a29f46cabb19.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-92a5af642b825be192be.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-68b2787ed48eca9ea0a4.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 11.4s 11.3s -114ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +7.17 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.13 kB ⚠️ +16 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..b50f.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..e781.js gzip N/A 13.8 kB N/A
Overall change 67.3 kB 67.5 kB ⚠️ +172 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.13 kB ⚠️ +14 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB N/A N/A
framework.HA..dule.js gzip 39.1 kB 39.1 kB
de003c3a9d30..dule.js gzip N/A 12.5 kB N/A
Overall change 61.9 kB 62.1 kB ⚠️ +163 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Serverless bundles Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_error.js gzip 46.5 kB 46.6 kB ⚠️ +147 B
404.html gzip 1.43 kB 1.45 kB ⚠️ +13 B
hooks.html gzip 1.07 kB 1.08 kB ⚠️ +12 B
index.js gzip 46.5 kB 46.7 kB ⚠️ +143 B
link.js gzip 72 kB 72.6 kB ⚠️ +627 B
routerDirect.js gzip 70.2 kB 70.8 kB ⚠️ +605 B
withRouter.js gzip 70 kB 70.6 kB ⚠️ +607 B
Overall change 308 kB 310 kB ⚠️ +2.15 kB

Commit: 310e98d

@ijjk ijjk requested a review from Timer February 7, 2020 04:36
@@ -504,6 +510,12 @@ export async function renderToHTML(
// _app's getInitialProps for getServerProps if not this can be removed
if (isDataReq) return props
Copy link
Member

Choose a reason for hiding this comment

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

The below code setting props.pageProps to an empty object probably has to come before this.

Copy link
Member Author

Choose a reason for hiding this comment

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

We don't generate a fallback for data requests so this is ok to come before, unless you think it flows more clearly coming after?

<link
rel="preload"
href={
assetPrefix + `/_next/data/${buildId}${dangerousAsPath}.json`
Copy link
Member

Choose a reason for hiding this comment

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

Is dangerousAsPath correct here? This would result in the incorrect data bundle for rewritten dynamic pages AFAIK.

Copy link
Member

Choose a reason for hiding this comment

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

We probably want pathname (href) w/ dynamic route parts interpolated.

Copy link
Member

Choose a reason for hiding this comment

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

Let's be sure to add a test case for this, one way or another. The test should render a fallback page by means of a rewrite, then find this preload in the DOM and request it to verify it's real.

Copy link
Member Author

Choose a reason for hiding this comment

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

It looks like we might not be able to use link[rel=preload] to kick-off the data fetching in the fallback since the data URL needs to be specific to the dynamic route e.g. /blog/post-1 and we can only specify one since we're pre-rendering it

@ijjk
Copy link
Member Author

ijjk commented Feb 7, 2020

Stats from current PR

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 12.2s 12.4s ⚠️ +201ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +7.17 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.13 kB ⚠️ +16 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..b50f.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..e781.js gzip N/A 13.8 kB N/A
Overall change 67.3 kB 67.5 kB ⚠️ +172 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.13 kB ⚠️ +14 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB 12.5 kB ⚠️ +149 B
framework.HA..dule.js gzip 39.1 kB 39.1 kB
Overall change 61.9 kB 62.1 kB ⚠️ +163 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Rendered Page Sizes Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
index.html gzip 1.02 kB 1.03 kB ⚠️ +13 B
link.html gzip 1.03 kB 1.04 kB ⚠️ +10 B
withRouter.html gzip 1.02 kB 1.03 kB ⚠️ +13 B
Overall change 3.07 kB 3.11 kB ⚠️ +36 B

Diffs

Diff for index.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-68b2787ed48eca9ea0a4.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.94ffdad0a29f46cabb19.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-92a5af642b825be192be.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-68b2787ed48eca9ea0a4.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for main-HASH.module.js
@@ -240,7 +240,8 @@ var {
   buildId,
   assetPrefix,
   runtimeConfig,
-  dynamicIds
+  dynamicIds,
+  isFallback
 } = data;
 var prefix = assetPrefix || ''; // With dynamic assetPrefix it's no longer possible to set assetPrefix at the build time
 // So, this is how we do it in the client side at runtime
@@ -286,16 +287,17 @@ class Container extends _react.default.Component {
 
     if (false) {} // If page was exported and has a querystring
     // If it's a dynamic route or has a querystring
+    // if it's a fallback page
 
 
-    if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+    if (router.isSsr && (isFallback || data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
       // update query on mount for exported pages
       router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2.default)({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
         // WARNING: `_h` is an internal option for handing Next.js
         // client-side hydration. Your app should _never_ use this property.
         // It may change at any time without notice.
         _h: 1,
-        shallow: true
+        shallow: !isFallback
       });
     }
Diff for main-HASH.js
@@ -320,7 +320,8 @@ var props = data.props,
     buildId = data.buildId,
     assetPrefix = data.assetPrefix,
     runtimeConfig = data.runtimeConfig,
-    dynamicIds = data.dynamicIds;
+    dynamicIds = data.dynamicIds,
+    isFallback = data.isFallback;
 var prefix = assetPrefix || ''; // With dynamic assetPrefix it's no longer possible to set assetPrefix at the build time
 // So, this is how we do it in the client side at runtime
 
@@ -381,16 +382,17 @@ function (_react$default$Compon) {
 
       if (false) {} // If page was exported and has a querystring
       // If it's a dynamic route or has a querystring
+      // if it's a fallback page
 
 
-      if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+      if (router.isSsr && (isFallback || data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
         // update query on mount for exported pages
         router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2["default"])({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
           // WARNING: `_h` is an internal option for handing Next.js
           // client-side hydration. Your app should _never_ use this property.
           // It may change at any time without notice.
           _h: 1,
-          shallow: true
+          shallow: !isFallback
         });
       }
Diff for de003c3a9d30..29.module.js
@@ -1480,16 +1480,14 @@ var fetchNextData = (pathname, query, cb) => {
     query
   })).then(res => {
     if (!res.ok) {
-      throw new Error("Failed to load static props");
+      var error = new Error("Failed to load static props");
+      error.statusCode = res.status;
+      throw error;
     }
 
     return res.json();
   }).then(data => {
     return cb ? cb(data) : data;
-  }).catch(err => {
-    ;
-    err.code = 'PAGE_LOAD_ERROR';
-    throw err;
   });
 };
 
@@ -1765,28 +1763,57 @@ class Router {
       Router.events.emit('routeChangeStart', as); // If shallow is true and the route exists in the router cache we reuse the previous result
 
       this.getRouteInfo(route, pathname, query, as, shallow).then(routeInfo => {
-        var {
-          error
-        } = routeInfo;
+        var emitHistory = false;
 
-        if (error && error.cancelled) {
-          return resolve(false);
-        }
+        var doRouteChange = (routeInfo, complete) => {
+          var {
+            error
+          } = routeInfo;
 
-        Router.events.emit('beforeHistoryChange', as);
-        this.changeState(method, url, addBasePath(as), options);
+          if (error && error.cancelled) {
+            return resolve(false);
+          }
 
-        if (false) { var appComp; }
+          if (!emitHistory) {
+            emitHistory = true;
+            Router.events.emit('beforeHistoryChange', as);
+            this.changeState(method, url, addBasePath(as), options);
+          }
 
-        this.set(route, pathname, query, as, routeInfo);
+          if (false) { var appComp; }
 
-        if (error) {
-          Router.events.emit('routeChangeError', error, as);
-          throw error;
-        }
+          this.set(route, pathname, query, as, routeInfo);
 
-        Router.events.emit('routeChangeComplete', as);
-        return resolve(true);
+          if (complete) {
+            if (error) {
+              Router.events.emit('routeChangeError', error, as);
+              throw error;
+            }
+
+            Router.events.emit('routeChangeComplete', as);
+            resolve(true);
+          }
+        };
+
+        if (routeInfo.dataRes) {
+          var dataRes = routeInfo.dataRes; // to prevent a flash of the fallback page we delay showing it for
+          // 110ms and race the timeout with the data response. If the data
+          // beats the timeout we skip showing the fallback
+
+          _Promise.race([new _Promise(resolve => setTimeout(() => resolve(false), 110)), dataRes]).then(data => {
+            if (!data) {
+              // data didn't win the race, show fallback
+              doRouteChange(routeInfo, false);
+            }
+
+            return dataRes;
+          }).then(finalData => {
+            // render with the data and complete route change
+            doRouteChange(finalData, true);
+          }, reject);
+        } else {
+          doRouteChange(routeInfo, true);
+        }
       }, reject);
     });
   }
@@ -1830,16 +1857,40 @@ class Router {
 
       if (false) { var isValidElementType; }
 
-      return this._getData(() => Component.__N_SSG ? this._getStaticData(as) : Component.__N_SSP ? this._getServerData(as) : this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+      var isSSG = Component.__N_SSG;
+      var isSSP = Component.__N_SSP;
+
+      var handleData = props => {
+        routeInfo.props = props;
+        this.components[route] = routeInfo;
+        return routeInfo;
+      }; // resolve with fallback routeInfo and promise for data
+
+
+      if (isSSG || isSSP) {
+        var dataMethod = () => isSSG ? this._getStaticData(as) : this._getServerData(as);
+
+        var retry = error => {
+          if (error.statusCode === 404) {
+            throw error;
+          }
+
+          return dataMethod();
+        };
+
+        return _Promise.resolve(_Object$assign(_Object$assign({}, routeInfo), {
+          props: {},
+          dataRes: this._getData(() => dataMethod() // we retry for data twice unless we get a 404
+          .catch(retry).catch(retry).then(props => handleData(props)))
+        }));
+      }
+
+      return this._getData(() => this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
       {
         pathname,
         query,
         asPath: as
-      })).then(props => {
-        routeInfo.props = props;
-        this.components[route] = routeInfo;
-        return routeInfo;
-      });
+      })).then(props => handleData(props));
     }).catch(err => {
       return new _Promise(resolve => {
         if (err.code === 'PAGE_LOAD_ERROR') {
Diff for de003c3a9d30..686f3d49e.js
@@ -1200,16 +1200,14 @@ var fetchNextData = function fetchNextData(pathname, query, cb) {
     query: query
   })).then(function (res) {
     if (!res.ok) {
-      throw new Error("Failed to load static props");
+      var error = new Error("Failed to load static props");
+      error.statusCode = res.status;
+      throw error;
     }
 
     return res.json();
   }).then(function (data) {
     return cb ? cb(data) : data;
-  })["catch"](function (err) {
-    ;
-    err.code = 'PAGE_LOAD_ERROR';
-    throw err;
   });
 };
 
@@ -1498,27 +1496,60 @@ function () {
         Router.events.emit('routeChangeStart', as); // If shallow is true and the route exists in the router cache we reuse the previous result
 
         _this2.getRouteInfo(route, pathname, query, as, shallow).then(function (routeInfo) {
-          var error = routeInfo.error;
+          var emitHistory = false;
 
-          if (error && error.cancelled) {
-            return resolve(false);
-          }
+          var doRouteChange = function doRouteChange(routeInfo, complete) {
+            var error = routeInfo.error;
 
-          Router.events.emit('beforeHistoryChange', as);
+            if (error && error.cancelled) {
+              return resolve(false);
+            }
 
-          _this2.changeState(method, url, addBasePath(as), options);
+            if (!emitHistory) {
+              emitHistory = true;
+              Router.events.emit('beforeHistoryChange', as);
 
-          if (false) { var appComp; }
+              _this2.changeState(method, url, addBasePath(as), options);
+            }
 
-          _this2.set(route, pathname, query, as, routeInfo);
+            if (false) { var appComp; }
 
-          if (error) {
-            Router.events.emit('routeChangeError', error, as);
-            throw error;
-          }
+            _this2.set(route, pathname, query, as, routeInfo);
 
-          Router.events.emit('routeChangeComplete', as);
-          return resolve(true);
+            if (complete) {
+              if (error) {
+                Router.events.emit('routeChangeError', error, as);
+                throw error;
+              }
+
+              Router.events.emit('routeChangeComplete', as);
+              resolve(true);
+            }
+          };
+
+          if (routeInfo.dataRes) {
+            var dataRes = routeInfo.dataRes; // to prevent a flash of the fallback page we delay showing it for
+            // 110ms and race the timeout with the data response. If the data
+            // beats the timeout we skip showing the fallback
+
+            _Promise.race([new _Promise(function (resolve) {
+              return setTimeout(function () {
+                return resolve(false);
+              }, 110);
+            }), dataRes]).then(function (data) {
+              if (!data) {
+                // data didn't win the race, show fallback
+                doRouteChange(routeInfo, false);
+              }
+
+              return dataRes;
+            }).then(function (finalData) {
+              // render with the data and complete route change
+              doRouteChange(finalData, true);
+            }, reject);
+          } else {
+            doRouteChange(routeInfo, true);
+          }
         }, reject);
       });
     }
@@ -1566,17 +1597,49 @@ function () {
 
         if (false) { var _require, isValidElementType; }
 
+        var isSSG = Component.__N_SSG;
+        var isSSP = Component.__N_SSP;
+
+        var handleData = function handleData(props) {
+          routeInfo.props = props;
+          _this3.components[route] = routeInfo;
+          return routeInfo;
+        }; // resolve with fallback routeInfo and promise for data
+
+
+        if (isSSG || isSSP) {
+          var dataMethod = function dataMethod() {
+            return isSSG ? _this3._getStaticData(as) : _this3._getServerData(as);
+          };
+
+          var retry = function retry(error) {
+            if (error.statusCode === 404) {
+              throw error;
+            }
+
+            return dataMethod();
+          };
+
+          return _Promise.resolve(_Object$assign(_Object$assign({}, routeInfo), {
+            props: {},
+            dataRes: _this3._getData(function () {
+              return dataMethod() // we retry for data twice unless we get a 404
+              ["catch"](retry)["catch"](retry).then(function (props) {
+                return handleData(props);
+              });
+            })
+          }));
+        }
+
         return _this3._getData(function () {
-          return Component.__N_SSG ? _this3._getStaticData(as) : Component.__N_SSP ? _this3._getServerData(as) : _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+          return _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
           {
             pathname: pathname,
             query: query,
             asPath: as
           });
         }).then(function (props) {
-          routeInfo.props = props;
-          _this3.components[route] = routeInfo;
-          return routeInfo;
+          return handleData(props);
         });
       })["catch"](function (err) {
         return new _Promise(function (resolve) {
Diff for link.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-68b2787ed48eca9ea0a4.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.94ffdad0a29f46cabb19.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-92a5af642b825be192be.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-68b2787ed48eca9ea0a4.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for withRouter.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-68b2787ed48eca9ea0a4.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.94ffdad0a29f46cabb19.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-92a5af642b825be192be.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-68b2787ed48eca9ea0a4.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 12.5s 12.8s ⚠️ +311ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +7.17 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.13 kB ⚠️ +16 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..b50f.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..e781.js gzip N/A 13.8 kB N/A
Overall change 67.3 kB 67.5 kB ⚠️ +172 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.13 kB ⚠️ +14 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB N/A N/A
framework.HA..dule.js gzip 39.1 kB 39.1 kB
de003c3a9d30..dule.js gzip N/A 12.5 kB N/A
Overall change 61.9 kB 62.1 kB ⚠️ +163 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Serverless bundles Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_error.js gzip 46.5 kB 46.6 kB ⚠️ +101 B
404.html gzip 1.43 kB 1.45 kB ⚠️ +13 B
hooks.html gzip 1.07 kB 1.08 kB ⚠️ +12 B
index.js gzip 46.5 kB 46.6 kB ⚠️ +93 B
link.js gzip 72 kB 72.6 kB ⚠️ +583 B
routerDirect.js gzip 70.2 kB 70.8 kB ⚠️ +560 B
withRouter.js gzip 70 kB 70.6 kB ⚠️ +561 B
Overall change 308 kB 310 kB ⚠️ +1.92 kB

Commit: 6f50f3d

@ijjk
Copy link
Member Author

ijjk commented Feb 7, 2020

Stats from current PR

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 12.1s 12.5s ⚠️ +337ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +7.5 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.13 kB ⚠️ +16 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..b50f.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..e781.js gzip N/A 13.8 kB N/A
Overall change 67.3 kB 67.5 kB ⚠️ +172 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.13 kB ⚠️ +14 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB 12.5 kB ⚠️ +149 B
framework.HA..dule.js gzip 39.1 kB 39.1 kB
Overall change 61.9 kB 62.1 kB ⚠️ +163 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Rendered Page Sizes Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
index.html gzip 1.02 kB 1.03 kB ⚠️ +13 B
link.html gzip 1.03 kB 1.04 kB ⚠️ +10 B
withRouter.html gzip 1.02 kB 1.03 kB ⚠️ +13 B
Overall change 3.07 kB 3.11 kB ⚠️ +36 B

Diffs

Diff for link.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/link.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-68b2787ed48eca9ea0a4.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div><h3>A Link page!</h3><a href="/">Go to /</a></div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/link","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/link" src="/_next/static/BUILD_ID/pages/link.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.94ffdad0a29f46cabb19.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-92a5af642b825be192be.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-68b2787ed48eca9ea0a4.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for index.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/index.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-68b2787ed48eca9ea0a4.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next">Hello world 👋</div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/" src="/_next/static/BUILD_ID/pages/index.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.94ffdad0a29f46cabb19.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-92a5af642b825be192be.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-68b2787ed48eca9ea0a4.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
Diff for main-HASH.module.js
@@ -240,7 +240,8 @@ var {
   buildId,
   assetPrefix,
   runtimeConfig,
-  dynamicIds
+  dynamicIds,
+  isFallback
 } = data;
 var prefix = assetPrefix || ''; // With dynamic assetPrefix it's no longer possible to set assetPrefix at the build time
 // So, this is how we do it in the client side at runtime
@@ -286,16 +287,17 @@ class Container extends _react.default.Component {
 
     if (false) {} // If page was exported and has a querystring
     // If it's a dynamic route or has a querystring
+    // if it's a fallback page
 
 
-    if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+    if (router.isSsr && (isFallback || data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
       // update query on mount for exported pages
       router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2.default)({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
         // WARNING: `_h` is an internal option for handing Next.js
         // client-side hydration. Your app should _never_ use this property.
         // It may change at any time without notice.
         _h: 1,
-        shallow: true
+        shallow: !isFallback
       });
     }
Diff for main-HASH.js
@@ -320,7 +320,8 @@ var props = data.props,
     buildId = data.buildId,
     assetPrefix = data.assetPrefix,
     runtimeConfig = data.runtimeConfig,
-    dynamicIds = data.dynamicIds;
+    dynamicIds = data.dynamicIds,
+    isFallback = data.isFallback;
 var prefix = assetPrefix || ''; // With dynamic assetPrefix it's no longer possible to set assetPrefix at the build time
 // So, this is how we do it in the client side at runtime
 
@@ -381,16 +382,17 @@ function (_react$default$Compon) {
 
       if (false) {} // If page was exported and has a querystring
       // If it's a dynamic route or has a querystring
+      // if it's a fallback page
 
 
-      if (router.isSsr && (data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
+      if (router.isSsr && (isFallback || data.nextExport && ((0, _isDynamic.isDynamicRoute)(router.pathname) || location.search) || Component && Component.__N_SSG && location.search)) {
         // update query on mount for exported pages
         router.replace(router.pathname + '?' + (0, _querystring.stringify)((0, _extends2["default"])({}, router.query, {}, (0, _querystring.parse)(location.search.substr(1)))), asPath, {
           // WARNING: `_h` is an internal option for handing Next.js
           // client-side hydration. Your app should _never_ use this property.
           // It may change at any time without notice.
           _h: 1,
-          shallow: true
+          shallow: !isFallback
         });
       }
Diff for de003c3a9d30..29.module.js
@@ -1480,16 +1480,14 @@ var fetchNextData = (pathname, query, cb) => {
     query
   })).then(res => {
     if (!res.ok) {
-      throw new Error("Failed to load static props");
+      var error = new Error("Failed to load static props");
+      error.statusCode = res.status;
+      throw error;
     }
 
     return res.json();
   }).then(data => {
     return cb ? cb(data) : data;
-  }).catch(err => {
-    ;
-    err.code = 'PAGE_LOAD_ERROR';
-    throw err;
   });
 };
 
@@ -1765,28 +1763,57 @@ class Router {
       Router.events.emit('routeChangeStart', as); // If shallow is true and the route exists in the router cache we reuse the previous result
 
       this.getRouteInfo(route, pathname, query, as, shallow).then(routeInfo => {
-        var {
-          error
-        } = routeInfo;
+        var emitHistory = false;
 
-        if (error && error.cancelled) {
-          return resolve(false);
-        }
+        var doRouteChange = (routeInfo, complete) => {
+          var {
+            error
+          } = routeInfo;
 
-        Router.events.emit('beforeHistoryChange', as);
-        this.changeState(method, url, addBasePath(as), options);
+          if (error && error.cancelled) {
+            return resolve(false);
+          }
 
-        if (false) { var appComp; }
+          if (!emitHistory) {
+            emitHistory = true;
+            Router.events.emit('beforeHistoryChange', as);
+            this.changeState(method, url, addBasePath(as), options);
+          }
 
-        this.set(route, pathname, query, as, routeInfo);
+          if (false) { var appComp; }
 
-        if (error) {
-          Router.events.emit('routeChangeError', error, as);
-          throw error;
-        }
+          this.set(route, pathname, query, as, routeInfo);
 
-        Router.events.emit('routeChangeComplete', as);
-        return resolve(true);
+          if (complete) {
+            if (error) {
+              Router.events.emit('routeChangeError', error, as);
+              throw error;
+            }
+
+            Router.events.emit('routeChangeComplete', as);
+            resolve(true);
+          }
+        };
+
+        if (routeInfo.dataRes) {
+          var dataRes = routeInfo.dataRes; // to prevent a flash of the fallback page we delay showing it for
+          // 110ms and race the timeout with the data response. If the data
+          // beats the timeout we skip showing the fallback
+
+          _Promise.race([new _Promise(resolve => setTimeout(() => resolve(false), 110)), dataRes]).then(data => {
+            if (!data) {
+              // data didn't win the race, show fallback
+              doRouteChange(routeInfo, false);
+            }
+
+            return dataRes;
+          }).then(finalData => {
+            // render with the data and complete route change
+            doRouteChange(finalData, true);
+          }, reject);
+        } else {
+          doRouteChange(routeInfo, true);
+        }
       }, reject);
     });
   }
@@ -1830,16 +1857,40 @@ class Router {
 
       if (false) { var isValidElementType; }
 
-      return this._getData(() => Component.__N_SSG ? this._getStaticData(as) : Component.__N_SSP ? this._getServerData(as) : this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+      var isSSG = Component.__N_SSG;
+      var isSSP = Component.__N_SSP;
+
+      var handleData = props => {
+        routeInfo.props = props;
+        this.components[route] = routeInfo;
+        return routeInfo;
+      }; // resolve with fallback routeInfo and promise for data
+
+
+      if (isSSG || isSSP) {
+        var dataMethod = () => isSSG ? this._getStaticData(as) : this._getServerData(as);
+
+        var retry = error => {
+          if (error.statusCode === 404) {
+            throw error;
+          }
+
+          return dataMethod();
+        };
+
+        return _Promise.resolve(_Object$assign(_Object$assign({}, routeInfo), {
+          props: {},
+          dataRes: this._getData(() => dataMethod() // we retry for data twice unless we get a 404
+          .catch(retry).catch(retry).then(props => handleData(props)))
+        }));
+      }
+
+      return this._getData(() => this.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
       {
         pathname,
         query,
         asPath: as
-      })).then(props => {
-        routeInfo.props = props;
-        this.components[route] = routeInfo;
-        return routeInfo;
-      });
+      })).then(props => handleData(props));
     }).catch(err => {
       return new _Promise(resolve => {
         if (err.code === 'PAGE_LOAD_ERROR') {
Diff for de003c3a9d30..686f3d49e.js
@@ -1200,16 +1200,14 @@ var fetchNextData = function fetchNextData(pathname, query, cb) {
     query: query
   })).then(function (res) {
     if (!res.ok) {
-      throw new Error("Failed to load static props");
+      var error = new Error("Failed to load static props");
+      error.statusCode = res.status;
+      throw error;
     }
 
     return res.json();
   }).then(function (data) {
     return cb ? cb(data) : data;
-  })["catch"](function (err) {
-    ;
-    err.code = 'PAGE_LOAD_ERROR';
-    throw err;
   });
 };
 
@@ -1498,27 +1496,60 @@ function () {
         Router.events.emit('routeChangeStart', as); // If shallow is true and the route exists in the router cache we reuse the previous result
 
         _this2.getRouteInfo(route, pathname, query, as, shallow).then(function (routeInfo) {
-          var error = routeInfo.error;
+          var emitHistory = false;
 
-          if (error && error.cancelled) {
-            return resolve(false);
-          }
+          var doRouteChange = function doRouteChange(routeInfo, complete) {
+            var error = routeInfo.error;
 
-          Router.events.emit('beforeHistoryChange', as);
+            if (error && error.cancelled) {
+              return resolve(false);
+            }
 
-          _this2.changeState(method, url, addBasePath(as), options);
+            if (!emitHistory) {
+              emitHistory = true;
+              Router.events.emit('beforeHistoryChange', as);
 
-          if (false) { var appComp; }
+              _this2.changeState(method, url, addBasePath(as), options);
+            }
 
-          _this2.set(route, pathname, query, as, routeInfo);
+            if (false) { var appComp; }
 
-          if (error) {
-            Router.events.emit('routeChangeError', error, as);
-            throw error;
-          }
+            _this2.set(route, pathname, query, as, routeInfo);
 
-          Router.events.emit('routeChangeComplete', as);
-          return resolve(true);
+            if (complete) {
+              if (error) {
+                Router.events.emit('routeChangeError', error, as);
+                throw error;
+              }
+
+              Router.events.emit('routeChangeComplete', as);
+              resolve(true);
+            }
+          };
+
+          if (routeInfo.dataRes) {
+            var dataRes = routeInfo.dataRes; // to prevent a flash of the fallback page we delay showing it for
+            // 110ms and race the timeout with the data response. If the data
+            // beats the timeout we skip showing the fallback
+
+            _Promise.race([new _Promise(function (resolve) {
+              return setTimeout(function () {
+                return resolve(false);
+              }, 110);
+            }), dataRes]).then(function (data) {
+              if (!data) {
+                // data didn't win the race, show fallback
+                doRouteChange(routeInfo, false);
+              }
+
+              return dataRes;
+            }).then(function (finalData) {
+              // render with the data and complete route change
+              doRouteChange(finalData, true);
+            }, reject);
+          } else {
+            doRouteChange(routeInfo, true);
+          }
         }, reject);
       });
     }
@@ -1566,17 +1597,49 @@ function () {
 
         if (false) { var _require, isValidElementType; }
 
+        var isSSG = Component.__N_SSG;
+        var isSSP = Component.__N_SSP;
+
+        var handleData = function handleData(props) {
+          routeInfo.props = props;
+          _this3.components[route] = routeInfo;
+          return routeInfo;
+        }; // resolve with fallback routeInfo and promise for data
+
+
+        if (isSSG || isSSP) {
+          var dataMethod = function dataMethod() {
+            return isSSG ? _this3._getStaticData(as) : _this3._getServerData(as);
+          };
+
+          var retry = function retry(error) {
+            if (error.statusCode === 404) {
+              throw error;
+            }
+
+            return dataMethod();
+          };
+
+          return _Promise.resolve(_Object$assign(_Object$assign({}, routeInfo), {
+            props: {},
+            dataRes: _this3._getData(function () {
+              return dataMethod() // we retry for data twice unless we get a 404
+              ["catch"](retry)["catch"](retry).then(function (props) {
+                return handleData(props);
+              });
+            })
+          }));
+        }
+
         return _this3._getData(function () {
-          return Component.__N_SSG ? _this3._getStaticData(as) : Component.__N_SSP ? _this3._getServerData(as) : _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
+          return _this3.getInitialProps(Component, // we provide AppTree later so this needs to be `any`
           {
             pathname: pathname,
             query: query,
             asPath: as
           });
         }).then(function (props) {
-          routeInfo.props = props;
-          _this3.components[route] = routeInfo;
-          return routeInfo;
+          return handleData(props);
         });
       })["catch"](function (err) {
         return new _Promise(function (resolve) {
Diff for withRouter.html
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID"}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.10085c0ac2a686f3d49e.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.9a4d336620e9148d6529.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-6429722a0b2ea4ff3238.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-a7dfb73a66775e653fab.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/BUILD_ID/pages/withRouter.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/BUILD_ID/pages/_app.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" as="script" crossorigin="anonymous"/><link rel="preload" href="/_next/static/runtime/main-68b2787ed48eca9ea0a4.module.js" as="script" crossorigin="anonymous"/></head><body><div id="__next"><div>I use withRouter</div></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{"props":{"pageProps":{}},"page":"/withRouter","query":{},"buildId":"BUILD_ID","isFallback":false}</script><script crossorigin="anonymous" nomodule="">!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script><script crossorigin="anonymous" nomodule="" src="/_next/static/runtime/polyfills-355bc4b3077ea9d3fc7a.js"></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/withRouter" src="/_next/static/BUILD_ID/pages/withRouter.module.js" crossorigin="anonymous" type="module"></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.js" crossorigin="anonymous" nomodule=""></script><script async="" data-next-page="/_app" src="/_next/static/BUILD_ID/pages/_app.module.js" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/webpack-4d739ac7b0d8f888ab18.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/webpack-d629b83a65f3e33fa99e.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/framework.c07ba8a3b0945b0f6315.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/framework.5bb7f30f859f5f31359f.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/commons.5d483f979b96e9afed5a.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.9a0caf742c992a927903.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.6406830adfd759a39616.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.94ffdad0a29f46cabb19.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.978383ccfbd093c75ec7.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/runtime/main-92a5af642b825be192be.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/runtime/main-68b2787ed48eca9ea0a4.module.js" async="" crossorigin="anonymous" type="module"></script><script src="/_next/static/BUILD_ID/_buildManifest.js" async="" crossorigin="anonymous" nomodule=""></script><script src="/_next/static/BUILD_ID/_buildManifest.module.js" async="" crossorigin="anonymous" type="module"></script></body></html>
\ No newline at end of file

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
buildDuration 12.6s 12.7s ⚠️ +81ms
nodeModulesSize 52.6 MB 52.6 MB ⚠️ +7.5 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.js gzip 5.12 kB 5.13 kB ⚠️ +16 B
webpack-HASH.js gzip 746 B 746 B
4952ddcd88e7..54d3.js gzip 4.68 kB 4.68 kB
commons.HASH.js gzip 4.06 kB 4.06 kB
de003c3a9d30..b50f.js gzip 13.6 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..e781.js gzip N/A 13.8 kB N/A
Overall change 67.3 kB 67.5 kB ⚠️ +172 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
main-HASH.module.js gzip 4.12 kB 4.13 kB ⚠️ +14 B
webpack-HASH..dule.js gzip 746 B 746 B
4952ddcd88e7..dule.js gzip 5.56 kB 5.56 kB
de003c3a9d30..dule.js gzip 12.4 kB N/A N/A
framework.HA..dule.js gzip 39.1 kB 39.1 kB
de003c3a9d30..dule.js gzip N/A 12.5 kB N/A
Overall change 61.9 kB 62.1 kB ⚠️ +163 B
Legacy Client Bundles (polyfills)
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
polyfills-HASH.js gzip 4.76 kB 4.76 kB
Overall change 4.76 kB 4.76 kB
Client Pages
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.js gzip 1.15 kB 1.15 kB
_error.js gzip 4.07 kB 4.07 kB
hooks.js gzip 779 B 779 B
index.js gzip 222 B 222 B
link.js gzip 2.89 kB 2.89 kB
routerDirect.js gzip 283 B 283 B
withRouter.js gzip 282 B 282 B
Overall change 9.68 kB 9.68 kB
Client Pages Modern
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_app.module.js gzip 576 B 576 B
_error.module.js gzip 3.06 kB 3.06 kB
hooks.module.js gzip 371 B 371 B
index.module.js gzip 212 B 212 B
link.module.js gzip 2.46 kB 2.46 kB
routerDirect..dule.js gzip 273 B 273 B
withRouter.m..dule.js gzip 272 B 272 B
Overall change 7.22 kB 7.22 kB
Client Build Manifests
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_buildManifest.js gzip 61 B 61 B
_buildManife..dule.js gzip 61 B 61 B
Overall change 122 B 122 B
Serverless bundles Overall increase ⚠️
zeit/next.js canary ijjk/next.js add/ssg-loading-state Change
_error.js gzip 46.5 kB 46.6 kB ⚠️ +135 B
404.html gzip 1.43 kB 1.45 kB ⚠️ +13 B
hooks.html gzip 1.07 kB 1.08 kB ⚠️ +12 B
index.js gzip 46.5 kB 46.7 kB ⚠️ +123 B
link.js gzip 72 kB 72.6 kB ⚠️ +624 B
routerDirect.js gzip 70.2 kB 70.8 kB ⚠️ +594 B
withRouter.js gzip 70 kB 70.6 kB ⚠️ +595 B
Overall change 308 kB 310 kB ⚠️ +2.1 kB

Commit: e647434

@timneutkens timneutkens merged commit 3099f08 into vercel:canary Feb 7, 2020
@timneutkens timneutkens deleted the add/ssg-loading-state branch February 7, 2020 13:09
chibicode pushed a commit to chibicode/next.js that referenced this pull request Feb 11, 2020
* Add initial SSG fallback handling

* Remove extra changes and update fallback handling

* Remove extra timeout for testing

* Update SSG tests in dynamic-routing suite

* Add racing to decide between rendering fallback and data

* Update size-limit test

* Update comment

* Make sure to follow correct route change order

* Make comment more verbose for racing

* Revert getStaticData to only return Promise

* Make sure to update URL on fallback

* Add retrying for data, de-dupe initial fallback request, and merge fallback replace

* Update to add preload for fallback pages data

* Add test for data preload link

* Use pre-built fallback in production mode

* Remove preload link for fallback from _document

* Update to make sure fallback is rendered correctly for serverless
@Timer Timer mentioned this pull request Feb 13, 2020
5 tasks
kodiakhq bot pushed a commit to vercel/vercel that referenced this pull request Feb 13, 2020
…ges (#3752)

This adds support for using the fallback file for dynamic (lazy) SSG pages to allow showing a loading state while the cache is populated with data. We can add tests for this behavior once the below referenced PR is shipped on canary

x-ref: vercel/next.js#10424

~Update: added tests now that fallback support has landed in Next.js although it appears `now-proxy` might need to be updated to revalidate the fallback correctly since the initial fallback is always being shown for lazy SSG pages with these changes~

Looks like this is working properly in `now-proxy` and we were overriding the prerender output with the static page output, thanks @juancampa for helping investigate! 🙏
@Timer Timer removed this from the 10.x.x milestone Nov 16, 2020
ofhouse pushed a commit to milliHQ/terraform-aws-next-js that referenced this pull request Mar 13, 2021
…ges (#3752)

This adds support for using the fallback file for dynamic (lazy) SSG pages to allow showing a loading state while the cache is populated with data. We can add tests for this behavior once the below referenced PR is shipped on canary

x-ref: vercel/next.js#10424

~Update: added tests now that fallback support has landed in Next.js although it appears `now-proxy` might need to be updated to revalidate the fallback correctly since the initial fallback is always being shown for lazy SSG pages with these changes~

Looks like this is working properly in `now-proxy` and we were overriding the prerender output with the static page output, thanks @juancampa for helping investigate! 🙏
@vercel vercel locked as resolved and limited conversation to collaborators Jan 29, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants