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 scroll restoration handling after render is complete #13914

Merged
merged 12 commits into from
Jun 9, 2020

Conversation

ijjk
Copy link
Member

@ijjk ijjk commented Jun 8, 2020

This adds scroll restoration handling to make sure the correct scroll position is restored after navigating back/forward to a page and the rendering hasn't completed by the time the default browser scroll restoration has taken place.

An initial failing test case was added which is working with the changes in this PR, if there are any other cases that should be added let me know and I can make sure we have them to ensure we don't regress on this behavior


Fixes #12530

@ijjk ijjk added this to the 9.4.5 milestone Jun 8, 2020
@ijjk ijjk added the type: next label Jun 8, 2020
@ijjk
Copy link
Member Author

ijjk commented Jun 8, 2020

Stats from current PR

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
buildDuration 11.5s 11.6s ⚠️ +109ms
nodeModulesSize 66 MB 66 MB ⚠️ +912 B
Page Load Tests Overall increase ✓
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
/ failed reqs 0 0
/ total time (seconds) 1.88 1.978 ⚠️ +0.1
/ avg req/sec 1329.65 1263.85 -65.8
/error-in-render failed reqs 0 0
/error-in-render total time (seconds) 1.195 1.109 -0.09
/error-in-render avg req/sec 2091.73 2254.87 ⚠️ +163.14
Client Bundles (main, webpack, commons) Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.js gzip 6.49 kB 6.49 kB
webpack-HASH.js gzip 746 B 746 B
de003c3a9d30..ec24.js gzip 10.5 kB 10.8 kB ⚠️ +256 B
framework.HASH.js gzip 39.1 kB 39.1 kB
Overall change 56.9 kB 57.2 kB ⚠️ +256 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.module.js gzip 5.58 kB 5.58 kB
webpack-HASH..dule.js gzip 746 B 746 B
de003c3a9d30..dule.js gzip 6.92 kB 7.2 kB ⚠️ +277 B
framework.HA..dule.js gzip 39.1 kB 39.1 kB
Overall change 52.4 kB 52.7 kB ⚠️ +277 B
Legacy Client Bundles (polyfills)
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
polyfills-HASH.js gzip 26.3 kB 26.3 kB
Overall change 26.3 kB 26.3 kB
Client Pages
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.js gzip 1.26 kB 1.26 kB
_error.js gzip 3.25 kB 3.25 kB
hooks.js gzip 881 B 881 B
index.js gzip 222 B 222 B
link.js gzip 2.05 kB 2.05 kB
routerDirect.js gzip 279 B 279 B
withRouter.js gzip 278 B 278 B
Overall change 8.22 kB 8.22 kB
Client Pages Modern
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.module.js gzip 604 B 604 B
_error.module.js gzip 2.04 kB 2.04 kB
hooks.module.js gzip 383 B 383 B
index.module.js gzip 223 B 223 B
link.module.js gzip 1.52 kB 1.52 kB
routerDirect..dule.js gzip 281 B 281 B
withRouter.m..dule.js gzip 278 B 278 B
Overall change 5.33 kB 5.33 kB
Client Build Manifests
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_buildManifest.js gzip 171 B 171 B
_buildManife..dule.js gzip 180 B 180 B
Overall change 351 B 351 B
Rendered Page Sizes Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
index.html gzip 901 B 901 B
link.html gzip 906 B 906 B
withRouter.html gzip 894 B 895 B ⚠️ +1 B
Overall change 2.7 kB 2.7 kB ⚠️ +1 B

Diffs

Diff for de003c3a9d30..492ddeda7.js
@@ -707,10 +707,50 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
 
       var _slicedToArray = __webpack_require__("J4zp");
 
+      var _defineProperty = __webpack_require__("lSNA");
+
       var _classCallCheck = __webpack_require__("lwsE");
 
       var _createClass = __webpack_require__("W8MJ");
 
+      function ownKeys(object, enumerableOnly) {
+        var keys = Object.keys(object);
+        if (Object.getOwnPropertySymbols) {
+          var symbols = Object.getOwnPropertySymbols(object);
+          if (enumerableOnly)
+            symbols = symbols.filter(function(sym) {
+              return Object.getOwnPropertyDescriptor(object, sym).enumerable;
+            });
+          keys.push.apply(keys, symbols);
+        }
+        return keys;
+      }
+
+      function _objectSpread(target) {
+        for (var i = 1; i < arguments.length; i++) {
+          var source = arguments[i] != null ? arguments[i] : {};
+          if (i % 2) {
+            ownKeys(Object(source), true).forEach(function(key) {
+              _defineProperty(target, key, source[key]);
+            });
+          } else if (Object.getOwnPropertyDescriptors) {
+            Object.defineProperties(
+              target,
+              Object.getOwnPropertyDescriptors(source)
+            );
+          } else {
+            ownKeys(Object(source)).forEach(function(key) {
+              Object.defineProperty(
+                target,
+                key,
+                Object.getOwnPropertyDescriptor(source, key)
+              );
+            });
+          }
+        }
+        return target;
+      }
+
       exports.__esModule = true;
       exports.addBasePath = addBasePath;
       exports.delBasePath = delBasePath;
@@ -1204,6 +1244,23 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                       }
 
                       Router.events.emit("beforeHistoryChange", as);
+                      var _history$state = history.state,
+                        curUrl = _history$state.url,
+                        curAs = _history$state.as,
+                        curOptions = _history$state.options;
+
+                      _this2.changeState(
+                        "replaceState",
+                        curUrl,
+                        curAs,
+                        _objectSpread(
+                          _objectSpread({}, curOptions),
+                          {},
+                          {
+                            scrollY: window.scrollY
+                          }
+                        )
+                      );
 
                       _this2.changeState(method, url, as, options);
 
@@ -1220,6 +1277,11 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                           }
 
                           Router.events.emit("routeChangeComplete", as);
+
+                          if (options.scrollY) {
+                            window.scrollTo(0, options.scrollY);
+                          }
+
                           return resolve(true);
                         });
                     }, reject);
@@ -2005,6 +2067,27 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
       /***/
     },
 
+    /***/ lSNA: /***/ function(module, exports) {
+      function _defineProperty(obj, key, value) {
+        if (key in obj) {
+          Object.defineProperty(obj, key, {
+            value: value,
+            enumerable: true,
+            configurable: true,
+            writable: true
+          });
+        } else {
+          obj[key] = value;
+        }
+
+        return obj;
+      }
+
+      module.exports = _defineProperty;
+
+      /***/
+    },
+
     /***/ ls82: /***/ function(module, exports, __webpack_require__) {
       /**
        * Copyright (c) 2014-present, Facebook, Inc.
Diff for de003c3a9d30..36.module.js
@@ -583,6 +583,46 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
     /***/ elyg: /***/ function(module, exports, __webpack_require__) {
       "use strict";
 
+      var _defineProperty = __webpack_require__("lSNA");
+
+      function ownKeys(object, enumerableOnly) {
+        var keys = Object.keys(object);
+        if (Object.getOwnPropertySymbols) {
+          var symbols = Object.getOwnPropertySymbols(object);
+          if (enumerableOnly)
+            symbols = symbols.filter(function(sym) {
+              return Object.getOwnPropertyDescriptor(object, sym).enumerable;
+            });
+          keys.push.apply(keys, symbols);
+        }
+        return keys;
+      }
+
+      function _objectSpread(target) {
+        for (var i = 1; i < arguments.length; i++) {
+          var source = arguments[i] != null ? arguments[i] : {};
+          if (i % 2) {
+            ownKeys(Object(source), true).forEach(function(key) {
+              _defineProperty(target, key, source[key]);
+            });
+          } else if (Object.getOwnPropertyDescriptors) {
+            Object.defineProperties(
+              target,
+              Object.getOwnPropertyDescriptors(source)
+            );
+          } else {
+            ownKeys(Object(source)).forEach(function(key) {
+              Object.defineProperty(
+                target,
+                key,
+                Object.getOwnPropertyDescriptor(source, key)
+              );
+            });
+          }
+        }
+        return target;
+      }
+
       exports.__esModule = true;
       exports.addBasePath = addBasePath;
       exports.delBasePath = delBasePath;
@@ -1036,6 +1076,23 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                 }
 
                 Router.events.emit("beforeHistoryChange", as);
+                var {
+                  url: curUrl,
+                  as: curAs,
+                  options: curOptions
+                } = history.state;
+                this.changeState(
+                  "replaceState",
+                  curUrl,
+                  curAs,
+                  _objectSpread(
+                    _objectSpread({}, curOptions),
+                    {},
+                    {
+                      scrollY: window.scrollY
+                    }
+                  )
+                );
                 this.changeState(method, url, as, options);
 
                 if (false) {
@@ -1049,6 +1106,11 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                   }
 
                   Router.events.emit("routeChangeComplete", as);
+
+                  if (options.scrollY) {
+                    window.scrollTo(0, options.scrollY);
+                  }
+
                   return resolve(true);
                 });
               },
@@ -1647,6 +1709,27 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
       /***/
     },
 
+    /***/ lSNA: /***/ function(module, exports) {
+      function _defineProperty(obj, key, value) {
+        if (key in obj) {
+          Object.defineProperty(obj, key, {
+            value: value,
+            enumerable: true,
+            configurable: true,
+            writable: true
+          });
+        } else {
+          obj[key] = value;
+        }
+
+        return obj;
+      }
+
+      module.exports = _defineProperty;
+
+      /***/
+    },
+
     /***/ nOHt: /***/ function(module, exports, __webpack_require__) {
       "use strict";
Diff for index.html
@@ -18,7 +18,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c8db6e7351695637e7ad.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -105,13 +105,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.22a0a091d06492ddeda7.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c31f3e0b9847c99f2340.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c8db6e7351695637e7ad.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
Diff for link.html
@@ -18,7 +18,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c8db6e7351695637e7ad.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -110,13 +110,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.22a0a091d06492ddeda7.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c31f3e0b9847c99f2340.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c8db6e7351695637e7ad.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
Diff for withRouter.html
@@ -18,7 +18,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c8db6e7351695637e7ad.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -105,13 +105,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.22a0a091d06492ddeda7.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c31f3e0b9847c99f2340.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c8db6e7351695637e7ad.module.js"
       async=""
       crossorigin="anonymous"
       type="module"

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
buildDuration 12.5s 12.7s ⚠️ +199ms
nodeModulesSize 66 MB 66 MB ⚠️ +912 B
Client Bundles (main, webpack, commons) Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.js gzip 6.49 kB 6.49 kB
webpack-HASH.js gzip 746 B 746 B
de003c3a9d30..ec24.js gzip 10.5 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..3fb8.js gzip N/A 10.8 kB N/A
Overall change 56.9 kB 57.2 kB ⚠️ +256 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.module.js gzip 5.58 kB 5.58 kB
webpack-HASH..dule.js gzip 746 B 746 B
de003c3a9d30..dule.js gzip 6.92 kB N/A N/A
framework.HA..dule.js gzip 39.1 kB 39.1 kB
de003c3a9d30..dule.js gzip N/A 7.2 kB N/A
Overall change 52.4 kB 52.7 kB ⚠️ +277 B
Legacy Client Bundles (polyfills)
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
polyfills-HASH.js gzip 26.3 kB 26.3 kB
Overall change 26.3 kB 26.3 kB
Client Pages
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.js gzip 1.26 kB 1.26 kB
_error.js gzip 3.25 kB 3.25 kB
hooks.js gzip 881 B 881 B
index.js gzip 222 B 222 B
link.js gzip 2.05 kB 2.05 kB
routerDirect.js gzip 279 B 279 B
withRouter.js gzip 278 B 278 B
Overall change 8.22 kB 8.22 kB
Client Pages Modern
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.module.js gzip 604 B 604 B
_error.module.js gzip 2.04 kB 2.04 kB
hooks.module.js gzip 383 B 383 B
index.module.js gzip 223 B 223 B
link.module.js gzip 1.52 kB 1.52 kB
routerDirect..dule.js gzip 281 B 281 B
withRouter.m..dule.js gzip 278 B 278 B
Overall change 5.33 kB 5.33 kB
Client Build Manifests
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_buildManifest.js gzip 171 B 171 B
_buildManife..dule.js gzip 180 B 180 B
Overall change 351 B 351 B
Serverless bundles Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_error.js 874 kB 874 kB
404.html 4.13 kB 4.13 kB
hooks.html 3.71 kB 3.71 kB
index.js 875 kB 875 kB
link.js 913 kB 914 kB ⚠️ +1.46 kB
routerDirect.js 905 kB 907 kB ⚠️ +1.46 kB
withRouter.js 905 kB 907 kB ⚠️ +1.46 kB
Overall change 4.48 MB 4.48 MB ⚠️ +4.37 kB

Copy link
Member

@Timer Timer left a comment

Choose a reason for hiding this comment

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

  1. We need to consider both X and Y state.
  2. This will fight with the browser's default behavior. We need to feature detect this via 'scrollRestoration' in window.history & set window.history.scrollRestoration = 'manual'.

@ijjk ijjk requested a review from Timer June 8, 2020 20:44
@ijjk

This comment has been minimized.

@ijjk
Copy link
Member Author

ijjk commented Jun 8, 2020

Stats from current PR

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
buildDuration 12.3s 12.4s ⚠️ +80ms
nodeModulesSize 66 MB 66 MB ⚠️ +2.2 kB
Page Load Tests Overall increase ✓
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
/ failed reqs 0 0
/ total time (seconds) 2.191 2.137 -0.05
/ avg req/sec 1141.09 1169.83 ⚠️ +28.74
/error-in-render failed reqs 0 0
/error-in-render total time (seconds) 1.404 1.35 -0.05
/error-in-render avg req/sec 1780.84 1851.64 ⚠️ +70.8
Client Bundles (main, webpack, commons) Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.js gzip 6.49 kB 6.49 kB
webpack-HASH.js gzip 746 B 746 B
de003c3a9d30..ec24.js gzip 10.5 kB 10.9 kB ⚠️ +322 B
framework.HASH.js gzip 39.1 kB 39.1 kB
Overall change 56.9 kB 57.2 kB ⚠️ +322 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.module.js gzip 5.58 kB 5.58 kB
webpack-HASH..dule.js gzip 746 B 746 B
de003c3a9d30..dule.js gzip 6.92 kB 7.26 kB ⚠️ +338 B
framework.HA..dule.js gzip 39.1 kB 39.1 kB
Overall change 52.4 kB 52.7 kB ⚠️ +338 B
Legacy Client Bundles (polyfills)
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
polyfills-HASH.js gzip 26.3 kB 26.3 kB
Overall change 26.3 kB 26.3 kB
Client Pages
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.js gzip 1.26 kB 1.26 kB
_error.js gzip 3.25 kB 3.25 kB
hooks.js gzip 881 B 881 B
index.js gzip 222 B 222 B
link.js gzip 2.05 kB 2.05 kB
routerDirect.js gzip 279 B 279 B
withRouter.js gzip 278 B 278 B
Overall change 8.22 kB 8.22 kB
Client Pages Modern
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.module.js gzip 604 B 604 B
_error.module.js gzip 2.04 kB 2.04 kB
hooks.module.js gzip 383 B 383 B
index.module.js gzip 223 B 223 B
link.module.js gzip 1.52 kB 1.52 kB
routerDirect..dule.js gzip 281 B 281 B
withRouter.m..dule.js gzip 278 B 278 B
Overall change 5.33 kB 5.33 kB
Client Build Manifests
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_buildManifest.js gzip 171 B 171 B
_buildManife..dule.js gzip 180 B 180 B
Overall change 351 B 351 B
Rendered Page Sizes Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
index.html gzip 901 B 901 B
link.html gzip 906 B 907 B ⚠️ +1 B
withRouter.html gzip 894 B 894 B
Overall change 2.7 kB 2.7 kB ⚠️ +1 B

Diffs

Diff for de003c3a9d30..492ddeda7.js
@@ -707,10 +707,50 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
 
       var _slicedToArray = __webpack_require__("J4zp");
 
+      var _defineProperty = __webpack_require__("lSNA");
+
       var _classCallCheck = __webpack_require__("lwsE");
 
       var _createClass = __webpack_require__("W8MJ");
 
+      function ownKeys(object, enumerableOnly) {
+        var keys = Object.keys(object);
+        if (Object.getOwnPropertySymbols) {
+          var symbols = Object.getOwnPropertySymbols(object);
+          if (enumerableOnly)
+            symbols = symbols.filter(function(sym) {
+              return Object.getOwnPropertyDescriptor(object, sym).enumerable;
+            });
+          keys.push.apply(keys, symbols);
+        }
+        return keys;
+      }
+
+      function _objectSpread(target) {
+        for (var i = 1; i < arguments.length; i++) {
+          var source = arguments[i] != null ? arguments[i] : {};
+          if (i % 2) {
+            ownKeys(Object(source), true).forEach(function(key) {
+              _defineProperty(target, key, source[key]);
+            });
+          } else if (Object.getOwnPropertyDescriptors) {
+            Object.defineProperties(
+              target,
+              Object.getOwnPropertyDescriptors(source)
+            );
+          } else {
+            ownKeys(Object(source)).forEach(function(key) {
+              Object.defineProperty(
+                target,
+                key,
+                Object.getOwnPropertyDescriptor(source, key)
+              );
+            });
+          }
+        }
+        return target;
+      }
+
       exports.__esModule = true;
       exports.addBasePath = addBasePath;
       exports.delBasePath = delBasePath;
@@ -770,6 +810,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
         };
       }
 
+      var manualScrollRestoration =
+        true && "scrollRestoration" in window.history;
+
       function fetchNextData(pathname, query, isServerRender, cb) {
         var attempts = isServerRender ? 3 : 1;
 
@@ -989,7 +1032,12 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
               );
             }
 
-            window.addEventListener("popstate", this.onPopState);
+            window.addEventListener("popstate", this.onPopState); // enable custom scroll restoration handling when available
+            // otherwise fallback to browser's default handling
+
+            if (manualScrollRestoration) {
+              window.history.scrollRestoration = "manual";
+            }
           }
         } // @deprecated backwards compatibility even though it's a private method.
 
@@ -1205,6 +1253,27 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
 
                       Router.events.emit("beforeHistoryChange", as);
 
+                      if (manualScrollRestoration && history.state) {
+                        var _history$state = history.state,
+                          curUrl = _history$state.url,
+                          curAs = _history$state.as,
+                          curOptions = _history$state.options;
+
+                        _this2.changeState(
+                          "replaceState",
+                          curUrl,
+                          curAs,
+                          _objectSpread(
+                            _objectSpread({}, curOptions),
+                            {},
+                            {
+                              _N_X: window.scrollX,
+                              _N_Y: window.scrollY
+                            }
+                          )
+                        );
+                      }
+
                       _this2.changeState(method, url, as, options);
 
                       if (false) {
@@ -1220,6 +1289,11 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                           }
 
                           Router.events.emit("routeChangeComplete", as);
+
+                          if (manualScrollRestoration && "_N_X" in options) {
+                            window.scrollTo(options._N_X, options._N_Y);
+                          }
+
                           return resolve(true);
                         });
                     }, reject);
@@ -2005,6 +2079,27 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
       /***/
     },
 
+    /***/ lSNA: /***/ function(module, exports) {
+      function _defineProperty(obj, key, value) {
+        if (key in obj) {
+          Object.defineProperty(obj, key, {
+            value: value,
+            enumerable: true,
+            configurable: true,
+            writable: true
+          });
+        } else {
+          obj[key] = value;
+        }
+
+        return obj;
+      }
+
+      module.exports = _defineProperty;
+
+      /***/
+    },
+
     /***/ ls82: /***/ function(module, exports, __webpack_require__) {
       /**
        * Copyright (c) 2014-present, Facebook, Inc.
Diff for de003c3a9d30..36.module.js
@@ -583,6 +583,46 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
     /***/ elyg: /***/ function(module, exports, __webpack_require__) {
       "use strict";
 
+      var _defineProperty = __webpack_require__("lSNA");
+
+      function ownKeys(object, enumerableOnly) {
+        var keys = Object.keys(object);
+        if (Object.getOwnPropertySymbols) {
+          var symbols = Object.getOwnPropertySymbols(object);
+          if (enumerableOnly)
+            symbols = symbols.filter(function(sym) {
+              return Object.getOwnPropertyDescriptor(object, sym).enumerable;
+            });
+          keys.push.apply(keys, symbols);
+        }
+        return keys;
+      }
+
+      function _objectSpread(target) {
+        for (var i = 1; i < arguments.length; i++) {
+          var source = arguments[i] != null ? arguments[i] : {};
+          if (i % 2) {
+            ownKeys(Object(source), true).forEach(function(key) {
+              _defineProperty(target, key, source[key]);
+            });
+          } else if (Object.getOwnPropertyDescriptors) {
+            Object.defineProperties(
+              target,
+              Object.getOwnPropertyDescriptors(source)
+            );
+          } else {
+            ownKeys(Object(source)).forEach(function(key) {
+              Object.defineProperty(
+                target,
+                key,
+                Object.getOwnPropertyDescriptor(source, key)
+              );
+            });
+          }
+        }
+        return target;
+      }
+
       exports.__esModule = true;
       exports.addBasePath = addBasePath;
       exports.delBasePath = delBasePath;
@@ -641,6 +681,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
         };
       }
 
+      var manualScrollRestoration =
+        true && "scrollRestoration" in window.history;
+
       function fetchNextData(pathname, query, isServerRender, cb) {
         var attempts = isServerRender ? 3 : 1;
 
@@ -851,7 +894,12 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
               );
             }
 
-            window.addEventListener("popstate", this.onPopState);
+            window.addEventListener("popstate", this.onPopState); // enable custom scroll restoration handling when available
+            // otherwise fallback to browser's default handling
+
+            if (manualScrollRestoration) {
+              window.history.scrollRestoration = "manual";
+            }
           }
         } // @deprecated backwards compatibility even though it's a private method.
 
@@ -1036,6 +1084,28 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                 }
 
                 Router.events.emit("beforeHistoryChange", as);
+
+                if (manualScrollRestoration && history.state) {
+                  var {
+                    url: curUrl,
+                    as: curAs,
+                    options: curOptions
+                  } = history.state;
+                  this.changeState(
+                    "replaceState",
+                    curUrl,
+                    curAs,
+                    _objectSpread(
+                      _objectSpread({}, curOptions),
+                      {},
+                      {
+                        _N_X: window.scrollX,
+                        _N_Y: window.scrollY
+                      }
+                    )
+                  );
+                }
+
                 this.changeState(method, url, as, options);
 
                 if (false) {
@@ -1049,6 +1119,11 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                   }
 
                   Router.events.emit("routeChangeComplete", as);
+
+                  if (manualScrollRestoration && "_N_X" in options) {
+                    window.scrollTo(options._N_X, options._N_Y);
+                  }
+
                   return resolve(true);
                 });
               },
@@ -1647,6 +1722,27 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
       /***/
     },
 
+    /***/ lSNA: /***/ function(module, exports) {
+      function _defineProperty(obj, key, value) {
+        if (key in obj) {
+          Object.defineProperty(obj, key, {
+            value: value,
+            enumerable: true,
+            configurable: true,
+            writable: true
+          });
+        } else {
+          obj[key] = value;
+        }
+
+        return obj;
+      }
+
+      module.exports = _defineProperty;
+
+      /***/
+    },
+
     /***/ nOHt: /***/ function(module, exports, __webpack_require__) {
       "use strict";
Diff for index.html
@@ -18,7 +18,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -105,13 +105,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.22a0a091d06492ddeda7.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.7d58880f5e575b3ee36f.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
Diff for link.html
@@ -18,7 +18,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -110,13 +110,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.22a0a091d06492ddeda7.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.7d58880f5e575b3ee36f.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
Diff for withRouter.html
@@ -18,7 +18,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -105,13 +105,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.22a0a091d06492ddeda7.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.7d58880f5e575b3ee36f.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       async=""
       crossorigin="anonymous"
       type="module"

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
buildDuration 12.9s 12.7s -185ms
nodeModulesSize 66 MB 66 MB ⚠️ +2.2 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.js gzip 6.49 kB 6.49 kB
webpack-HASH.js gzip 746 B 746 B
de003c3a9d30..ec24.js gzip 10.5 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..4b11.js gzip N/A 10.9 kB N/A
Overall change 56.9 kB 57.2 kB ⚠️ +322 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.module.js gzip 5.58 kB 5.58 kB
webpack-HASH..dule.js gzip 746 B 746 B
de003c3a9d30..dule.js gzip 6.92 kB N/A N/A
framework.HA..dule.js gzip 39.1 kB 39.1 kB
de003c3a9d30..dule.js gzip N/A 7.26 kB N/A
Overall change 52.4 kB 52.7 kB ⚠️ +338 B
Legacy Client Bundles (polyfills)
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
polyfills-HASH.js gzip 26.3 kB 26.3 kB
Overall change 26.3 kB 26.3 kB
Client Pages
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.js gzip 1.26 kB 1.26 kB
_error.js gzip 3.25 kB 3.25 kB
hooks.js gzip 881 B 881 B
index.js gzip 222 B 222 B
link.js gzip 2.05 kB 2.05 kB
routerDirect.js gzip 279 B 279 B
withRouter.js gzip 278 B 278 B
Overall change 8.22 kB 8.22 kB
Client Pages Modern
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.module.js gzip 604 B 604 B
_error.module.js gzip 2.04 kB 2.04 kB
hooks.module.js gzip 383 B 383 B
index.module.js gzip 223 B 223 B
link.module.js gzip 1.52 kB 1.52 kB
routerDirect..dule.js gzip 281 B 281 B
withRouter.m..dule.js gzip 278 B 278 B
Overall change 5.33 kB 5.33 kB
Client Build Manifests
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_buildManifest.js gzip 171 B 171 B
_buildManife..dule.js gzip 180 B 180 B
Overall change 351 B 351 B
Serverless bundles Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_error.js 874 kB 874 kB
404.html 4.13 kB 4.13 kB
hooks.html 3.71 kB 3.71 kB
index.js 875 kB 875 kB
link.js 913 kB 914 kB ⚠️ +1.66 kB
routerDirect.js 905 kB 907 kB ⚠️ +1.66 kB
withRouter.js 905 kB 907 kB ⚠️ +1.66 kB
Overall change 4.48 MB 4.49 MB ⚠️ +4.98 kB

@ijjk

This comment has been minimized.

@ijjk
Copy link
Member Author

ijjk commented Jun 9, 2020

Stats from current PR

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
buildDuration 13s 12.7s -326ms
nodeModulesSize 64.9 MB 64.9 MB ⚠️ +2.37 kB
Page Load Tests Overall increase ✓
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
/ failed reqs 0 0
/ total time (seconds) 2.194 2.179 -0.02
/ avg req/sec 1139.48 1147.29 ⚠️ +7.81
/error-in-render failed reqs 0 0
/error-in-render total time (seconds) 1.448 1.355 -0.09
/error-in-render avg req/sec 1726.06 1845.22 ⚠️ +119.16
Client Bundles (main, webpack, commons) Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.js gzip 6.49 kB 6.49 kB
webpack-HASH.js gzip 746 B 746 B
de003c3a9d30..ec24.js gzip 10.5 kB 10.9 kB ⚠️ +342 B
framework.HASH.js gzip 39.1 kB 39.1 kB
Overall change 56.9 kB 57.3 kB ⚠️ +342 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.module.js gzip 5.58 kB 5.58 kB
webpack-HASH..dule.js gzip 746 B 746 B
de003c3a9d30..dule.js gzip 6.92 kB 7.28 kB ⚠️ +357 B
framework.HA..dule.js gzip 39.1 kB 39.1 kB
Overall change 52.4 kB 52.8 kB ⚠️ +357 B
Legacy Client Bundles (polyfills)
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
polyfills-HASH.js gzip 26.3 kB 26.3 kB
Overall change 26.3 kB 26.3 kB
Client Pages
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.js gzip 1.26 kB 1.26 kB
_error.js gzip 3.25 kB 3.25 kB
hooks.js gzip 881 B 881 B
index.js gzip 222 B 222 B
link.js gzip 2.05 kB 2.05 kB
routerDirect.js gzip 279 B 279 B
withRouter.js gzip 278 B 278 B
Overall change 8.22 kB 8.22 kB
Client Pages Modern
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.module.js gzip 604 B 604 B
_error.module.js gzip 2.04 kB 2.04 kB
hooks.module.js gzip 383 B 383 B
index.module.js gzip 223 B 223 B
link.module.js gzip 1.52 kB 1.52 kB
routerDirect..dule.js gzip 281 B 281 B
withRouter.m..dule.js gzip 278 B 278 B
Overall change 5.33 kB 5.33 kB
Client Build Manifests
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_buildManifest.js gzip 171 B 171 B
_buildManife..dule.js gzip 180 B 180 B
Overall change 351 B 351 B
Rendered Page Sizes Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
index.html gzip 901 B 901 B
link.html gzip 906 B 906 B
withRouter.html gzip 894 B 895 B ⚠️ +1 B
Overall change 2.7 kB 2.7 kB ⚠️ +1 B

Diffs

Diff for de003c3a9d30..492ddeda7.js
@@ -707,10 +707,50 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
 
       var _slicedToArray = __webpack_require__("J4zp");
 
+      var _defineProperty = __webpack_require__("lSNA");
+
       var _classCallCheck = __webpack_require__("lwsE");
 
       var _createClass = __webpack_require__("W8MJ");
 
+      function ownKeys(object, enumerableOnly) {
+        var keys = Object.keys(object);
+        if (Object.getOwnPropertySymbols) {
+          var symbols = Object.getOwnPropertySymbols(object);
+          if (enumerableOnly)
+            symbols = symbols.filter(function(sym) {
+              return Object.getOwnPropertyDescriptor(object, sym).enumerable;
+            });
+          keys.push.apply(keys, symbols);
+        }
+        return keys;
+      }
+
+      function _objectSpread(target) {
+        for (var i = 1; i < arguments.length; i++) {
+          var source = arguments[i] != null ? arguments[i] : {};
+          if (i % 2) {
+            ownKeys(Object(source), true).forEach(function(key) {
+              _defineProperty(target, key, source[key]);
+            });
+          } else if (Object.getOwnPropertyDescriptors) {
+            Object.defineProperties(
+              target,
+              Object.getOwnPropertyDescriptors(source)
+            );
+          } else {
+            ownKeys(Object(source)).forEach(function(key) {
+              Object.defineProperty(
+                target,
+                key,
+                Object.getOwnPropertyDescriptor(source, key)
+              );
+            });
+          }
+        }
+        return target;
+      }
+
       exports.__esModule = true;
       exports.addBasePath = addBasePath;
       exports.delBasePath = delBasePath;
@@ -770,6 +810,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
         };
       }
 
+      var manualScrollRestoration =
+        true && "scrollRestoration" in window.history;
+
       function fetchNextData(pathname, query, isServerRender, cb) {
         var attempts = isServerRender ? 3 : 1;
 
@@ -989,7 +1032,12 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
               );
             }
 
-            window.addEventListener("popstate", this.onPopState);
+            window.addEventListener("popstate", this.onPopState); // enable custom scroll restoration handling when available
+            // otherwise fallback to browser's default handling
+
+            if (manualScrollRestoration) {
+              window.history.scrollRestoration = "manual";
+            }
           }
         } // @deprecated backwards compatibility even though it's a private method.
 
@@ -1205,6 +1253,27 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
 
                       Router.events.emit("beforeHistoryChange", as);
 
+                      if (manualScrollRestoration && history.state) {
+                        var _history$state = history.state,
+                          curUrl = _history$state.url,
+                          curAs = _history$state.as,
+                          curOptions = _history$state.options;
+
+                        _this2.changeState(
+                          "replaceState",
+                          curUrl,
+                          curAs,
+                          _objectSpread(
+                            _objectSpread({}, curOptions),
+                            {},
+                            {
+                              _N_X: window.scrollX,
+                              _N_Y: window.scrollY
+                            }
+                          )
+                        );
+                      }
+
                       _this2.changeState(method, url, as, options);
 
                       if (false) {
@@ -1220,6 +1289,13 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                           }
 
                           Router.events.emit("routeChangeComplete", as);
+
+                          if (manualScrollRestoration && "_N_X" in options) {
+                            requestAnimationFrame(function() {
+                              window.scrollTo(options._N_X, options._N_Y);
+                            });
+                          }
+
                           return resolve(true);
                         });
                     }, reject);
@@ -2005,6 +2081,27 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
       /***/
     },
 
+    /***/ lSNA: /***/ function(module, exports) {
+      function _defineProperty(obj, key, value) {
+        if (key in obj) {
+          Object.defineProperty(obj, key, {
+            value: value,
+            enumerable: true,
+            configurable: true,
+            writable: true
+          });
+        } else {
+          obj[key] = value;
+        }
+
+        return obj;
+      }
+
+      module.exports = _defineProperty;
+
+      /***/
+    },
+
     /***/ ls82: /***/ function(module, exports, __webpack_require__) {
       /**
        * Copyright (c) 2014-present, Facebook, Inc.
Diff for de003c3a9d30..36.module.js
@@ -583,6 +583,46 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
     /***/ elyg: /***/ function(module, exports, __webpack_require__) {
       "use strict";
 
+      var _defineProperty = __webpack_require__("lSNA");
+
+      function ownKeys(object, enumerableOnly) {
+        var keys = Object.keys(object);
+        if (Object.getOwnPropertySymbols) {
+          var symbols = Object.getOwnPropertySymbols(object);
+          if (enumerableOnly)
+            symbols = symbols.filter(function(sym) {
+              return Object.getOwnPropertyDescriptor(object, sym).enumerable;
+            });
+          keys.push.apply(keys, symbols);
+        }
+        return keys;
+      }
+
+      function _objectSpread(target) {
+        for (var i = 1; i < arguments.length; i++) {
+          var source = arguments[i] != null ? arguments[i] : {};
+          if (i % 2) {
+            ownKeys(Object(source), true).forEach(function(key) {
+              _defineProperty(target, key, source[key]);
+            });
+          } else if (Object.getOwnPropertyDescriptors) {
+            Object.defineProperties(
+              target,
+              Object.getOwnPropertyDescriptors(source)
+            );
+          } else {
+            ownKeys(Object(source)).forEach(function(key) {
+              Object.defineProperty(
+                target,
+                key,
+                Object.getOwnPropertyDescriptor(source, key)
+              );
+            });
+          }
+        }
+        return target;
+      }
+
       exports.__esModule = true;
       exports.addBasePath = addBasePath;
       exports.delBasePath = delBasePath;
@@ -641,6 +681,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
         };
       }
 
+      var manualScrollRestoration =
+        true && "scrollRestoration" in window.history;
+
       function fetchNextData(pathname, query, isServerRender, cb) {
         var attempts = isServerRender ? 3 : 1;
 
@@ -851,7 +894,12 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
               );
             }
 
-            window.addEventListener("popstate", this.onPopState);
+            window.addEventListener("popstate", this.onPopState); // enable custom scroll restoration handling when available
+            // otherwise fallback to browser's default handling
+
+            if (manualScrollRestoration) {
+              window.history.scrollRestoration = "manual";
+            }
           }
         } // @deprecated backwards compatibility even though it's a private method.
 
@@ -1036,6 +1084,28 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                 }
 
                 Router.events.emit("beforeHistoryChange", as);
+
+                if (manualScrollRestoration && history.state) {
+                  var {
+                    url: curUrl,
+                    as: curAs,
+                    options: curOptions
+                  } = history.state;
+                  this.changeState(
+                    "replaceState",
+                    curUrl,
+                    curAs,
+                    _objectSpread(
+                      _objectSpread({}, curOptions),
+                      {},
+                      {
+                        _N_X: window.scrollX,
+                        _N_Y: window.scrollY
+                      }
+                    )
+                  );
+                }
+
                 this.changeState(method, url, as, options);
 
                 if (false) {
@@ -1049,6 +1119,13 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                   }
 
                   Router.events.emit("routeChangeComplete", as);
+
+                  if (manualScrollRestoration && "_N_X" in options) {
+                    requestAnimationFrame(() => {
+                      window.scrollTo(options._N_X, options._N_Y);
+                    });
+                  }
+
                   return resolve(true);
                 });
               },
@@ -1647,6 +1724,27 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
       /***/
     },
 
+    /***/ lSNA: /***/ function(module, exports) {
+      function _defineProperty(obj, key, value) {
+        if (key in obj) {
+          Object.defineProperty(obj, key, {
+            value: value,
+            enumerable: true,
+            configurable: true,
+            writable: true
+          });
+        } else {
+          obj[key] = value;
+        }
+
+        return obj;
+      }
+
+      module.exports = _defineProperty;
+
+      /***/
+    },
+
     /***/ nOHt: /***/ function(module, exports, __webpack_require__) {
       "use strict";
Diff for index.html
@@ -18,7 +18,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.5eb473ef2cfbfc2f2003.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -105,13 +105,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.22a0a091d06492ddeda7.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.84c6e2281231b4a6fe2e.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.5eb473ef2cfbfc2f2003.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
Diff for link.html
@@ -18,7 +18,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.5eb473ef2cfbfc2f2003.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -110,13 +110,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.22a0a091d06492ddeda7.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.84c6e2281231b4a6fe2e.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.5eb473ef2cfbfc2f2003.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
Diff for withRouter.html
@@ -18,7 +18,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.5eb473ef2cfbfc2f2003.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -105,13 +105,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.22a0a091d06492ddeda7.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.84c6e2281231b4a6fe2e.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.5eb473ef2cfbfc2f2003.module.js"
       async=""
       crossorigin="anonymous"
       type="module"

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
buildDuration 13.9s 13.7s -271ms
nodeModulesSize 64.9 MB 64.9 MB ⚠️ +2.37 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.js gzip 6.49 kB 6.49 kB
webpack-HASH.js gzip 746 B 746 B
de003c3a9d30..ec24.js gzip 10.5 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..43e8.js gzip N/A 10.9 kB N/A
Overall change 56.9 kB 57.3 kB ⚠️ +342 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.module.js gzip 5.58 kB 5.58 kB
webpack-HASH..dule.js gzip 746 B 746 B
de003c3a9d30..dule.js gzip 6.92 kB N/A N/A
framework.HA..dule.js gzip 39.1 kB 39.1 kB
de003c3a9d30..dule.js gzip N/A 7.28 kB N/A
Overall change 52.4 kB 52.8 kB ⚠️ +357 B
Legacy Client Bundles (polyfills)
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
polyfills-HASH.js gzip 26.3 kB 26.3 kB
Overall change 26.3 kB 26.3 kB
Client Pages
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.js gzip 1.26 kB 1.26 kB
_error.js gzip 3.25 kB 3.25 kB
hooks.js gzip 881 B 881 B
index.js gzip 222 B 222 B
link.js gzip 2.05 kB 2.05 kB
routerDirect.js gzip 279 B 279 B
withRouter.js gzip 278 B 278 B
Overall change 8.22 kB 8.22 kB
Client Pages Modern
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.module.js gzip 604 B 604 B
_error.module.js gzip 2.04 kB 2.04 kB
hooks.module.js gzip 383 B 383 B
index.module.js gzip 223 B 223 B
link.module.js gzip 1.52 kB 1.52 kB
routerDirect..dule.js gzip 281 B 281 B
withRouter.m..dule.js gzip 278 B 278 B
Overall change 5.33 kB 5.33 kB
Client Build Manifests
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_buildManifest.js gzip 171 B 171 B
_buildManife..dule.js gzip 180 B 180 B
Overall change 351 B 351 B
Serverless bundles Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_error.js 874 kB 874 kB
404.html 4.13 kB 4.13 kB
hooks.html 3.71 kB 3.71 kB
index.js 875 kB 875 kB
link.js 913 kB 915 kB ⚠️ +1.72 kB
routerDirect.js 905 kB 907 kB ⚠️ +1.72 kB
withRouter.js 905 kB 907 kB ⚠️ +1.72 kB
Overall change 4.48 MB 4.49 MB ⚠️ +5.16 kB

@ijjk
Copy link
Member Author

ijjk commented Jun 9, 2020

Failing test suites

test/integration/scroll-restoration/test/index.test.js

  • Scroll Restoration Support > dev mode > should restore the scroll position on navigating back
  • Scroll Restoration Support > server mode > should restore the scroll position on navigating back
  • Scroll Restoration Support > serverless mode > should restore the scroll position on navigating back
Expand output

● Scroll Restoration Support › dev mode › should restore the scroll position on navigating back

expect(received).toBe(expected) // Object.is equality

Expected: 5015
Received: 5008

  44 |     const newScrollX = await browser.eval(() => window.scrollX)
  45 |     const newScrollY = await browser.eval(() => window.scrollY)
> 46 |     expect(scrollX).toBe(newScrollX)
     |                     ^
  47 |     expect(scrollY).toBe(newScrollY)
  48 |   })
  49 | }

  at Object.<anonymous> (integration/scroll-restoration/test/index.test.js:46:21)

● Scroll Restoration Support › server mode › should restore the scroll position on navigating back

expect(received).toBe(expected) // Object.is equality

Expected: 5015
Received: 5008

  44 |     const newScrollX = await browser.eval(() => window.scrollX)
  45 |     const newScrollY = await browser.eval(() => window.scrollY)
> 46 |     expect(scrollX).toBe(newScrollX)
     |                     ^
  47 |     expect(scrollY).toBe(newScrollY)
  48 |   })
  49 | }

  at Object.<anonymous> (integration/scroll-restoration/test/index.test.js:46:21)

● Scroll Restoration Support › serverless mode › should restore the scroll position on navigating back

expect(received).toBe(expected) // Object.is equality

Expected: 5015
Received: 5008

  44 |     const newScrollX = await browser.eval(() => window.scrollX)
  45 |     const newScrollY = await browser.eval(() => window.scrollY)
> 46 |     expect(scrollX).toBe(newScrollX)
     |                     ^
  47 |     expect(scrollY).toBe(newScrollY)
  48 |   })
  49 | }

  at Object.<anonymous> (integration/scroll-restoration/test/index.test.js:46:21)

@ijjk
Copy link
Member Author

ijjk commented Jun 9, 2020

Stats from current PR

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
buildDuration 12.8s 12.7s -134ms
nodeModulesSize 64.9 MB 64.9 MB ⚠️ +2.2 kB
Page Load Tests Overall decrease ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
/ failed reqs 0 0
/ total time (seconds) 2.153 2.149 0
/ avg req/sec 1160.92 1163.26 ⚠️ +2.34
/error-in-render failed reqs 0 0
/error-in-render total time (seconds) 1.426 1.435 ⚠️ +0.01
/error-in-render avg req/sec 1753.37 1742.66 -10.71
Client Bundles (main, webpack, commons) Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.js gzip 6.49 kB 6.49 kB
webpack-HASH.js gzip 746 B 746 B
de003c3a9d30..ec24.js gzip 10.5 kB 10.9 kB ⚠️ +322 B
framework.HASH.js gzip 39.1 kB 39.1 kB
Overall change 56.9 kB 57.2 kB ⚠️ +322 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.module.js gzip 5.58 kB 5.58 kB
webpack-HASH..dule.js gzip 746 B 746 B
de003c3a9d30..dule.js gzip 6.92 kB 7.26 kB ⚠️ +338 B
framework.HA..dule.js gzip 39.1 kB 39.1 kB
Overall change 52.4 kB 52.7 kB ⚠️ +338 B
Legacy Client Bundles (polyfills)
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
polyfills-HASH.js gzip 26.3 kB 26.3 kB
Overall change 26.3 kB 26.3 kB
Client Pages
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.js gzip 1.26 kB 1.26 kB
_error.js gzip 3.25 kB 3.25 kB
hooks.js gzip 881 B 881 B
index.js gzip 222 B 222 B
link.js gzip 2.05 kB 2.05 kB
routerDirect.js gzip 279 B 279 B
withRouter.js gzip 278 B 278 B
Overall change 8.22 kB 8.22 kB
Client Pages Modern
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.module.js gzip 604 B 604 B
_error.module.js gzip 2.04 kB 2.04 kB
hooks.module.js gzip 383 B 383 B
index.module.js gzip 223 B 223 B
link.module.js gzip 1.52 kB 1.52 kB
routerDirect..dule.js gzip 281 B 281 B
withRouter.m..dule.js gzip 278 B 278 B
Overall change 5.33 kB 5.33 kB
Client Build Manifests
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_buildManifest.js gzip 171 B 171 B
_buildManife..dule.js gzip 180 B 180 B
Overall change 351 B 351 B
Rendered Page Sizes Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
index.html gzip 901 B 901 B
link.html gzip 906 B 907 B ⚠️ +1 B
withRouter.html gzip 894 B 894 B
Overall change 2.7 kB 2.7 kB ⚠️ +1 B

Diffs

Diff for de003c3a9d30..492ddeda7.js
@@ -707,10 +707,50 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
 
       var _slicedToArray = __webpack_require__("J4zp");
 
+      var _defineProperty = __webpack_require__("lSNA");
+
       var _classCallCheck = __webpack_require__("lwsE");
 
       var _createClass = __webpack_require__("W8MJ");
 
+      function ownKeys(object, enumerableOnly) {
+        var keys = Object.keys(object);
+        if (Object.getOwnPropertySymbols) {
+          var symbols = Object.getOwnPropertySymbols(object);
+          if (enumerableOnly)
+            symbols = symbols.filter(function(sym) {
+              return Object.getOwnPropertyDescriptor(object, sym).enumerable;
+            });
+          keys.push.apply(keys, symbols);
+        }
+        return keys;
+      }
+
+      function _objectSpread(target) {
+        for (var i = 1; i < arguments.length; i++) {
+          var source = arguments[i] != null ? arguments[i] : {};
+          if (i % 2) {
+            ownKeys(Object(source), true).forEach(function(key) {
+              _defineProperty(target, key, source[key]);
+            });
+          } else if (Object.getOwnPropertyDescriptors) {
+            Object.defineProperties(
+              target,
+              Object.getOwnPropertyDescriptors(source)
+            );
+          } else {
+            ownKeys(Object(source)).forEach(function(key) {
+              Object.defineProperty(
+                target,
+                key,
+                Object.getOwnPropertyDescriptor(source, key)
+              );
+            });
+          }
+        }
+        return target;
+      }
+
       exports.__esModule = true;
       exports.addBasePath = addBasePath;
       exports.delBasePath = delBasePath;
@@ -770,6 +810,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
         };
       }
 
+      var manualScrollRestoration =
+        true && "scrollRestoration" in window.history;
+
       function fetchNextData(pathname, query, isServerRender, cb) {
         var attempts = isServerRender ? 3 : 1;
 
@@ -989,7 +1032,12 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
               );
             }
 
-            window.addEventListener("popstate", this.onPopState);
+            window.addEventListener("popstate", this.onPopState); // enable custom scroll restoration handling when available
+            // otherwise fallback to browser's default handling
+
+            if (manualScrollRestoration) {
+              window.history.scrollRestoration = "manual";
+            }
           }
         } // @deprecated backwards compatibility even though it's a private method.
 
@@ -1205,6 +1253,27 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
 
                       Router.events.emit("beforeHistoryChange", as);
 
+                      if (manualScrollRestoration && history.state) {
+                        var _history$state = history.state,
+                          curUrl = _history$state.url,
+                          curAs = _history$state.as,
+                          curOptions = _history$state.options;
+
+                        _this2.changeState(
+                          "replaceState",
+                          curUrl,
+                          curAs,
+                          _objectSpread(
+                            _objectSpread({}, curOptions),
+                            {},
+                            {
+                              _N_X: window.scrollX,
+                              _N_Y: window.scrollY
+                            }
+                          )
+                        );
+                      }
+
                       _this2.changeState(method, url, as, options);
 
                       if (false) {
@@ -1220,6 +1289,11 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                           }
 
                           Router.events.emit("routeChangeComplete", as);
+
+                          if (manualScrollRestoration && "_N_X" in options) {
+                            window.scrollTo(options._N_X, options._N_Y);
+                          }
+
                           return resolve(true);
                         });
                     }, reject);
@@ -2005,6 +2079,27 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
       /***/
     },
 
+    /***/ lSNA: /***/ function(module, exports) {
+      function _defineProperty(obj, key, value) {
+        if (key in obj) {
+          Object.defineProperty(obj, key, {
+            value: value,
+            enumerable: true,
+            configurable: true,
+            writable: true
+          });
+        } else {
+          obj[key] = value;
+        }
+
+        return obj;
+      }
+
+      module.exports = _defineProperty;
+
+      /***/
+    },
+
     /***/ ls82: /***/ function(module, exports, __webpack_require__) {
       /**
        * Copyright (c) 2014-present, Facebook, Inc.
Diff for de003c3a9d30..36.module.js
@@ -583,6 +583,46 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
     /***/ elyg: /***/ function(module, exports, __webpack_require__) {
       "use strict";
 
+      var _defineProperty = __webpack_require__("lSNA");
+
+      function ownKeys(object, enumerableOnly) {
+        var keys = Object.keys(object);
+        if (Object.getOwnPropertySymbols) {
+          var symbols = Object.getOwnPropertySymbols(object);
+          if (enumerableOnly)
+            symbols = symbols.filter(function(sym) {
+              return Object.getOwnPropertyDescriptor(object, sym).enumerable;
+            });
+          keys.push.apply(keys, symbols);
+        }
+        return keys;
+      }
+
+      function _objectSpread(target) {
+        for (var i = 1; i < arguments.length; i++) {
+          var source = arguments[i] != null ? arguments[i] : {};
+          if (i % 2) {
+            ownKeys(Object(source), true).forEach(function(key) {
+              _defineProperty(target, key, source[key]);
+            });
+          } else if (Object.getOwnPropertyDescriptors) {
+            Object.defineProperties(
+              target,
+              Object.getOwnPropertyDescriptors(source)
+            );
+          } else {
+            ownKeys(Object(source)).forEach(function(key) {
+              Object.defineProperty(
+                target,
+                key,
+                Object.getOwnPropertyDescriptor(source, key)
+              );
+            });
+          }
+        }
+        return target;
+      }
+
       exports.__esModule = true;
       exports.addBasePath = addBasePath;
       exports.delBasePath = delBasePath;
@@ -641,6 +681,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
         };
       }
 
+      var manualScrollRestoration =
+        true && "scrollRestoration" in window.history;
+
       function fetchNextData(pathname, query, isServerRender, cb) {
         var attempts = isServerRender ? 3 : 1;
 
@@ -851,7 +894,12 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
               );
             }
 
-            window.addEventListener("popstate", this.onPopState);
+            window.addEventListener("popstate", this.onPopState); // enable custom scroll restoration handling when available
+            // otherwise fallback to browser's default handling
+
+            if (manualScrollRestoration) {
+              window.history.scrollRestoration = "manual";
+            }
           }
         } // @deprecated backwards compatibility even though it's a private method.
 
@@ -1036,6 +1084,28 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                 }
 
                 Router.events.emit("beforeHistoryChange", as);
+
+                if (manualScrollRestoration && history.state) {
+                  var {
+                    url: curUrl,
+                    as: curAs,
+                    options: curOptions
+                  } = history.state;
+                  this.changeState(
+                    "replaceState",
+                    curUrl,
+                    curAs,
+                    _objectSpread(
+                      _objectSpread({}, curOptions),
+                      {},
+                      {
+                        _N_X: window.scrollX,
+                        _N_Y: window.scrollY
+                      }
+                    )
+                  );
+                }
+
                 this.changeState(method, url, as, options);
 
                 if (false) {
@@ -1049,6 +1119,11 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                   }
 
                   Router.events.emit("routeChangeComplete", as);
+
+                  if (manualScrollRestoration && "_N_X" in options) {
+                    window.scrollTo(options._N_X, options._N_Y);
+                  }
+
                   return resolve(true);
                 });
               },
@@ -1647,6 +1722,27 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
       /***/
     },
 
+    /***/ lSNA: /***/ function(module, exports) {
+      function _defineProperty(obj, key, value) {
+        if (key in obj) {
+          Object.defineProperty(obj, key, {
+            value: value,
+            enumerable: true,
+            configurable: true,
+            writable: true
+          });
+        } else {
+          obj[key] = value;
+        }
+
+        return obj;
+      }
+
+      module.exports = _defineProperty;
+
+      /***/
+    },
+
     /***/ nOHt: /***/ function(module, exports, __webpack_require__) {
       "use strict";
Diff for index.html
@@ -18,7 +18,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -105,13 +105,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.22a0a091d06492ddeda7.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.7d58880f5e575b3ee36f.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
Diff for link.html
@@ -18,7 +18,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -110,13 +110,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.22a0a091d06492ddeda7.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.7d58880f5e575b3ee36f.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
Diff for withRouter.html
@@ -18,7 +18,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -105,13 +105,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.22a0a091d06492ddeda7.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.7d58880f5e575b3ee36f.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       async=""
       crossorigin="anonymous"
       type="module"

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
buildDuration 13.6s 13.9s ⚠️ +250ms
nodeModulesSize 64.9 MB 64.9 MB ⚠️ +2.2 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.js gzip 6.49 kB 6.49 kB
webpack-HASH.js gzip 746 B 746 B
de003c3a9d30..ec24.js gzip 10.5 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..4b11.js gzip N/A 10.9 kB N/A
Overall change 56.9 kB 57.2 kB ⚠️ +322 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.module.js gzip 5.58 kB 5.58 kB
webpack-HASH..dule.js gzip 746 B 746 B
de003c3a9d30..dule.js gzip 6.92 kB N/A N/A
framework.HA..dule.js gzip 39.1 kB 39.1 kB
de003c3a9d30..dule.js gzip N/A 7.26 kB N/A
Overall change 52.4 kB 52.7 kB ⚠️ +338 B
Legacy Client Bundles (polyfills)
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
polyfills-HASH.js gzip 26.3 kB 26.3 kB
Overall change 26.3 kB 26.3 kB
Client Pages
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.js gzip 1.26 kB 1.26 kB
_error.js gzip 3.25 kB 3.25 kB
hooks.js gzip 881 B 881 B
index.js gzip 222 B 222 B
link.js gzip 2.05 kB 2.05 kB
routerDirect.js gzip 279 B 279 B
withRouter.js gzip 278 B 278 B
Overall change 8.22 kB 8.22 kB
Client Pages Modern
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.module.js gzip 604 B 604 B
_error.module.js gzip 2.04 kB 2.04 kB
hooks.module.js gzip 383 B 383 B
index.module.js gzip 223 B 223 B
link.module.js gzip 1.52 kB 1.52 kB
routerDirect..dule.js gzip 281 B 281 B
withRouter.m..dule.js gzip 278 B 278 B
Overall change 5.33 kB 5.33 kB
Client Build Manifests
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_buildManifest.js gzip 171 B 171 B
_buildManife..dule.js gzip 180 B 180 B
Overall change 351 B 351 B
Serverless bundles Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_error.js 874 kB 874 kB
404.html 4.13 kB 4.13 kB
hooks.html 3.71 kB 3.71 kB
index.js 875 kB 875 kB
link.js 913 kB 914 kB ⚠️ +1.66 kB
routerDirect.js 905 kB 907 kB ⚠️ +1.66 kB
withRouter.js 905 kB 907 kB ⚠️ +1.66 kB
Overall change 4.48 MB 4.49 MB ⚠️ +4.98 kB

@ijjk
Copy link
Member Author

ijjk commented Jun 9, 2020

Stats from current PR

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
buildDuration 12s 11.4s -629ms
nodeModulesSize 64.9 MB 64.9 MB ⚠️ +2.2 kB
Page Load Tests Overall increase ✓
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
/ failed reqs 0 0
/ total time (seconds) 2.07 2.088 ⚠️ +0.02
/ avg req/sec 1207.67 1197.57 -10.1
/error-in-render failed reqs 0 0
/error-in-render total time (seconds) 1.457 1.397 -0.06
/error-in-render avg req/sec 1716.23 1789.42 ⚠️ +73.19
Client Bundles (main, webpack, commons) Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.js gzip 6.49 kB 6.49 kB
webpack-HASH.js gzip 746 B 746 B
de003c3a9d30..ec24.js gzip 10.5 kB 10.9 kB ⚠️ +322 B
framework.HASH.js gzip 39.1 kB 39.1 kB
Overall change 56.9 kB 57.2 kB ⚠️ +322 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.module.js gzip 5.58 kB 5.58 kB
webpack-HASH..dule.js gzip 746 B 746 B
de003c3a9d30..dule.js gzip 6.92 kB 7.26 kB ⚠️ +338 B
framework.HA..dule.js gzip 39.1 kB 39.1 kB
Overall change 52.4 kB 52.7 kB ⚠️ +338 B
Legacy Client Bundles (polyfills)
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
polyfills-HASH.js gzip 26.3 kB 26.3 kB
Overall change 26.3 kB 26.3 kB
Client Pages
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.js gzip 1.26 kB 1.26 kB
_error.js gzip 3.25 kB 3.25 kB
hooks.js gzip 881 B 881 B
index.js gzip 222 B 222 B
link.js gzip 2.05 kB 2.05 kB
routerDirect.js gzip 279 B 279 B
withRouter.js gzip 278 B 278 B
Overall change 8.22 kB 8.22 kB
Client Pages Modern
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.module.js gzip 604 B 604 B
_error.module.js gzip 2.04 kB 2.04 kB
hooks.module.js gzip 383 B 383 B
index.module.js gzip 223 B 223 B
link.module.js gzip 1.52 kB 1.52 kB
routerDirect..dule.js gzip 281 B 281 B
withRouter.m..dule.js gzip 278 B 278 B
Overall change 5.33 kB 5.33 kB
Client Build Manifests
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_buildManifest.js gzip 171 B 171 B
_buildManife..dule.js gzip 180 B 180 B
Overall change 351 B 351 B
Rendered Page Sizes Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
index.html gzip 901 B 901 B
link.html gzip 906 B 907 B ⚠️ +1 B
withRouter.html gzip 894 B 894 B
Overall change 2.7 kB 2.7 kB ⚠️ +1 B

Diffs

Diff for de003c3a9d30..492ddeda7.js
@@ -707,10 +707,50 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
 
       var _slicedToArray = __webpack_require__("J4zp");
 
+      var _defineProperty = __webpack_require__("lSNA");
+
       var _classCallCheck = __webpack_require__("lwsE");
 
       var _createClass = __webpack_require__("W8MJ");
 
+      function ownKeys(object, enumerableOnly) {
+        var keys = Object.keys(object);
+        if (Object.getOwnPropertySymbols) {
+          var symbols = Object.getOwnPropertySymbols(object);
+          if (enumerableOnly)
+            symbols = symbols.filter(function(sym) {
+              return Object.getOwnPropertyDescriptor(object, sym).enumerable;
+            });
+          keys.push.apply(keys, symbols);
+        }
+        return keys;
+      }
+
+      function _objectSpread(target) {
+        for (var i = 1; i < arguments.length; i++) {
+          var source = arguments[i] != null ? arguments[i] : {};
+          if (i % 2) {
+            ownKeys(Object(source), true).forEach(function(key) {
+              _defineProperty(target, key, source[key]);
+            });
+          } else if (Object.getOwnPropertyDescriptors) {
+            Object.defineProperties(
+              target,
+              Object.getOwnPropertyDescriptors(source)
+            );
+          } else {
+            ownKeys(Object(source)).forEach(function(key) {
+              Object.defineProperty(
+                target,
+                key,
+                Object.getOwnPropertyDescriptor(source, key)
+              );
+            });
+          }
+        }
+        return target;
+      }
+
       exports.__esModule = true;
       exports.addBasePath = addBasePath;
       exports.delBasePath = delBasePath;
@@ -770,6 +810,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
         };
       }
 
+      var manualScrollRestoration =
+        true && "scrollRestoration" in window.history;
+
       function fetchNextData(pathname, query, isServerRender, cb) {
         var attempts = isServerRender ? 3 : 1;
 
@@ -989,7 +1032,12 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
               );
             }
 
-            window.addEventListener("popstate", this.onPopState);
+            window.addEventListener("popstate", this.onPopState); // enable custom scroll restoration handling when available
+            // otherwise fallback to browser's default handling
+
+            if (manualScrollRestoration) {
+              window.history.scrollRestoration = "manual";
+            }
           }
         } // @deprecated backwards compatibility even though it's a private method.
 
@@ -1205,6 +1253,27 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
 
                       Router.events.emit("beforeHistoryChange", as);
 
+                      if (manualScrollRestoration && history.state) {
+                        var _history$state = history.state,
+                          curUrl = _history$state.url,
+                          curAs = _history$state.as,
+                          curOptions = _history$state.options;
+
+                        _this2.changeState(
+                          "replaceState",
+                          curUrl,
+                          curAs,
+                          _objectSpread(
+                            _objectSpread({}, curOptions),
+                            {},
+                            {
+                              _N_X: window.scrollX,
+                              _N_Y: window.scrollY
+                            }
+                          )
+                        );
+                      }
+
                       _this2.changeState(method, url, as, options);
 
                       if (false) {
@@ -1220,6 +1289,11 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                           }
 
                           Router.events.emit("routeChangeComplete", as);
+
+                          if (manualScrollRestoration && "_N_X" in options) {
+                            window.scrollTo(options._N_X, options._N_Y);
+                          }
+
                           return resolve(true);
                         });
                     }, reject);
@@ -2005,6 +2079,27 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
       /***/
     },
 
+    /***/ lSNA: /***/ function(module, exports) {
+      function _defineProperty(obj, key, value) {
+        if (key in obj) {
+          Object.defineProperty(obj, key, {
+            value: value,
+            enumerable: true,
+            configurable: true,
+            writable: true
+          });
+        } else {
+          obj[key] = value;
+        }
+
+        return obj;
+      }
+
+      module.exports = _defineProperty;
+
+      /***/
+    },
+
     /***/ ls82: /***/ function(module, exports, __webpack_require__) {
       /**
        * Copyright (c) 2014-present, Facebook, Inc.
Diff for de003c3a9d30..36.module.js
@@ -583,6 +583,46 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
     /***/ elyg: /***/ function(module, exports, __webpack_require__) {
       "use strict";
 
+      var _defineProperty = __webpack_require__("lSNA");
+
+      function ownKeys(object, enumerableOnly) {
+        var keys = Object.keys(object);
+        if (Object.getOwnPropertySymbols) {
+          var symbols = Object.getOwnPropertySymbols(object);
+          if (enumerableOnly)
+            symbols = symbols.filter(function(sym) {
+              return Object.getOwnPropertyDescriptor(object, sym).enumerable;
+            });
+          keys.push.apply(keys, symbols);
+        }
+        return keys;
+      }
+
+      function _objectSpread(target) {
+        for (var i = 1; i < arguments.length; i++) {
+          var source = arguments[i] != null ? arguments[i] : {};
+          if (i % 2) {
+            ownKeys(Object(source), true).forEach(function(key) {
+              _defineProperty(target, key, source[key]);
+            });
+          } else if (Object.getOwnPropertyDescriptors) {
+            Object.defineProperties(
+              target,
+              Object.getOwnPropertyDescriptors(source)
+            );
+          } else {
+            ownKeys(Object(source)).forEach(function(key) {
+              Object.defineProperty(
+                target,
+                key,
+                Object.getOwnPropertyDescriptor(source, key)
+              );
+            });
+          }
+        }
+        return target;
+      }
+
       exports.__esModule = true;
       exports.addBasePath = addBasePath;
       exports.delBasePath = delBasePath;
@@ -641,6 +681,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
         };
       }
 
+      var manualScrollRestoration =
+        true && "scrollRestoration" in window.history;
+
       function fetchNextData(pathname, query, isServerRender, cb) {
         var attempts = isServerRender ? 3 : 1;
 
@@ -851,7 +894,12 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
               );
             }
 
-            window.addEventListener("popstate", this.onPopState);
+            window.addEventListener("popstate", this.onPopState); // enable custom scroll restoration handling when available
+            // otherwise fallback to browser's default handling
+
+            if (manualScrollRestoration) {
+              window.history.scrollRestoration = "manual";
+            }
           }
         } // @deprecated backwards compatibility even though it's a private method.
 
@@ -1036,6 +1084,28 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                 }
 
                 Router.events.emit("beforeHistoryChange", as);
+
+                if (manualScrollRestoration && history.state) {
+                  var {
+                    url: curUrl,
+                    as: curAs,
+                    options: curOptions
+                  } = history.state;
+                  this.changeState(
+                    "replaceState",
+                    curUrl,
+                    curAs,
+                    _objectSpread(
+                      _objectSpread({}, curOptions),
+                      {},
+                      {
+                        _N_X: window.scrollX,
+                        _N_Y: window.scrollY
+                      }
+                    )
+                  );
+                }
+
                 this.changeState(method, url, as, options);
 
                 if (false) {
@@ -1049,6 +1119,11 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                   }
 
                   Router.events.emit("routeChangeComplete", as);
+
+                  if (manualScrollRestoration && "_N_X" in options) {
+                    window.scrollTo(options._N_X, options._N_Y);
+                  }
+
                   return resolve(true);
                 });
               },
@@ -1647,6 +1722,27 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
       /***/
     },
 
+    /***/ lSNA: /***/ function(module, exports) {
+      function _defineProperty(obj, key, value) {
+        if (key in obj) {
+          Object.defineProperty(obj, key, {
+            value: value,
+            enumerable: true,
+            configurable: true,
+            writable: true
+          });
+        } else {
+          obj[key] = value;
+        }
+
+        return obj;
+      }
+
+      module.exports = _defineProperty;
+
+      /***/
+    },
+
     /***/ nOHt: /***/ function(module, exports, __webpack_require__) {
       "use strict";
Diff for index.html
@@ -18,7 +18,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -105,13 +105,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.22a0a091d06492ddeda7.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.7d58880f5e575b3ee36f.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
Diff for link.html
@@ -18,7 +18,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -110,13 +110,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.22a0a091d06492ddeda7.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.7d58880f5e575b3ee36f.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
Diff for withRouter.html
@@ -18,7 +18,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -105,13 +105,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.22a0a091d06492ddeda7.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.7d58880f5e575b3ee36f.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       async=""
       crossorigin="anonymous"
       type="module"

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
buildDuration 13s 13s ⚠️ +75ms
nodeModulesSize 64.9 MB 64.9 MB ⚠️ +2.2 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.js gzip 6.49 kB 6.49 kB
webpack-HASH.js gzip 746 B 746 B
de003c3a9d30..ec24.js gzip 10.5 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..4b11.js gzip N/A 10.9 kB N/A
Overall change 56.9 kB 57.2 kB ⚠️ +322 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.module.js gzip 5.58 kB 5.58 kB
webpack-HASH..dule.js gzip 746 B 746 B
de003c3a9d30..dule.js gzip 6.92 kB N/A N/A
framework.HA..dule.js gzip 39.1 kB 39.1 kB
de003c3a9d30..dule.js gzip N/A 7.26 kB N/A
Overall change 52.4 kB 52.7 kB ⚠️ +338 B
Legacy Client Bundles (polyfills)
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
polyfills-HASH.js gzip 26.3 kB 26.3 kB
Overall change 26.3 kB 26.3 kB
Client Pages
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.js gzip 1.26 kB 1.26 kB
_error.js gzip 3.25 kB 3.25 kB
hooks.js gzip 881 B 881 B
index.js gzip 222 B 222 B
link.js gzip 2.05 kB 2.05 kB
routerDirect.js gzip 279 B 279 B
withRouter.js gzip 278 B 278 B
Overall change 8.22 kB 8.22 kB
Client Pages Modern
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.module.js gzip 604 B 604 B
_error.module.js gzip 2.04 kB 2.04 kB
hooks.module.js gzip 383 B 383 B
index.module.js gzip 223 B 223 B
link.module.js gzip 1.52 kB 1.52 kB
routerDirect..dule.js gzip 281 B 281 B
withRouter.m..dule.js gzip 278 B 278 B
Overall change 5.33 kB 5.33 kB
Client Build Manifests
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_buildManifest.js gzip 171 B 171 B
_buildManife..dule.js gzip 180 B 180 B
Overall change 351 B 351 B
Serverless bundles Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_error.js 874 kB 874 kB
404.html 4.13 kB 4.13 kB
hooks.html 3.71 kB 3.71 kB
index.js 875 kB 875 kB
link.js 913 kB 914 kB ⚠️ +1.66 kB
routerDirect.js 905 kB 907 kB ⚠️ +1.66 kB
withRouter.js 905 kB 907 kB ⚠️ +1.66 kB
Overall change 4.48 MB 4.49 MB ⚠️ +4.98 kB

@ijjk
Copy link
Member Author

ijjk commented Jun 9, 2020

Stats from current PR

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
buildDuration 12.8s 12.8s -76ms
nodeModulesSize 64.9 MB 64.9 MB ⚠️ +2.2 kB
Page Load Tests Overall increase ✓
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
/ failed reqs 0 0
/ total time (seconds) 2.336 2.167 -0.17
/ avg req/sec 1070.17 1153.56 ⚠️ +83.39
/error-in-render failed reqs 0 0
/error-in-render total time (seconds) 1.443 1.389 -0.05
/error-in-render avg req/sec 1732.44 1800.28 ⚠️ +67.84
Client Bundles (main, webpack, commons) Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.js gzip 6.49 kB 6.49 kB
webpack-HASH.js gzip 746 B 746 B
de003c3a9d30..ec24.js gzip 10.5 kB 10.9 kB ⚠️ +322 B
framework.HASH.js gzip 39.1 kB 39.1 kB
Overall change 56.9 kB 57.2 kB ⚠️ +322 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.module.js gzip 5.58 kB 5.58 kB
webpack-HASH..dule.js gzip 746 B 746 B
de003c3a9d30..dule.js gzip 6.92 kB 7.26 kB ⚠️ +338 B
framework.HA..dule.js gzip 39.1 kB 39.1 kB
Overall change 52.4 kB 52.7 kB ⚠️ +338 B
Legacy Client Bundles (polyfills)
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
polyfills-HASH.js gzip 26.3 kB 26.3 kB
Overall change 26.3 kB 26.3 kB
Client Pages
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.js gzip 1.26 kB 1.26 kB
_error.js gzip 3.25 kB 3.25 kB
hooks.js gzip 881 B 881 B
index.js gzip 222 B 222 B
link.js gzip 2.05 kB 2.05 kB
routerDirect.js gzip 279 B 279 B
withRouter.js gzip 278 B 278 B
Overall change 8.22 kB 8.22 kB
Client Pages Modern
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.module.js gzip 604 B 604 B
_error.module.js gzip 2.04 kB 2.04 kB
hooks.module.js gzip 383 B 383 B
index.module.js gzip 223 B 223 B
link.module.js gzip 1.52 kB 1.52 kB
routerDirect..dule.js gzip 281 B 281 B
withRouter.m..dule.js gzip 278 B 278 B
Overall change 5.33 kB 5.33 kB
Client Build Manifests
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_buildManifest.js gzip 171 B 171 B
_buildManife..dule.js gzip 180 B 180 B
Overall change 351 B 351 B
Rendered Page Sizes Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
index.html gzip 901 B 901 B
link.html gzip 906 B 907 B ⚠️ +1 B
withRouter.html gzip 894 B 894 B
Overall change 2.7 kB 2.7 kB ⚠️ +1 B

Diffs

Diff for de003c3a9d30..492ddeda7.js
@@ -707,10 +707,50 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
 
       var _slicedToArray = __webpack_require__("J4zp");
 
+      var _defineProperty = __webpack_require__("lSNA");
+
       var _classCallCheck = __webpack_require__("lwsE");
 
       var _createClass = __webpack_require__("W8MJ");
 
+      function ownKeys(object, enumerableOnly) {
+        var keys = Object.keys(object);
+        if (Object.getOwnPropertySymbols) {
+          var symbols = Object.getOwnPropertySymbols(object);
+          if (enumerableOnly)
+            symbols = symbols.filter(function(sym) {
+              return Object.getOwnPropertyDescriptor(object, sym).enumerable;
+            });
+          keys.push.apply(keys, symbols);
+        }
+        return keys;
+      }
+
+      function _objectSpread(target) {
+        for (var i = 1; i < arguments.length; i++) {
+          var source = arguments[i] != null ? arguments[i] : {};
+          if (i % 2) {
+            ownKeys(Object(source), true).forEach(function(key) {
+              _defineProperty(target, key, source[key]);
+            });
+          } else if (Object.getOwnPropertyDescriptors) {
+            Object.defineProperties(
+              target,
+              Object.getOwnPropertyDescriptors(source)
+            );
+          } else {
+            ownKeys(Object(source)).forEach(function(key) {
+              Object.defineProperty(
+                target,
+                key,
+                Object.getOwnPropertyDescriptor(source, key)
+              );
+            });
+          }
+        }
+        return target;
+      }
+
       exports.__esModule = true;
       exports.addBasePath = addBasePath;
       exports.delBasePath = delBasePath;
@@ -770,6 +810,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
         };
       }
 
+      var manualScrollRestoration =
+        true && "scrollRestoration" in window.history;
+
       function fetchNextData(pathname, query, isServerRender, cb) {
         var attempts = isServerRender ? 3 : 1;
 
@@ -989,7 +1032,12 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
               );
             }
 
-            window.addEventListener("popstate", this.onPopState);
+            window.addEventListener("popstate", this.onPopState); // enable custom scroll restoration handling when available
+            // otherwise fallback to browser's default handling
+
+            if (manualScrollRestoration) {
+              window.history.scrollRestoration = "manual";
+            }
           }
         } // @deprecated backwards compatibility even though it's a private method.
 
@@ -1205,6 +1253,27 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
 
                       Router.events.emit("beforeHistoryChange", as);
 
+                      if (manualScrollRestoration && history.state) {
+                        var _history$state = history.state,
+                          curUrl = _history$state.url,
+                          curAs = _history$state.as,
+                          curOptions = _history$state.options;
+
+                        _this2.changeState(
+                          "replaceState",
+                          curUrl,
+                          curAs,
+                          _objectSpread(
+                            _objectSpread({}, curOptions),
+                            {},
+                            {
+                              _N_X: window.scrollX,
+                              _N_Y: window.scrollY
+                            }
+                          )
+                        );
+                      }
+
                       _this2.changeState(method, url, as, options);
 
                       if (false) {
@@ -1220,6 +1289,11 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                           }
 
                           Router.events.emit("routeChangeComplete", as);
+
+                          if (manualScrollRestoration && "_N_X" in options) {
+                            window.scrollTo(options._N_X, options._N_Y);
+                          }
+
                           return resolve(true);
                         });
                     }, reject);
@@ -2005,6 +2079,27 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
       /***/
     },
 
+    /***/ lSNA: /***/ function(module, exports) {
+      function _defineProperty(obj, key, value) {
+        if (key in obj) {
+          Object.defineProperty(obj, key, {
+            value: value,
+            enumerable: true,
+            configurable: true,
+            writable: true
+          });
+        } else {
+          obj[key] = value;
+        }
+
+        return obj;
+      }
+
+      module.exports = _defineProperty;
+
+      /***/
+    },
+
     /***/ ls82: /***/ function(module, exports, __webpack_require__) {
       /**
        * Copyright (c) 2014-present, Facebook, Inc.
Diff for de003c3a9d30..36.module.js
@@ -583,6 +583,46 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
     /***/ elyg: /***/ function(module, exports, __webpack_require__) {
       "use strict";
 
+      var _defineProperty = __webpack_require__("lSNA");
+
+      function ownKeys(object, enumerableOnly) {
+        var keys = Object.keys(object);
+        if (Object.getOwnPropertySymbols) {
+          var symbols = Object.getOwnPropertySymbols(object);
+          if (enumerableOnly)
+            symbols = symbols.filter(function(sym) {
+              return Object.getOwnPropertyDescriptor(object, sym).enumerable;
+            });
+          keys.push.apply(keys, symbols);
+        }
+        return keys;
+      }
+
+      function _objectSpread(target) {
+        for (var i = 1; i < arguments.length; i++) {
+          var source = arguments[i] != null ? arguments[i] : {};
+          if (i % 2) {
+            ownKeys(Object(source), true).forEach(function(key) {
+              _defineProperty(target, key, source[key]);
+            });
+          } else if (Object.getOwnPropertyDescriptors) {
+            Object.defineProperties(
+              target,
+              Object.getOwnPropertyDescriptors(source)
+            );
+          } else {
+            ownKeys(Object(source)).forEach(function(key) {
+              Object.defineProperty(
+                target,
+                key,
+                Object.getOwnPropertyDescriptor(source, key)
+              );
+            });
+          }
+        }
+        return target;
+      }
+
       exports.__esModule = true;
       exports.addBasePath = addBasePath;
       exports.delBasePath = delBasePath;
@@ -641,6 +681,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
         };
       }
 
+      var manualScrollRestoration =
+        true && "scrollRestoration" in window.history;
+
       function fetchNextData(pathname, query, isServerRender, cb) {
         var attempts = isServerRender ? 3 : 1;
 
@@ -851,7 +894,12 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
               );
             }
 
-            window.addEventListener("popstate", this.onPopState);
+            window.addEventListener("popstate", this.onPopState); // enable custom scroll restoration handling when available
+            // otherwise fallback to browser's default handling
+
+            if (manualScrollRestoration) {
+              window.history.scrollRestoration = "manual";
+            }
           }
         } // @deprecated backwards compatibility even though it's a private method.
 
@@ -1036,6 +1084,28 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                 }
 
                 Router.events.emit("beforeHistoryChange", as);
+
+                if (manualScrollRestoration && history.state) {
+                  var {
+                    url: curUrl,
+                    as: curAs,
+                    options: curOptions
+                  } = history.state;
+                  this.changeState(
+                    "replaceState",
+                    curUrl,
+                    curAs,
+                    _objectSpread(
+                      _objectSpread({}, curOptions),
+                      {},
+                      {
+                        _N_X: window.scrollX,
+                        _N_Y: window.scrollY
+                      }
+                    )
+                  );
+                }
+
                 this.changeState(method, url, as, options);
 
                 if (false) {
@@ -1049,6 +1119,11 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                   }
 
                   Router.events.emit("routeChangeComplete", as);
+
+                  if (manualScrollRestoration && "_N_X" in options) {
+                    window.scrollTo(options._N_X, options._N_Y);
+                  }
+
                   return resolve(true);
                 });
               },
@@ -1647,6 +1722,27 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
       /***/
     },
 
+    /***/ lSNA: /***/ function(module, exports) {
+      function _defineProperty(obj, key, value) {
+        if (key in obj) {
+          Object.defineProperty(obj, key, {
+            value: value,
+            enumerable: true,
+            configurable: true,
+            writable: true
+          });
+        } else {
+          obj[key] = value;
+        }
+
+        return obj;
+      }
+
+      module.exports = _defineProperty;
+
+      /***/
+    },
+
     /***/ nOHt: /***/ function(module, exports, __webpack_require__) {
       "use strict";
Diff for index.html
@@ -18,7 +18,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -105,13 +105,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.22a0a091d06492ddeda7.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.7d58880f5e575b3ee36f.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
Diff for link.html
@@ -18,7 +18,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -110,13 +110,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.22a0a091d06492ddeda7.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.7d58880f5e575b3ee36f.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
Diff for withRouter.html
@@ -18,7 +18,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -105,13 +105,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.22a0a091d06492ddeda7.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.7d58880f5e575b3ee36f.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       async=""
       crossorigin="anonymous"
       type="module"

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
buildDuration 13.4s 13.6s ⚠️ +246ms
nodeModulesSize 64.9 MB 64.9 MB ⚠️ +2.2 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.js gzip 6.49 kB 6.49 kB
webpack-HASH.js gzip 746 B 746 B
de003c3a9d30..ec24.js gzip 10.5 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..4b11.js gzip N/A 10.9 kB N/A
Overall change 56.9 kB 57.2 kB ⚠️ +322 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.module.js gzip 5.58 kB 5.58 kB
webpack-HASH..dule.js gzip 746 B 746 B
de003c3a9d30..dule.js gzip 6.92 kB N/A N/A
framework.HA..dule.js gzip 39.1 kB 39.1 kB
de003c3a9d30..dule.js gzip N/A 7.26 kB N/A
Overall change 52.4 kB 52.7 kB ⚠️ +338 B
Legacy Client Bundles (polyfills)
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
polyfills-HASH.js gzip 26.3 kB 26.3 kB
Overall change 26.3 kB 26.3 kB
Client Pages
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.js gzip 1.26 kB 1.26 kB
_error.js gzip 3.25 kB 3.25 kB
hooks.js gzip 881 B 881 B
index.js gzip 222 B 222 B
link.js gzip 2.05 kB 2.05 kB
routerDirect.js gzip 279 B 279 B
withRouter.js gzip 278 B 278 B
Overall change 8.22 kB 8.22 kB
Client Pages Modern
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.module.js gzip 604 B 604 B
_error.module.js gzip 2.04 kB 2.04 kB
hooks.module.js gzip 383 B 383 B
index.module.js gzip 223 B 223 B
link.module.js gzip 1.52 kB 1.52 kB
routerDirect..dule.js gzip 281 B 281 B
withRouter.m..dule.js gzip 278 B 278 B
Overall change 5.33 kB 5.33 kB
Client Build Manifests
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_buildManifest.js gzip 171 B 171 B
_buildManife..dule.js gzip 180 B 180 B
Overall change 351 B 351 B
Serverless bundles Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_error.js 874 kB 874 kB
404.html 4.13 kB 4.13 kB
hooks.html 3.71 kB 3.71 kB
index.js 875 kB 875 kB
link.js 913 kB 914 kB ⚠️ +1.66 kB
routerDirect.js 905 kB 907 kB ⚠️ +1.66 kB
withRouter.js 905 kB 907 kB ⚠️ +1.66 kB
Overall change 4.48 MB 4.49 MB ⚠️ +4.98 kB

@Timer Timer modified the milestones: 9.4.5, june 2020 Jun 9, 2020
@ijjk
Copy link
Member Author

ijjk commented Jun 9, 2020

Stats from current PR

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
buildDuration 12.3s 12.5s ⚠️ +228ms
nodeModulesSize 64.9 MB 64.9 MB ⚠️ +2.2 kB
Page Load Tests Overall increase ✓
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
/ failed reqs 0 0
/ total time (seconds) 2.151 2.15 0
/ avg req/sec 1162.1 1162.58 ⚠️ +0.48
/error-in-render failed reqs 0 0
/error-in-render total time (seconds) 1.448 1.378 -0.07
/error-in-render avg req/sec 1726.57 1814.84 ⚠️ +88.27
Client Bundles (main, webpack, commons) Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.js gzip 6.49 kB 6.49 kB
webpack-HASH.js gzip 746 B 746 B
de003c3a9d30..ec24.js gzip 10.5 kB 10.9 kB ⚠️ +322 B
framework.HASH.js gzip 39.1 kB 39.1 kB
Overall change 56.9 kB 57.2 kB ⚠️ +322 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.module.js gzip 5.58 kB 5.58 kB
webpack-HASH..dule.js gzip 746 B 746 B
de003c3a9d30..dule.js gzip 6.92 kB 7.26 kB ⚠️ +338 B
framework.HA..dule.js gzip 39.1 kB 39.1 kB
Overall change 52.4 kB 52.7 kB ⚠️ +338 B
Legacy Client Bundles (polyfills)
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
polyfills-HASH.js gzip 26.3 kB 26.3 kB
Overall change 26.3 kB 26.3 kB
Client Pages
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.js gzip 1.26 kB 1.26 kB
_error.js gzip 3.25 kB 3.25 kB
hooks.js gzip 881 B 881 B
index.js gzip 222 B 222 B
link.js gzip 2.05 kB 2.05 kB
routerDirect.js gzip 279 B 279 B
withRouter.js gzip 278 B 278 B
Overall change 8.22 kB 8.22 kB
Client Pages Modern
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.module.js gzip 604 B 604 B
_error.module.js gzip 2.04 kB 2.04 kB
hooks.module.js gzip 383 B 383 B
index.module.js gzip 223 B 223 B
link.module.js gzip 1.52 kB 1.52 kB
routerDirect..dule.js gzip 281 B 281 B
withRouter.m..dule.js gzip 278 B 278 B
Overall change 5.33 kB 5.33 kB
Client Build Manifests
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_buildManifest.js gzip 171 B 171 B
_buildManife..dule.js gzip 180 B 180 B
Overall change 351 B 351 B
Rendered Page Sizes Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
index.html gzip 901 B 901 B
link.html gzip 906 B 907 B ⚠️ +1 B
withRouter.html gzip 894 B 894 B
Overall change 2.7 kB 2.7 kB ⚠️ +1 B

Diffs

Diff for de003c3a9d30..492ddeda7.js
@@ -707,10 +707,50 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
 
       var _slicedToArray = __webpack_require__("J4zp");
 
+      var _defineProperty = __webpack_require__("lSNA");
+
       var _classCallCheck = __webpack_require__("lwsE");
 
       var _createClass = __webpack_require__("W8MJ");
 
+      function ownKeys(object, enumerableOnly) {
+        var keys = Object.keys(object);
+        if (Object.getOwnPropertySymbols) {
+          var symbols = Object.getOwnPropertySymbols(object);
+          if (enumerableOnly)
+            symbols = symbols.filter(function(sym) {
+              return Object.getOwnPropertyDescriptor(object, sym).enumerable;
+            });
+          keys.push.apply(keys, symbols);
+        }
+        return keys;
+      }
+
+      function _objectSpread(target) {
+        for (var i = 1; i < arguments.length; i++) {
+          var source = arguments[i] != null ? arguments[i] : {};
+          if (i % 2) {
+            ownKeys(Object(source), true).forEach(function(key) {
+              _defineProperty(target, key, source[key]);
+            });
+          } else if (Object.getOwnPropertyDescriptors) {
+            Object.defineProperties(
+              target,
+              Object.getOwnPropertyDescriptors(source)
+            );
+          } else {
+            ownKeys(Object(source)).forEach(function(key) {
+              Object.defineProperty(
+                target,
+                key,
+                Object.getOwnPropertyDescriptor(source, key)
+              );
+            });
+          }
+        }
+        return target;
+      }
+
       exports.__esModule = true;
       exports.addBasePath = addBasePath;
       exports.delBasePath = delBasePath;
@@ -770,6 +810,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
         };
       }
 
+      var manualScrollRestoration =
+        true && "scrollRestoration" in window.history;
+
       function fetchNextData(pathname, query, isServerRender, cb) {
         var attempts = isServerRender ? 3 : 1;
 
@@ -989,7 +1032,12 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
               );
             }
 
-            window.addEventListener("popstate", this.onPopState);
+            window.addEventListener("popstate", this.onPopState); // enable custom scroll restoration handling when available
+            // otherwise fallback to browser's default handling
+
+            if (manualScrollRestoration) {
+              window.history.scrollRestoration = "manual";
+            }
           }
         } // @deprecated backwards compatibility even though it's a private method.
 
@@ -1205,6 +1253,27 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
 
                       Router.events.emit("beforeHistoryChange", as);
 
+                      if (manualScrollRestoration && history.state) {
+                        var _history$state = history.state,
+                          curUrl = _history$state.url,
+                          curAs = _history$state.as,
+                          curOptions = _history$state.options;
+
+                        _this2.changeState(
+                          "replaceState",
+                          curUrl,
+                          curAs,
+                          _objectSpread(
+                            _objectSpread({}, curOptions),
+                            {},
+                            {
+                              _N_X: window.scrollX,
+                              _N_Y: window.scrollY
+                            }
+                          )
+                        );
+                      }
+
                       _this2.changeState(method, url, as, options);
 
                       if (false) {
@@ -1220,6 +1289,11 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                           }
 
                           Router.events.emit("routeChangeComplete", as);
+
+                          if (manualScrollRestoration && "_N_X" in options) {
+                            window.scrollTo(options._N_X, options._N_Y);
+                          }
+
                           return resolve(true);
                         });
                     }, reject);
@@ -2005,6 +2079,27 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
       /***/
     },
 
+    /***/ lSNA: /***/ function(module, exports) {
+      function _defineProperty(obj, key, value) {
+        if (key in obj) {
+          Object.defineProperty(obj, key, {
+            value: value,
+            enumerable: true,
+            configurable: true,
+            writable: true
+          });
+        } else {
+          obj[key] = value;
+        }
+
+        return obj;
+      }
+
+      module.exports = _defineProperty;
+
+      /***/
+    },
+
     /***/ ls82: /***/ function(module, exports, __webpack_require__) {
       /**
        * Copyright (c) 2014-present, Facebook, Inc.
Diff for de003c3a9d30..36.module.js
@@ -583,6 +583,46 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
     /***/ elyg: /***/ function(module, exports, __webpack_require__) {
       "use strict";
 
+      var _defineProperty = __webpack_require__("lSNA");
+
+      function ownKeys(object, enumerableOnly) {
+        var keys = Object.keys(object);
+        if (Object.getOwnPropertySymbols) {
+          var symbols = Object.getOwnPropertySymbols(object);
+          if (enumerableOnly)
+            symbols = symbols.filter(function(sym) {
+              return Object.getOwnPropertyDescriptor(object, sym).enumerable;
+            });
+          keys.push.apply(keys, symbols);
+        }
+        return keys;
+      }
+
+      function _objectSpread(target) {
+        for (var i = 1; i < arguments.length; i++) {
+          var source = arguments[i] != null ? arguments[i] : {};
+          if (i % 2) {
+            ownKeys(Object(source), true).forEach(function(key) {
+              _defineProperty(target, key, source[key]);
+            });
+          } else if (Object.getOwnPropertyDescriptors) {
+            Object.defineProperties(
+              target,
+              Object.getOwnPropertyDescriptors(source)
+            );
+          } else {
+            ownKeys(Object(source)).forEach(function(key) {
+              Object.defineProperty(
+                target,
+                key,
+                Object.getOwnPropertyDescriptor(source, key)
+              );
+            });
+          }
+        }
+        return target;
+      }
+
       exports.__esModule = true;
       exports.addBasePath = addBasePath;
       exports.delBasePath = delBasePath;
@@ -641,6 +681,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
         };
       }
 
+      var manualScrollRestoration =
+        true && "scrollRestoration" in window.history;
+
       function fetchNextData(pathname, query, isServerRender, cb) {
         var attempts = isServerRender ? 3 : 1;
 
@@ -851,7 +894,12 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
               );
             }
 
-            window.addEventListener("popstate", this.onPopState);
+            window.addEventListener("popstate", this.onPopState); // enable custom scroll restoration handling when available
+            // otherwise fallback to browser's default handling
+
+            if (manualScrollRestoration) {
+              window.history.scrollRestoration = "manual";
+            }
           }
         } // @deprecated backwards compatibility even though it's a private method.
 
@@ -1036,6 +1084,28 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                 }
 
                 Router.events.emit("beforeHistoryChange", as);
+
+                if (manualScrollRestoration && history.state) {
+                  var {
+                    url: curUrl,
+                    as: curAs,
+                    options: curOptions
+                  } = history.state;
+                  this.changeState(
+                    "replaceState",
+                    curUrl,
+                    curAs,
+                    _objectSpread(
+                      _objectSpread({}, curOptions),
+                      {},
+                      {
+                        _N_X: window.scrollX,
+                        _N_Y: window.scrollY
+                      }
+                    )
+                  );
+                }
+
                 this.changeState(method, url, as, options);
 
                 if (false) {
@@ -1049,6 +1119,11 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                   }
 
                   Router.events.emit("routeChangeComplete", as);
+
+                  if (manualScrollRestoration && "_N_X" in options) {
+                    window.scrollTo(options._N_X, options._N_Y);
+                  }
+
                   return resolve(true);
                 });
               },
@@ -1647,6 +1722,27 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
       /***/
     },
 
+    /***/ lSNA: /***/ function(module, exports) {
+      function _defineProperty(obj, key, value) {
+        if (key in obj) {
+          Object.defineProperty(obj, key, {
+            value: value,
+            enumerable: true,
+            configurable: true,
+            writable: true
+          });
+        } else {
+          obj[key] = value;
+        }
+
+        return obj;
+      }
+
+      module.exports = _defineProperty;
+
+      /***/
+    },
+
     /***/ nOHt: /***/ function(module, exports, __webpack_require__) {
       "use strict";
Diff for index.html
@@ -18,7 +18,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -105,13 +105,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.22a0a091d06492ddeda7.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.7d58880f5e575b3ee36f.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
Diff for link.html
@@ -18,7 +18,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -110,13 +110,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.22a0a091d06492ddeda7.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.7d58880f5e575b3ee36f.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
Diff for withRouter.html
@@ -18,7 +18,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -105,13 +105,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.22a0a091d06492ddeda7.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.7d58880f5e575b3ee36f.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.3c0e78228684b57e6b36.module.js"
+      src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.c9c4494d45b20185ecd7.module.js"
       async=""
       crossorigin="anonymous"
       type="module"

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
buildDuration 13.2s 13.2s -18ms
nodeModulesSize 64.9 MB 64.9 MB ⚠️ +2.2 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.js gzip 6.49 kB 6.49 kB
webpack-HASH.js gzip 746 B 746 B
de003c3a9d30..ec24.js gzip 10.5 kB N/A N/A
framework.HASH.js gzip 39.1 kB 39.1 kB
de003c3a9d30..4b11.js gzip N/A 10.9 kB N/A
Overall change 56.9 kB 57.2 kB ⚠️ +322 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
main-HASH.module.js gzip 5.58 kB 5.58 kB
webpack-HASH..dule.js gzip 746 B 746 B
de003c3a9d30..dule.js gzip 6.92 kB N/A N/A
framework.HA..dule.js gzip 39.1 kB 39.1 kB
de003c3a9d30..dule.js gzip N/A 7.26 kB N/A
Overall change 52.4 kB 52.7 kB ⚠️ +338 B
Legacy Client Bundles (polyfills)
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
polyfills-HASH.js gzip 26.3 kB 26.3 kB
Overall change 26.3 kB 26.3 kB
Client Pages
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.js gzip 1.26 kB 1.26 kB
_error.js gzip 3.25 kB 3.25 kB
hooks.js gzip 881 B 881 B
index.js gzip 222 B 222 B
link.js gzip 2.05 kB 2.05 kB
routerDirect.js gzip 279 B 279 B
withRouter.js gzip 278 B 278 B
Overall change 8.22 kB 8.22 kB
Client Pages Modern
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_app.module.js gzip 604 B 604 B
_error.module.js gzip 2.04 kB 2.04 kB
hooks.module.js gzip 383 B 383 B
index.module.js gzip 223 B 223 B
link.module.js gzip 1.52 kB 1.52 kB
routerDirect..dule.js gzip 281 B 281 B
withRouter.m..dule.js gzip 278 B 278 B
Overall change 5.33 kB 5.33 kB
Client Build Manifests
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_buildManifest.js gzip 171 B 171 B
_buildManife..dule.js gzip 180 B 180 B
Overall change 351 B 351 B
Serverless bundles Overall increase ⚠️
vercel/next.js canary ijjk/next.js add/scroll-restoration Change
_error.js 874 kB 874 kB
404.html 4.13 kB 4.13 kB
hooks.html 3.71 kB 3.71 kB
index.js 875 kB 875 kB
link.js 913 kB 914 kB ⚠️ +1.66 kB
routerDirect.js 905 kB 907 kB ⚠️ +1.66 kB
withRouter.js 905 kB 907 kB ⚠️ +1.66 kB
Overall change 4.48 MB 4.49 MB ⚠️ +4.98 kB

@kodiakhq kodiakhq bot merged commit 06ac0ad into vercel:canary Jun 9, 2020
Timer added a commit that referenced this pull request Jun 11, 2020
rokinsky pushed a commit to rokinsky/next.js that referenced this pull request Jul 11, 2020
This adds scroll restoration handling to make sure the correct scroll position is restored after navigating back/forward to a page and the rendering hasn't completed by the time the default browser scroll restoration has taken place. 

An initial failing test case was added which is working with the changes in this PR, if there are any other cases that should be added let me know and I can make sure we have them to ensure we don't regress on this behavior

---

Fixes vercel#12530
@vercel vercel locked as resolved and limited conversation to collaborators Jan 30, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Using getServerSideProps breaks scroll restoration
2 participants