Skip to content

Commit

Permalink
fix hydration mismatch on href for url with anchor refs (#21065)
Browse files Browse the repository at this point in the history
Co-authored-by: Tim Neutkens <tim@timneutkens.nl>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
3 people committed Jan 15, 2021
1 parent ceef156 commit cdab7bf
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 1 deletion.
3 changes: 2 additions & 1 deletion packages/next/next-server/lib/router/router.ts
Expand Up @@ -163,7 +163,8 @@ export function delBasePath(path: string): string {
* Detects whether a given url is routable by the Next.js router (browser only).
*/
export function isLocalURL(url: string): boolean {
if (url.startsWith('/')) return true
// prevent a hydration mismatch on href for url with anchor refs
if (url.startsWith('/') || url.startsWith('#')) return true
try {
// absolute urls can be local if they are on the same origin
const locationOrigin = getLocationOrigin()
Expand Down
14 changes: 14 additions & 0 deletions test/integration/link-with-hash/pages/index.js
@@ -0,0 +1,14 @@
import React from 'react'
import Link from 'next/link'

const Home = () => {
return (
<>
<Link href="#hash-link">
<a>Hash Link</a>
</Link>
</>
)
}

export default Home
53 changes: 53 additions & 0 deletions test/integration/link-with-hash/test/index.test.js
@@ -0,0 +1,53 @@
/* eslint-env jest */

import { join } from 'path'
import webdriver from 'next-webdriver'
import {
findPort,
launchApp,
killApp,
nextStart,
nextBuild,
} from 'next-test-utils'

jest.setTimeout(1000 * 60 * 5)
let app
let appPort
const appDir = join(__dirname, '..')

const runTests = () => {
it('should not have hydration mis-match for hash link', async () => {
const browser = await webdriver(appPort, '/')
const browserLogs = await browser.log('browser')
let found = false
browserLogs.forEach((log) => {
if (log.message.includes('Warning: Prop')) {
found = true
}
})
expect(found).toEqual(false)
})
}

describe('Link with hash href', () => {
describe('development', () => {
beforeAll(async () => {
appPort = await findPort()
app = await launchApp(appDir, appPort)
})
afterAll(() => killApp(app))

runTests()
})

describe('production', () => {
beforeAll(async () => {
await nextBuild(appDir)
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(() => killApp(app))

runTests()
})
})

1 comment on commit cdab7bf

@ijjk
Copy link
Member

@ijjk ijjk commented on cdab7bf Jan 15, 2021

Choose a reason for hiding this comment

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

Stats from current release

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary v9.5.5 vercel/next.js refs/heads/canary Change
buildDuration 8.3s 8.9s ⚠️ +646ms
nodeModulesSize 61.9 MB 77.5 MB ⚠️ +15.6 MB
Page Load Tests Overall increase ✓
vercel/next.js canary v9.5.5 vercel/next.js refs/heads/canary Change
/ failed reqs 0 0
/ total time (seconds) 1.835 1.78 -0.05
/ avg req/sec 1362.17 1404.13 +41.96
/error-in-render failed reqs 0 0
/error-in-render total time (seconds) 1.094 1.109 ⚠️ +0.01
/error-in-render avg req/sec 2285.74 2253.96 ⚠️ -31.78
Client Bundles (main, webpack, commons) Overall increase ⚠️
vercel/next.js canary v9.5.5 vercel/next.js refs/heads/canary Change
677f882d2ed8..9b19.js gzip 11.1 kB 13.1 kB ⚠️ +2 kB
framework.HASH.js gzip 39 kB 39 kB ⚠️ +14 B
main-79d6d55..698e.js gzip 7.2 kB N/A N/A
webpack-e067..f178.js gzip 751 B 751 B
main-712e20f..aa05.js gzip N/A 6.63 kB N/A
Overall change 58 kB 59.4 kB ⚠️ +1.45 kB
Legacy Client Bundles (polyfills) Overall increase ⚠️
vercel/next.js canary v9.5.5 vercel/next.js refs/heads/canary Change
polyfills-4b..e242.js gzip 31 kB 31.3 kB ⚠️ +265 B
Overall change 31 kB 31.3 kB ⚠️ +265 B
Client Pages Overall increase ⚠️
vercel/next.js canary v9.5.5 vercel/next.js refs/heads/canary Change
_app-9a0b9e1..b37e.js gzip 1.28 kB 1.28 kB
_error-ed1b0..8fbd.js gzip 3.44 kB 3.46 kB ⚠️ +17 B
hooks-89731c..c609.js gzip 887 B 887 B
index-17468f..5d83.js gzip 227 B 227 B
link-409b283..e3ab.js gzip 1.32 kB N/A N/A
routerDirect..924c.js gzip 284 B 303 B ⚠️ +19 B
withRouter-7..c13d.js gzip 284 B 302 B ⚠️ +18 B
link-7faf09b..eba4.js gzip N/A 1.64 kB N/A
Overall change 7.73 kB 8.09 kB ⚠️ +368 B
Client Build Manifests Overall decrease ✓
vercel/next.js canary v9.5.5 vercel/next.js refs/heads/canary Change
_buildManifest.js gzip 323 B 321 B -2 B
Overall change 323 B 321 B -2 B
Rendered Page Sizes Overall decrease ✓
vercel/next.js canary v9.5.5 vercel/next.js refs/heads/canary Change
index.html gzip 646 B 615 B -31 B
link.html gzip 652 B 620 B -32 B
withRouter.html gzip 639 B 608 B -31 B
Overall change 1.94 kB 1.84 kB -94 B

Diffs

Diff for _buildManifest.js
@@ -1,18 +1,18 @@
 self.__BUILD_MANIFEST = {
   __rewrites: [],
-  "/": ["static\u002Fchunks\u002Fpages\u002Findex-283eed3c1520dcc26e8d.js"],
+  "/": ["static\u002Fchunks\u002Fpages\u002Findex-5219d40a02e71ed7dcbf.js"],
   "/_error": [
-    "static\u002Fchunks\u002Fpages\u002F_error-a0c4519f5ca8e97fa7be.js"
+    "static\u002Fchunks\u002Fpages\u002F_error-e3034768442652eac2c9.js"
   ],
   "/hooks": [
-    "static\u002Fchunks\u002Fpages\u002Fhooks-8001dc76075832ee8949.js"
+    "static\u002Fchunks\u002Fpages\u002Fhooks-1de3df238a86bcb083d4.js"
   ],
-  "/link": ["static\u002Fchunks\u002Fpages\u002Flink-67e857671520c009f99f.js"],
+  "/link": ["static\u002Fchunks\u002Fpages\u002Flink-3a08ad7c5282582ee217.js"],
   "/routerDirect": [
-    "static\u002Fchunks\u002Fpages\u002FrouterDirect-2e9bfd441bd88cd3382e.js"
+    "static\u002Fchunks\u002Fpages\u002FrouterDirect-a5bdcfc87579b1d2776d.js"
   ],
   "/withRouter": [
-    "static\u002Fchunks\u002Fpages\u002FwithRouter-9af1d72bd996729e701e.js"
+    "static\u002Fchunks\u002Fpages\u002FwithRouter-748b809bbc7636857f70.js"
   ],
   sortedPages: [
     "\u002F",
Diff for _error-a0c45..8e97fa7be.js
@@ -461,8 +461,10 @@ Also adds support for deduplicated `key` properties
         var metaCategories = {};
         return function(h) {
           var isUnique = true;
+          var hasKey = false;
 
           if (h.key && typeof h.key !== "number" && h.key.indexOf("$") > 0) {
+            hasKey = true;
             var key = h.key.slice(h.key.indexOf("$") + 1);
 
             if (keys.has(key)) {
@@ -498,7 +500,10 @@ Also adds support for deduplicated `key` properties
                   var category = h.props[metatype];
                   var categories = metaCategories[metatype] || new Set();
 
-                  if (categories.has(category)) {
+                  if (
+                    (metatype !== "name" || !hasKey) &&
+                    categories.has(category)
+                  ) {
                     isUnique = false;
                   } else {
                     categories.add(category);
Diff for link-3a08ad7..2582ee217.js
@@ -0,0 +1,435 @@
+_N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
+  [8],
+  {
+    /***/ ObF3: /***/ function(
+      module,
+      __webpack_exports__,
+      __webpack_require__
+    ) {
+      "use strict";
+      __webpack_require__.r(__webpack_exports__);
+      /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(
+        "q1tI"
+      );
+      /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/ __webpack_require__.n(
+        react__WEBPACK_IMPORTED_MODULE_0__
+      );
+      /* harmony import */ var next_link__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(
+        "YFqc"
+      );
+      /* harmony import */ var next_link__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/ __webpack_require__.n(
+        next_link__WEBPACK_IMPORTED_MODULE_1__
+      );
+
+      var __jsx = react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement;
+
+      function aLink(props) {
+        return __jsx(
+          "div",
+          null,
+          __jsx("h3", null, "A Link page!"),
+          __jsx(
+            next_link__WEBPACK_IMPORTED_MODULE_1___default.a,
+            {
+              href: "/"
+            },
+            "Go to /"
+          )
+        );
+      }
+
+      aLink.getInitialProps = function() {
+        return {};
+      };
+
+      /* harmony default export */ __webpack_exports__["default"] = aLink;
+
+      /***/
+    },
+
+    /***/ V8Sf: /***/ function(module, exports, __webpack_require__) {
+      (window.__NEXT_P = window.__NEXT_P || []).push([
+        "/link",
+        function() {
+          return __webpack_require__("ObF3");
+        }
+      ]);
+
+      /***/
+    },
+
+    /***/ YFqc: /***/ function(module, exports, __webpack_require__) {
+      module.exports = __webpack_require__("cTJO");
+
+      /***/
+    },
+
+    /***/ cTJO: /***/ function(module, exports, __webpack_require__) {
+      "use strict";
+
+      var _slicedToArray = __webpack_require__("J4zp");
+
+      var _interopRequireWildcard = __webpack_require__("284h");
+
+      exports.__esModule = true;
+      exports["default"] = void 0;
+
+      var _react = _interopRequireWildcard(__webpack_require__("q1tI"));
+
+      var _router = __webpack_require__("elyg");
+
+      var _router2 = __webpack_require__("nOHt");
+
+      var _useIntersection = __webpack_require__("vNVm");
+
+      var prefetched = {};
+
+      function prefetch(router, href, as, options) {
+        if (false || !router) return;
+        if (!(0, _router.isLocalURL)(href)) return; // Prefetch the JSON page if asked (only in the client)
+        // We need to handle a prefetch error here since we may be
+        // loading with priority which can reject but we don't
+        // want to force navigation since this is only a prefetch
+
+        router.prefetch(href, as, options)["catch"](function(err) {
+          if (false) {
+          }
+        });
+        var curLocale =
+          options && typeof options.locale !== "undefined"
+            ? options.locale
+            : router && router.locale; // Join on an invalid URI character
+
+        prefetched[href + "%" + as + (curLocale ? "%" + curLocale : "")] = true;
+      }
+
+      function isModifiedEvent(event) {
+        var target = event.currentTarget.target;
+        return (
+          (target && target !== "_self") ||
+          event.metaKey ||
+          event.ctrlKey ||
+          event.shiftKey ||
+          event.altKey || // triggers resource download
+          (event.nativeEvent && event.nativeEvent.which === 2)
+        );
+      }
+
+      function linkClicked(
+        e,
+        router,
+        href,
+        as,
+        replace,
+        shallow,
+        scroll,
+        locale
+      ) {
+        var nodeName = e.currentTarget.nodeName;
+
+        if (
+          nodeName === "A" &&
+          (isModifiedEvent(e) || !(0, _router.isLocalURL)(href))
+        ) {
+          // ignore click for browser’s default behavior
+          return;
+        }
+
+        e.preventDefault(); //  avoid scroll for urls with anchor refs
+
+        if (scroll == null) {
+          scroll = as.indexOf("#") < 0;
+        } // replace state instead of push if prop is present
+
+        router[replace ? "replace" : "push"](href, as, {
+          shallow: shallow,
+          locale: locale,
+          scroll: scroll
+        }).then(function(success) {
+          if (!success) return;
+
+          if (scroll) {
+            // FIXME: proper route announcing at Router level, not Link:
+            document.body.focus();
+          }
+        });
+      }
+
+      function Link(props) {
+        if (false) {
+          var hasWarned,
+            optionalProps,
+            optionalPropsGuard,
+            requiredProps,
+            requiredPropsGuard,
+            createPropError;
+        }
+
+        var p = props.prefetch !== false;
+        var router = (0, _router2.useRouter)();
+        var pathname = (router && router.pathname) || "/";
+
+        var _react$default$useMem = _react["default"].useMemo(
+            function() {
+              var _ref = (0, _router.resolveHref)(pathname, props.href, true),
+                _ref2 = _slicedToArray(_ref, 2),
+                resolvedHref = _ref2[0],
+                resolvedAs = _ref2[1];
+
+              return {
+                href: resolvedHref,
+                as: props.as
+                  ? (0, _router.resolveHref)(pathname, props.as)
+                  : resolvedAs || resolvedHref
+              };
+            },
+            [pathname, props.href, props.as]
+          ),
+          href = _react$default$useMem.href,
+          as = _react$default$useMem.as;
+
+        var children = props.children,
+          replace = props.replace,
+          shallow = props.shallow,
+          scroll = props.scroll,
+          locale = props.locale; // Deprecated. Warning shown by propType check. If the children provided is a string (<Link>example</Link>) we wrap it in an <a> tag
+
+        if (typeof children === "string") {
+          children = /*#__PURE__*/ _react["default"].createElement(
+            "a",
+            null,
+            children
+          );
+        } // This will return the first child, if multiple are provided it will throw an error
+
+        var child = _react.Children.only(children);
+
+        var childRef = child && typeof child === "object" && child.ref;
+
+        var _ref3 = (0, _useIntersection.useIntersection)({
+            rootMargin: "200px"
+          }),
+          _ref4 = _slicedToArray(_ref3, 2),
+          setIntersectionRef = _ref4[0],
+          isVisible = _ref4[1];
+
+        var setRef = _react["default"].useCallback(
+          function(el) {
+            setIntersectionRef(el);
+
+            if (childRef) {
+              if (typeof childRef === "function") childRef(el);
+              else if (typeof childRef === "object") {
+                childRef.current = el;
+              }
+            }
+          },
+          [childRef, setIntersectionRef]
+        );
+
+        (0, _react.useEffect)(
+          function() {
+            var shouldPrefetch =
+              isVisible && p && (0, _router.isLocalURL)(href);
+            var curLocale =
+              typeof locale !== "undefined" ? locale : router && router.locale;
+            var isPrefetched =
+              prefetched[href + "%" + as + (curLocale ? "%" + curLocale : "")];
+
+            if (shouldPrefetch && !isPrefetched) {
+              prefetch(router, href, as, {
+                locale: curLocale
+              });
+            }
+          },
+          [as, href, isVisible, locale, p, router]
+        );
+        var childProps = {
+          ref: setRef,
+          onClick: function onClick(e) {
+            if (child.props && typeof child.props.onClick === "function") {
+              child.props.onClick(e);
+            }
+
+            if (!e.defaultPrevented) {
+              linkClicked(
+                e,
+                router,
+                href,
+                as,
+                replace,
+                shallow,
+                scroll,
+                locale
+              );
+            }
+          }
+        };
+
+        childProps.onMouseEnter = function(e) {
+          if (!(0, _router.isLocalURL)(href)) return;
+
+          if (child.props && typeof child.props.onMouseEnter === "function") {
+            child.props.onMouseEnter(e);
+          }
+
+          prefetch(router, href, as, {
+            priority: true
+          });
+        }; // If child is an <a> tag and doesn't have a href attribute, or if the 'passHref' property is
+        // defined, we specify the current 'href', so that repetition is not needed by the user
+
+        if (
+          props.passHref ||
+          (child.type === "a" && !("href" in child.props))
+        ) {
+          var curLocale =
+            typeof locale !== "undefined" ? locale : router && router.locale;
+          var localeDomain = (0, _router.getDomainLocale)(
+            as,
+            curLocale,
+            router && router.locales,
+            router && router.domainLocales
+          );
+          childProps.href =
+            localeDomain ||
+            (0, _router.addBasePath)(
+              (0, _router.addLocale)(
+                as,
+                curLocale,
+                router && router.defaultLocale
+              )
+            );
+        }
+
+        return /*#__PURE__*/ _react["default"].cloneElement(child, childProps);
+      }
+
+      var _default = Link;
+      exports["default"] = _default;
+
+      /***/
+    },
+
+    /***/ vNVm: /***/ function(module, exports, __webpack_require__) {
+      "use strict";
+
+      var _slicedToArray = __webpack_require__("J4zp");
+
+      var _interopRequireDefault = __webpack_require__("TqRt");
+
+      exports.__esModule = true;
+      exports.useIntersection = useIntersection;
+
+      var _react = __webpack_require__("q1tI");
+
+      var _requestIdleCallback = _interopRequireDefault(
+        __webpack_require__("0G5g")
+      );
+
+      var hasIntersectionObserver = typeof IntersectionObserver !== "undefined";
+
+      function useIntersection(_ref) {
+        var rootMargin = _ref.rootMargin,
+          disabled = _ref.disabled;
+        var isDisabled = disabled || !hasIntersectionObserver;
+        var unobserve = (0, _react.useRef)();
+
+        var _ref2 = (0, _react.useState)(false),
+          _ref3 = _slicedToArray(_ref2, 2),
+          visible = _ref3[0],
+          setVisible = _ref3[1];
+
+        var setRef = (0, _react.useCallback)(
+          function(el) {
+            if (unobserve.current) {
+              unobserve.current();
+              unobserve.current = undefined;
+            }
+
+            if (isDisabled || visible) return;
+
+            if (el && el.tagName) {
+              unobserve.current = observe(
+                el,
+                function(isVisible) {
+                  return isVisible && setVisible(isVisible);
+                },
+                {
+                  rootMargin: rootMargin
+                }
+              );
+            }
+          },
+          [isDisabled, rootMargin, visible]
+        );
+        (0, _react.useEffect)(
+          function() {
+            if (!hasIntersectionObserver) {
+              if (!visible)
+                (0, _requestIdleCallback["default"])(function() {
+                  return setVisible(true);
+                });
+            }
+          },
+          [visible]
+        );
+        return [setRef, visible];
+      }
+
+      function observe(element, callback, options) {
+        var _createObserver = createObserver(options),
+          id = _createObserver.id,
+          observer = _createObserver.observer,
+          elements = _createObserver.elements;
+
+        elements.set(element, callback);
+        observer.observe(element);
+        return function unobserve() {
+          elements["delete"](element);
+          observer.unobserve(element); // Destroy observer when there's nothing left to watch:
+
+          if (elements.size === 0) {
+            observer.disconnect();
+            observers["delete"](id);
+          }
+        };
+      }
+
+      var observers = new Map();
+
+      function createObserver(options) {
+        var id = options.rootMargin || "";
+        var instance = observers.get(id);
+
+        if (instance) {
+          return instance;
+        }
+
+        var elements = new Map();
+        var observer = new IntersectionObserver(function(entries) {
+          entries.forEach(function(entry) {
+            var callback = elements.get(entry.target);
+            var isVisible = entry.isIntersecting || entry.intersectionRatio > 0;
+
+            if (callback && isVisible) {
+              callback(isVisible);
+            }
+          });
+        }, options);
+        observers.set(
+          id,
+          (instance = {
+            id: id,
+            observer: observer,
+            elements: elements
+          })
+        );
+        return instance;
+      }
+
+      /***/
+    }
+  },
+  [["V8Sf", 0, 1, 2]]
+]);
Diff for link-67e8576..0c009f99f.js
deleted
Diff for routerDirect..88cd3382e.js
@@ -1,6 +1,12 @@
 _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
   [9],
   {
+    /***/ "20a2": /***/ function(module, exports, __webpack_require__) {
+      module.exports = __webpack_require__("nOHt");
+
+      /***/
+    },
+
     /***/ LtRI: /***/ function(module, exports, __webpack_require__) {
       (window.__NEXT_P = window.__NEXT_P || []).push([
         "/routerDirect",
@@ -26,7 +32,7 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
         react__WEBPACK_IMPORTED_MODULE_0__
       );
       /* harmony import */ var next_router__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(
-        "nOHt"
+        "20a2"
       );
       /* harmony import */ var next_router__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/ __webpack_require__.n(
         next_router__WEBPACK_IMPORTED_MODULE_1__
Diff for withRouter-9..6729e701e.js
@@ -15,7 +15,7 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
         react__WEBPACK_IMPORTED_MODULE_0__
       );
       /* harmony import */ var next_router__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(
-        "nOHt"
+        "20a2"
       );
       /* harmony import */ var next_router__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/ __webpack_require__.n(
         next_router__WEBPACK_IMPORTED_MODULE_1__
@@ -38,6 +38,12 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
       /***/
     },
 
+    /***/ "20a2": /***/ function(module, exports, __webpack_require__) {
+      module.exports = __webpack_require__("nOHt");
+
+      /***/
+    },
+
     /***/ eThv: /***/ function(module, exports, __webpack_require__) {
       (window.__NEXT_P = window.__NEXT_P || []).push([
         "/withRouter",
Diff for 677f882d2ed8..4eeebf399.js

Diff too large to display

Diff for main-2aa8068..281f09665.js

Diff too large to display

Diff for polyfills-f7..972ef83e9.js
failed to diff
Diff for index.html
@@ -3,10 +3,11 @@
   <head>
     <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width" />
-    <noscript data-n-css="true"></noscript>
+    <meta name="next-head-count" content="2" />
+    <noscript data-n-css=""></noscript>
     <link
       rel="preload"
-      href="/_next/static/chunks/main-2aa8068f0cc281f09665.js"
+      href="/_next/static/chunks/main-82580def8071a0a14a04.js"
       as="script"
     />
     <link
@@ -21,17 +22,17 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.5472d08d2594eeebf399.js"
+      href="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.68413f75a18d3759e1c6.js"
       as="script"
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/pages/_app-7512045a5b3d9376e2ca.js"
+      href="/_next/static/chunks/pages/_app-b9cf267ce11e4373e54e.js"
       as="script"
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/pages/index-283eed3c1520dcc26e8d.js"
+      href="/_next/static/chunks/pages/index-5219d40a02e71ed7dcbf.js"
       as="script"
     />
   </head>
@@ -44,19 +45,15 @@
         "query": {},
         "buildId": "BUILD_ID",
         "isFallback": false,
-        "gip": true,
-        "head": [
-          ["meta", { "charSet": "utf-8" }],
-          ["meta", { "name": "viewport", "content": "width=device-width" }]
-        ]
+        "gip": true
       }
     </script>
     <script
       nomodule=""
-      src="/_next/static/chunks/polyfills-f73ba3fc145972ef83e9.js"
+      src="/_next/static/chunks/polyfills-7cd0807c85ae48513b2d.js"
     ></script>
     <script
-      src="/_next/static/chunks/main-2aa8068f0cc281f09665.js"
+      src="/_next/static/chunks/main-82580def8071a0a14a04.js"
       async=""
     ></script>
     <script
@@ -68,15 +65,15 @@
       async=""
     ></script>
     <script
-      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.5472d08d2594eeebf399.js"
+      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.68413f75a18d3759e1c6.js"
       async=""
     ></script>
     <script
-      src="/_next/static/chunks/pages/_app-7512045a5b3d9376e2ca.js"
+      src="/_next/static/chunks/pages/_app-b9cf267ce11e4373e54e.js"
       async=""
     ></script>
     <script
-      src="/_next/static/chunks/pages/index-283eed3c1520dcc26e8d.js"
+      src="/_next/static/chunks/pages/index-5219d40a02e71ed7dcbf.js"
       async=""
     ></script>
     <script src="/_next/static/BUILD_ID/_buildManifest.js" async=""></script>
Diff for link.html
@@ -3,10 +3,11 @@
   <head>
     <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width" />
-    <noscript data-n-css="true"></noscript>
+    <meta name="next-head-count" content="2" />
+    <noscript data-n-css=""></noscript>
     <link
       rel="preload"
-      href="/_next/static/chunks/main-2aa8068f0cc281f09665.js"
+      href="/_next/static/chunks/main-82580def8071a0a14a04.js"
       as="script"
     />
     <link
@@ -21,17 +22,17 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.5472d08d2594eeebf399.js"
+      href="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.68413f75a18d3759e1c6.js"
       as="script"
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/pages/_app-7512045a5b3d9376e2ca.js"
+      href="/_next/static/chunks/pages/_app-b9cf267ce11e4373e54e.js"
       as="script"
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/pages/link-67e857671520c009f99f.js"
+      href="/_next/static/chunks/pages/link-3a08ad7c5282582ee217.js"
       as="script"
     />
   </head>
@@ -49,19 +50,15 @@
         "query": {},
         "buildId": "BUILD_ID",
         "isFallback": false,
-        "gip": true,
-        "head": [
-          ["meta", { "charSet": "utf-8" }],
-          ["meta", { "name": "viewport", "content": "width=device-width" }]
-        ]
+        "gip": true
       }
     </script>
     <script
       nomodule=""
-      src="/_next/static/chunks/polyfills-f73ba3fc145972ef83e9.js"
+      src="/_next/static/chunks/polyfills-7cd0807c85ae48513b2d.js"
     ></script>
     <script
-      src="/_next/static/chunks/main-2aa8068f0cc281f09665.js"
+      src="/_next/static/chunks/main-82580def8071a0a14a04.js"
       async=""
     ></script>
     <script
@@ -73,15 +70,15 @@
       async=""
     ></script>
     <script
-      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.5472d08d2594eeebf399.js"
+      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.68413f75a18d3759e1c6.js"
       async=""
     ></script>
     <script
-      src="/_next/static/chunks/pages/_app-7512045a5b3d9376e2ca.js"
+      src="/_next/static/chunks/pages/_app-b9cf267ce11e4373e54e.js"
       async=""
     ></script>
     <script
-      src="/_next/static/chunks/pages/link-67e857671520c009f99f.js"
+      src="/_next/static/chunks/pages/link-3a08ad7c5282582ee217.js"
       async=""
     ></script>
     <script src="/_next/static/BUILD_ID/_buildManifest.js" async=""></script>
Diff for withRouter.html
@@ -3,10 +3,11 @@
   <head>
     <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width" />
-    <noscript data-n-css="true"></noscript>
+    <meta name="next-head-count" content="2" />
+    <noscript data-n-css=""></noscript>
     <link
       rel="preload"
-      href="/_next/static/chunks/main-2aa8068f0cc281f09665.js"
+      href="/_next/static/chunks/main-82580def8071a0a14a04.js"
       as="script"
     />
     <link
@@ -21,17 +22,17 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.5472d08d2594eeebf399.js"
+      href="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.68413f75a18d3759e1c6.js"
       as="script"
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/pages/_app-7512045a5b3d9376e2ca.js"
+      href="/_next/static/chunks/pages/_app-b9cf267ce11e4373e54e.js"
       as="script"
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/pages/withRouter-9af1d72bd996729e701e.js"
+      href="/_next/static/chunks/pages/withRouter-748b809bbc7636857f70.js"
       as="script"
     />
   </head>
@@ -44,19 +45,15 @@
         "query": {},
         "buildId": "BUILD_ID",
         "isFallback": false,
-        "gip": true,
-        "head": [
-          ["meta", { "charSet": "utf-8" }],
-          ["meta", { "name": "viewport", "content": "width=device-width" }]
-        ]
+        "gip": true
       }
     </script>
     <script
       nomodule=""
-      src="/_next/static/chunks/polyfills-f73ba3fc145972ef83e9.js"
+      src="/_next/static/chunks/polyfills-7cd0807c85ae48513b2d.js"
     ></script>
     <script
-      src="/_next/static/chunks/main-2aa8068f0cc281f09665.js"
+      src="/_next/static/chunks/main-82580def8071a0a14a04.js"
       async=""
     ></script>
     <script
@@ -68,15 +65,15 @@
       async=""
     ></script>
     <script
-      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.5472d08d2594eeebf399.js"
+      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.68413f75a18d3759e1c6.js"
       async=""
     ></script>
     <script
-      src="/_next/static/chunks/pages/_app-7512045a5b3d9376e2ca.js"
+      src="/_next/static/chunks/pages/_app-b9cf267ce11e4373e54e.js"
       async=""
     ></script>
     <script
-      src="/_next/static/chunks/pages/withRouter-9af1d72bd996729e701e.js"
+      src="/_next/static/chunks/pages/withRouter-748b809bbc7636857f70.js"
       async=""
     ></script>
     <script src="/_next/static/BUILD_ID/_buildManifest.js" async=""></script>

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary v9.5.5 vercel/next.js refs/heads/canary Change
buildDuration 9.7s 10.4s ⚠️ +699ms
nodeModulesSize 61.9 MB 77.5 MB ⚠️ +15.6 MB
Client Bundles (main, webpack, commons) Overall increase ⚠️
vercel/next.js canary v9.5.5 vercel/next.js refs/heads/canary Change
677f882d2ed8..9b19.js gzip 11.1 kB N/A N/A
framework.HASH.js gzip 39 kB 39 kB ⚠️ +14 B
main-79d6d55..698e.js gzip 7.2 kB N/A N/A
webpack-e067..f178.js gzip 751 B N/A N/A
677f882d2ed8..43e3.js gzip N/A 13.1 kB N/A
main-712e20f..aa05.js gzip N/A 6.63 kB N/A
webpack-50be..df5b.js gzip N/A 751 B N/A
Overall change 58 kB 59.4 kB ⚠️ +1.45 kB
Legacy Client Bundles (polyfills) Overall increase ⚠️
vercel/next.js canary v9.5.5 vercel/next.js refs/heads/canary Change
polyfills-4b..e242.js gzip 31 kB N/A N/A
polyfills-af..9390.js gzip N/A 31.3 kB N/A
Overall change 31 kB 31.3 kB ⚠️ +265 B
Client Pages Overall increase ⚠️
vercel/next.js canary v9.5.5 vercel/next.js refs/heads/canary Change
_app-9a0b9e1..b37e.js gzip 1.28 kB N/A N/A
_error-ed1b0..8fbd.js gzip 3.44 kB N/A N/A
hooks-89731c..c609.js gzip 887 B N/A N/A
index-17468f..5d83.js gzip 227 B N/A N/A
link-409b283..e3ab.js gzip 1.32 kB N/A N/A
routerDirect..924c.js gzip 284 B N/A N/A
withRouter-7..c13d.js gzip 284 B N/A N/A
_app-2a09aa2..4a98.js gzip N/A 1.28 kB N/A
_error-8b758..aef6.js gzip N/A 3.46 kB N/A
hooks-c71ae4..70cd.js gzip N/A 887 B N/A
index-bbee2f..528b.js gzip N/A 227 B N/A
link-7faf09b..eba4.js gzip N/A 1.64 kB N/A
routerDirect..bf84.js gzip N/A 303 B N/A
withRouter-a..5826.js gzip N/A 302 B N/A
Overall change 7.73 kB 8.09 kB ⚠️ +368 B
Client Build Manifests Overall decrease ✓
vercel/next.js canary v9.5.5 vercel/next.js refs/heads/canary Change
_buildManifest.js gzip 323 B 321 B -2 B
Overall change 323 B 321 B -2 B
Serverless bundles Overall decrease ✓
vercel/next.js canary v9.5.5 vercel/next.js refs/heads/canary Change
_error.js 1.05 MB 1 MB -49.4 kB
404.html 2.6 kB 2.67 kB ⚠️ +69 B
hooks.html 1.98 kB 1.92 kB -60 B
index.js 1.05 MB 1 MB -49.4 kB
link.js 1.1 MB 1.06 MB -38.3 kB
routerDirect.js 1.09 MB 1.05 MB -40 kB
withRouter.js 1.09 MB 1.05 MB -40 kB
Overall change 5.4 MB 5.18 MB -217 kB

Please sign in to comment.