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

Ensure interpolating dynamic href values works correctly #16774

Merged
merged 5 commits into from Sep 2, 2020

Conversation

ijjk
Copy link
Member

@ijjk ijjk commented Sep 2, 2020

This corrects/makes sure interpolating dynamic route values for href works correctly. This provides an alternative approach to building the href value with next/link so that you don't need to worry about encoding the params manually.

Closes: #13473
Closes: #14959
Closes: #16771

@ijjk

This comment has been minimized.

@ijjk

This comment has been minimized.

@ijjk
Copy link
Member Author

ijjk commented Sep 2, 2020

Stats from current PR

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
buildDuration 11.9s 12.1s ⚠️ +175ms
nodeModulesSize 55.9 MB 55.9 MB ⚠️ +2.17 kB
Page Load Tests Overall decrease ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
/ failed reqs 0 0
/ total time (seconds) 2.156 2.192 ⚠️ +0.04
/ avg req/sec 1159.59 1140.33 ⚠️ -19.26
/error-in-render failed reqs 0 0
/error-in-render total time (seconds) 1.187 1.179 -0.01
/error-in-render avg req/sec 2106.03 2120.85 +14.82
Client Bundles (main, webpack, commons) Overall increase ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
677f882d2ed8..9ff9.js gzip 10.3 kB 10.5 kB ⚠️ +267 B
framework.HASH.js gzip 39 kB 39 kB
main-e1c4209..e2c9.js gzip 7.32 kB 7.1 kB -221 B
webpack-e067..f178.js gzip 751 B 751 B
Overall change 57.3 kB 57.4 kB ⚠️ +46 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
677f882d2ed8..dule.js gzip 6.13 kB 6.41 kB ⚠️ +278 B
framework.HA..dule.js gzip 39 kB 39 kB
main-9077898..dule.js gzip 6.38 kB 6.16 kB -220 B
webpack-07c5..dule.js gzip 751 B 751 B
Overall change 52.2 kB 52.3 kB ⚠️ +58 B
Legacy Client Bundles (polyfills)
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
polyfills-4b..e242.js gzip 31 kB 31 kB
Overall change 31 kB 31 kB
Client Pages Overall increase ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
_app-9a0b9e1..b37e.js gzip 1.28 kB 1.28 kB
_error-ed1b0..8fbd.js gzip 3.44 kB 3.44 kB
hooks-89731c..c609.js gzip 887 B 887 B
index-17468f..5d83.js gzip 227 B 227 B
link-ae98065..267e.js gzip 1.29 kB 1.3 kB ⚠️ +16 B
routerDirect..924c.js gzip 284 B 284 B
withRouter-7..c13d.js gzip 284 B 284 B
Overall change 7.69 kB 7.71 kB ⚠️ +16 B
Client Pages Modern Overall increase ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
_app-75d3a82..dule.js gzip 625 B 625 B
_error-4469a..dule.js gzip 2.29 kB 2.29 kB
hooks-cbf13f..dule.js gzip 387 B 387 B
index-b9a643..dule.js gzip 226 B 226 B
link-cb244c4..dule.js gzip 1.26 kB 1.26 kB ⚠️ +5 B
routerDirect..dule.js gzip 284 B 284 B
withRouter-f..dule.js gzip 282 B 282 B
Overall change 5.35 kB 5.36 kB ⚠️ +5 B
Client Build Manifests Overall decrease ✓
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
_buildManifest.js gzip 323 B 322 B -1 B
_buildManife..dule.js gzip 329 B 329 B
Overall change 652 B 651 B -1 B
Rendered Page Sizes
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
index.html gzip 971 B 971 B
link.html gzip 976 B 976 B
withRouter.html gzip 963 B 963 B
Overall change 2.91 kB 2.91 kB

Diffs

Diff for _buildManifest.js
@@ -7,7 +7,7 @@ self.__BUILD_MANIFEST = {
   "/hooks": [
     "static\u002Fchunks\u002Fpages\u002Fhooks-8001dc76075832ee8949.js"
   ],
-  "/link": ["static\u002Fchunks\u002Fpages\u002Flink-46fd48c0b73b2f2d75a4.js"],
+  "/link": ["static\u002Fchunks\u002Fpages\u002Flink-32658e75d53af2daa2e0.js"],
   "/routerDirect": [
     "static\u002Fchunks\u002Fpages\u002FrouterDirect-2e9bfd441bd88cd3382e.js"
   ],
Diff for _buildManifest.module.js
@@ -10,7 +10,7 @@ self.__BUILD_MANIFEST = {
     "static\u002Fchunks\u002Fpages\u002Fhooks-56fa58a6f0993d7d36d7.module.js"
   ],
   "/link": [
-    "static\u002Fchunks\u002Fpages\u002Flink-e2f1e0e7ed02569239da.module.js"
+    "static\u002Fchunks\u002Fpages\u002Flink-cb038f0ac2e648ce4861.module.js"
   ],
   "/routerDirect": [
     "static\u002Fchunks\u002Fpages\u002FrouterDirect-368af3dfef3c9cd99dc3.module.js"
Diff for link-46fd48c..b2f2d75a4.js
@@ -216,12 +216,16 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
 
         var _react$default$useMem = _react["default"].useMemo(
             function() {
-              var resolvedHref = (0, _router.resolveHref)(pathname, props.href);
+              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)
-                  : resolvedHref
+                  : resolvedAs || resolvedHref
               };
             },
             [pathname, props.href, props.as]
Diff for link-e2f1e0e..da.module.js
@@ -207,12 +207,16 @@
         var pathname = (router && router.pathname) || "/";
 
         var { href, as } = _react.default.useMemo(() => {
-          var resolvedHref = (0, _router.resolveHref)(pathname, props.href);
+          var [resolvedHref, resolvedAs] = (0, _router.resolveHref)(
+            pathname,
+            props.href,
+            true
+          );
           return {
             href: resolvedHref,
             as: props.as
               ? (0, _router.resolveHref)(pathname, props.as)
-              : resolvedHref
+              : resolvedAs || resolvedHref
           };
         }, [pathname, props.href, props.as]);
Diff for 677f882d2ed8..7000fca82.js
@@ -683,6 +683,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
       exports.addBasePath = addBasePath;
       exports.delBasePath = delBasePath;
       exports.isLocalURL = isLocalURL;
+      exports.interpolateAs = interpolateAs;
       exports.resolveHref = resolveHref;
       exports.markLoadingError = markLoadingError;
       exports["default"] = void 0;
@@ -709,6 +710,10 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
 
       var _routeRegex = __webpack_require__("YTqd");
 
+      var _escapePathDelimiters = _interopRequireDefault(
+        __webpack_require__("fcRV")
+      );
+
       function _interopRequireDefault(obj) {
         return obj && obj.__esModule
           ? obj
@@ -761,12 +766,61 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
           return false;
         }
       }
+
+      function interpolateAs(route, asPathname, query) {
+        var interpolatedRoute = "";
+        var dynamicRegex = (0, _routeRegex.getRouteRegex)(route);
+        var dynamicGroups = dynamicRegex.groups;
+        var dynamicMatches = // Try to match the dynamic route against the asPath
+          (asPathname !== route
+            ? (0, _routeMatcher.getRouteMatcher)(dynamicRegex)(asPathname)
+            : "") || // Fall back to reading the values from the href
+          // TODO: should this take priority; also need to change in the router.
+          query;
+        interpolatedRoute = route;
+
+        if (
+          !Object.keys(dynamicGroups).every(function(param) {
+            var value = dynamicMatches[param] || "";
+            var _dynamicGroups$param = dynamicGroups[param],
+              repeat = _dynamicGroups$param.repeat,
+              optional = _dynamicGroups$param.optional; // support single-level catch-all
+            // TODO: more robust handling for user-error (passing `/`)
+
+            var replaced = "[".concat(repeat ? "..." : "").concat(param, "]");
+
+            if (optional) {
+              replaced = ""
+                .concat(!value ? "/" : "", "[")
+                .concat(replaced, "]");
+            }
+
+            if (repeat && !Array.isArray(value)) value = [value];
+            return (
+              (optional || param in dynamicMatches) && // Interpolate group into data URL if present
+              (interpolatedRoute =
+                interpolatedRoute.replace(
+                  replaced,
+                  repeat
+                    ? value.map(_escapePathDelimiters["default"]).join("/")
+                    : (0, _escapePathDelimiters["default"])(value)
+                ) || "/")
+            );
+          })
+        ) {
+          interpolatedRoute = ""; // did not satisfy all requirements
+          // n.b. We ignore this error because we handle warning for this case in
+          // development in the `<Link>` component directly.
+        }
+
+        return interpolatedRoute;
+      }
       /**
        * Resolves a given hyperlink with a certain router state (basePath not included).
        * Preserves absolute urls.
        */
 
-      function resolveHref(currentPath, href) {
+      function resolveHref(currentPath, href, resolveAs) {
         // we use a dummy base url for relative urls
         var base = new URL(currentPath, "http://n");
         var urlAsString =
@@ -779,13 +833,31 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
           finalUrl.pathname = (0,
           _normalizeTrailingSlash.normalizePathTrailingSlash)(
             finalUrl.pathname
-          ); // if the origin didn't change, it means we received a relative href
+          );
+          var interpolatedAs = "";
 
-          return finalUrl.origin === base.origin
-            ? finalUrl.href.slice(finalUrl.origin.length)
-            : finalUrl.href;
+          if (
+            (0, _isDynamic.isDynamicRoute)(finalUrl.pathname) &&
+            finalUrl.searchParams &&
+            resolveAs
+          ) {
+            var query = (0, _querystring.searchParamsToUrlQuery)(
+              finalUrl.searchParams
+            );
+            interpolatedAs = interpolateAs(
+              finalUrl.pathname,
+              finalUrl.pathname,
+              query
+            );
+          } // if the origin didn't change, it means we received a relative href
+
+          var resolvedHref =
+            finalUrl.origin === base.origin
+              ? finalUrl.href.slice(finalUrl.origin.length)
+              : finalUrl.href;
+          return resolveAs ? [resolvedHref, interpolatedAs] : resolvedHref;
         } catch (_) {
-          return urlAsString;
+          return resolveAs ? [urlAsString] : urlAsString;
         }
       }
 
@@ -1124,15 +1196,20 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                       while (1) {
                         switch ((_context.prev = _context.next)) {
                           case 0:
+                            console.log({
+                              url: url,
+                              as: as
+                            });
+
                             if (isLocalURL(url)) {
-                              _context.next = 3;
+                              _context.next = 4;
                               break;
                             }
 
                             window.location.href = url;
                             return _context.abrupt("return", false);
 
-                          case 3:
+                          case 4:
                             if (!options._h) {
                               this.isSsr = false;
                             } // marking route changes as a navigation start entry
@@ -1155,7 +1232,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                             if (
                               !(!options._h && this.onlyAHashChange(cleanedAs))
                             ) {
-                              _context.next = 16;
+                              _context.next = 17;
                               break;
                             }
 
@@ -1168,16 +1245,16 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                             Router.events.emit("hashChangeComplete", as);
                             return _context.abrupt("return", true);
 
-                          case 16:
-                            _context.next = 18;
+                          case 17:
+                            _context.next = 19;
                             return this.pageLoader.getPageList();
 
-                          case 18:
+                          case 19:
                             pages = _context.sent;
-                            _context.next = 21;
+                            _context.next = 22;
                             return this.pageLoader.promisedBuildManifest;
 
-                          case 21:
+                          case 22:
                             _yield$this$pageLoade = _context.sent;
                             rewrites = _yield$this$pageLoade.__rewrites;
                             parsed = (0, _parseRelativeUrl.parseRelativeUrl)(
@@ -1233,7 +1310,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                             resolvedAs = delBasePath(resolvedAs);
 
                             if (!(0, _isDynamic.isDynamicRoute)(route)) {
-                              _context.next = 47;
+                              _context.next = 48;
                               break;
                             }
 
@@ -1247,7 +1324,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                             )(asPathname);
 
                             if (routeMatch) {
-                              _context.next = 46;
+                              _context.next = 47;
                               break;
                             }
 
@@ -1258,7 +1335,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                             });
 
                             if (!(missingParams.length > 0)) {
-                              _context.next = 44;
+                              _context.next = 45;
                               break;
                             }
 
@@ -1275,18 +1352,22 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                                 "Read more: https://err.sh/vercel/next.js/incompatible-href-as"
                             );
 
-                          case 44:
-                            _context.next = 47;
+                          case 45:
+                            _context.next = 48;
                             break;
 
-                          case 46:
-                            // Merge params into `query`, overwriting any specified in search
-                            Object.assign(query, routeMatch);
-
                           case 47:
+                            if (route === asPathname) {
+                              as = interpolateAs(route, asPathname, query);
+                            } else {
+                              // Merge params into `query`, overwriting any specified in search
+                              Object.assign(query, routeMatch);
+                            }
+
+                          case 48:
                             Router.events.emit("routeChangeStart", as);
-                            _context.prev = 48;
-                            _context.next = 51;
+                            _context.prev = 49;
+                            _context.next = 52;
                             return this.getRouteInfo(
                               route,
                               pathname,
@@ -1295,7 +1376,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                               shallow
                             );
 
-                          case 51:
+                          case 52:
                             routeInfo = _context.sent;
                             error = routeInfo.error;
                             Router.events.emit("beforeHistoryChange", as);
@@ -1304,7 +1385,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                             if (false) {
                             }
 
-                            _context.next = 58;
+                            _context.next = 59;
                             return this.set(
                               route,
                               pathname,
@@ -1316,9 +1397,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                               else throw e;
                             });
 
-                          case 58:
+                          case 59:
                             if (!error) {
-                              _context.next = 61;
+                              _context.next = 62;
                               break;
                             }
 
@@ -1329,28 +1410,28 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                             );
                             throw error;
 
-                          case 61:
+                          case 62:
                             if (false) {
                             }
 
                             Router.events.emit("routeChangeComplete", as);
                             return _context.abrupt("return", true);
 
-                          case 66:
-                            _context.prev = 66;
-                            _context.t0 = _context["catch"](48);
+                          case 67:
+                            _context.prev = 67;
+                            _context.t0 = _context["catch"](49);
 
                             if (!_context.t0.cancelled) {
-                              _context.next = 70;
+                              _context.next = 71;
                               break;
                             }
 
                             return _context.abrupt("return", false);
 
-                          case 70:
+                          case 71:
                             throw _context.t0;
 
-                          case 71:
+                          case 72:
                           case "end":
                             return _context.stop();
                         }
@@ -1358,7 +1439,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                     },
                     _callee,
                     this,
-                    [[48, 66]]
+                    [[49, 67]]
                   );
                 })
               );
@@ -2060,6 +2141,21 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
       /***/
     },
 
+    /***/ fcRV: /***/ function(module, exports, __webpack_require__) {
+      "use strict";
+
+      exports.__esModule = true;
+      exports["default"] = escapePathDelimiters; // escape delimiters used by path-to-regexp
+
+      function escapePathDelimiters(segment) {
+        return segment.replace(/[/#?]/g, function(_char) {
+          return encodeURIComponent(_char);
+        });
+      }
+
+      /***/
+    },
+
     /***/ "g/15": /***/ function(module, exports, __webpack_require__) {
       "use strict";
Diff for 677f882d2ed8..87.module.js
@@ -542,6 +542,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
       exports.addBasePath = addBasePath;
       exports.delBasePath = delBasePath;
       exports.isLocalURL = isLocalURL;
+      exports.interpolateAs = interpolateAs;
       exports.resolveHref = resolveHref;
       exports.markLoadingError = markLoadingError;
       exports.default = void 0;
@@ -568,6 +569,10 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
 
       var _routeRegex = __webpack_require__("YTqd");
 
+      var _escapePathDelimiters = _interopRequireDefault(
+        __webpack_require__("fcRV")
+      );
+
       function _interopRequireDefault(obj) {
         return obj && obj.__esModule
           ? obj
@@ -620,12 +625,59 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
           return false;
         }
       }
+
+      function interpolateAs(route, asPathname, query) {
+        var interpolatedRoute = "";
+        var dynamicRegex = (0, _routeRegex.getRouteRegex)(route);
+        var dynamicGroups = dynamicRegex.groups;
+        var dynamicMatches = // Try to match the dynamic route against the asPath
+          (asPathname !== route
+            ? (0, _routeMatcher.getRouteMatcher)(dynamicRegex)(asPathname)
+            : "") || // Fall back to reading the values from the href
+          // TODO: should this take priority; also need to change in the router.
+          query;
+        interpolatedRoute = route;
+
+        if (
+          !Object.keys(dynamicGroups).every(param => {
+            var value = dynamicMatches[param] || "";
+            var { repeat, optional } = dynamicGroups[param]; // support single-level catch-all
+            // TODO: more robust handling for user-error (passing `/`)
+
+            var replaced = "[".concat(repeat ? "..." : "").concat(param, "]");
+
+            if (optional) {
+              replaced = ""
+                .concat(!value ? "/" : "", "[")
+                .concat(replaced, "]");
+            }
+
+            if (repeat && !Array.isArray(value)) value = [value];
+            return (
+              (optional || param in dynamicMatches) && // Interpolate group into data URL if present
+              (interpolatedRoute =
+                interpolatedRoute.replace(
+                  replaced,
+                  repeat
+                    ? value.map(_escapePathDelimiters.default).join("/")
+                    : (0, _escapePathDelimiters.default)(value)
+                ) || "/")
+            );
+          })
+        ) {
+          interpolatedRoute = ""; // did not satisfy all requirements
+          // n.b. We ignore this error because we handle warning for this case in
+          // development in the `<Link>` component directly.
+        }
+
+        return interpolatedRoute;
+      }
       /**
        * Resolves a given hyperlink with a certain router state (basePath not included).
        * Preserves absolute urls.
        */
 
-      function resolveHref(currentPath, href) {
+      function resolveHref(currentPath, href, resolveAs) {
         // we use a dummy base url for relative urls
         var base = new URL(currentPath, "http://n");
         var urlAsString =
@@ -638,13 +690,31 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
           finalUrl.pathname = (0,
           _normalizeTrailingSlash.normalizePathTrailingSlash)(
             finalUrl.pathname
-          ); // if the origin didn't change, it means we received a relative href
+          );
+          var interpolatedAs = "";
+
+          if (
+            (0, _isDynamic.isDynamicRoute)(finalUrl.pathname) &&
+            finalUrl.searchParams &&
+            resolveAs
+          ) {
+            var query = (0, _querystring.searchParamsToUrlQuery)(
+              finalUrl.searchParams
+            );
+            interpolatedAs = interpolateAs(
+              finalUrl.pathname,
+              finalUrl.pathname,
+              query
+            );
+          } // if the origin didn't change, it means we received a relative href
 
-          return finalUrl.origin === base.origin
-            ? finalUrl.href.slice(finalUrl.origin.length)
-            : finalUrl.href;
+          var resolvedHref =
+            finalUrl.origin === base.origin
+              ? finalUrl.href.slice(finalUrl.origin.length)
+              : finalUrl.href;
+          return resolveAs ? [resolvedHref, interpolatedAs] : resolvedHref;
         } catch (_) {
-          return urlAsString;
+          return resolveAs ? [urlAsString] : urlAsString;
         }
       }
 
@@ -918,6 +988,11 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
         }
 
         async change(method, url, as, options) {
+          console.log({
+            url,
+            as
+          });
+
           if (!isLocalURL(url)) {
             window.location.href = url;
             return false;
@@ -1025,6 +1100,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                     "Read more: https://err.sh/vercel/next.js/incompatible-href-as"
                 );
               }
+            } else if (route === asPathname) {
+              as = interpolateAs(route, asPathname, query);
             } else {
               // Merge params into `query`, overwriting any specified in search
               Object.assign(query, routeMatch);
@@ -1443,6 +1520,19 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
       /***/
     },
 
+    /***/ fcRV: /***/ function(module, exports, __webpack_require__) {
+      "use strict";
+
+      exports.__esModule = true;
+      exports.default = escapePathDelimiters; // escape delimiters used by path-to-regexp
+
+      function escapePathDelimiters(segment) {
+        return segment.replace(/[/#?]/g, char => encodeURIComponent(char));
+      }
+
+      /***/
+    },
+
     /***/ "g/15": /***/ function(module, exports, __webpack_require__) {
       "use strict";
Diff for main-4d90bb4..32.module.js
@@ -895,19 +895,6 @@
       /***/
     },
 
-    /***/ fcRV: /***/ function(module, exports, __webpack_require__) {
-      "use strict";
-
-      exports.__esModule = true;
-      exports.default = escapePathDelimiters; // escape delimiters used by path-to-regexp
-
-      function escapePathDelimiters(segment) {
-        return segment.replace(/[/#?]/g, char => encodeURIComponent(char));
-      }
-
-      /***/
-    },
-
     /***/ pVnL: /***/ function(module, exports) {
       function _extends() {
         module.exports = _extends =
@@ -1214,10 +1201,6 @@
 
       var _router = __webpack_require__("elyg");
 
-      var _escapePathDelimiters = _interopRequireDefault(
-        __webpack_require__("fcRV")
-      );
-
       var _getAssetPathFromRoute = _interopRequireDefault(
         __webpack_require__("Lab5")
       );
@@ -1228,10 +1211,6 @@
 
       var _querystring = __webpack_require__("3WeD");
 
-      var _routeMatcher = __webpack_require__("gguc");
-
-      var _routeRegex = __webpack_require__("YTqd");
-
       var looseToArray = input => [].slice.call(input);
 
       exports.looseToArray = looseToArray;
@@ -1407,53 +1386,10 @@
             );
           };
 
-          var isDynamic = (0, _isDynamic.isDynamicRoute)(route),
-            interpolatedRoute;
-
-          if (isDynamic) {
-            var dynamicRegex = (0, _routeRegex.getRouteRegex)(route);
-            var dynamicGroups = dynamicRegex.groups;
-            var dynamicMatches = // Try to match the dynamic route against the asPath
-              (0, _routeMatcher.getRouteMatcher)(dynamicRegex)(asPathname) || // Fall back to reading the values from the href
-              // TODO: should this take priority; also need to change in the router.
-              query;
-            interpolatedRoute = route;
-
-            if (
-              !Object.keys(dynamicGroups).every(param => {
-                var value = dynamicMatches[param] || "";
-                var { repeat, optional } = dynamicGroups[param]; // support single-level catch-all
-                // TODO: more robust handling for user-error (passing `/`)
-
-                var replaced = "["
-                  .concat(repeat ? "..." : "")
-                  .concat(param, "]");
-
-                if (optional) {
-                  replaced = ""
-                    .concat(!value ? "/" : "", "[")
-                    .concat(replaced, "]");
-                }
-
-                if (repeat && !Array.isArray(value)) value = [value];
-                return (
-                  (optional || param in dynamicMatches) && // Interpolate group into data URL if present
-                  (interpolatedRoute =
-                    interpolatedRoute.replace(
-                      replaced,
-                      repeat
-                        ? value.map(_escapePathDelimiters.default).join("/")
-                        : (0, _escapePathDelimiters.default)(value)
-                    ) || "/")
-                );
-              })
-            ) {
-              interpolatedRoute = ""; // did not satisfy all requirements
-              // n.b. We ignore this error because we handle warning for this case in
-              // development in the `<Link>` component directly.
-            }
-          }
-
+          var isDynamic = (0, _isDynamic.isDynamicRoute)(route);
+          var interpolatedRoute = isDynamic
+            ? (0, _router.interpolateAs)(hrefPathname, asPathname, query)
+            : "";
           return isDynamic
             ? interpolatedRoute && getHrefForSlug(interpolatedRoute)
             : getHrefForSlug(route);
Diff for main-b8d3644..f586aeb2b.js
@@ -1225,21 +1225,6 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
       /***/
     },
 
-    /***/ fcRV: /***/ function(module, exports, __webpack_require__) {
-      "use strict";
-
-      exports.__esModule = true;
-      exports["default"] = escapePathDelimiters; // escape delimiters used by path-to-regexp
-
-      function escapePathDelimiters(segment) {
-        return segment.replace(/[/#?]/g, function(_char) {
-          return encodeURIComponent(_char);
-        });
-      }
-
-      /***/
-    },
-
     /***/ pVnL: /***/ function(module, exports) {
       function _extends() {
         module.exports = _extends =
@@ -1550,10 +1535,6 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
 
       var _router = __webpack_require__("elyg");
 
-      var _escapePathDelimiters = _interopRequireDefault(
-        __webpack_require__("fcRV")
-      );
-
       var _getAssetPathFromRoute = _interopRequireDefault(
         __webpack_require__("Lab5")
       );
@@ -1564,10 +1545,6 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
 
       var _querystring = __webpack_require__("3WeD");
 
-      var _routeMatcher = __webpack_require__("gguc");
-
-      var _routeRegex = __webpack_require__("YTqd");
-
       var looseToArray = function looseToArray(input) {
         return [].slice.call(input);
       };
@@ -1777,59 +1754,10 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
                 );
               };
 
-              var isDynamic = (0, _isDynamic.isDynamicRoute)(route),
-                interpolatedRoute;
-
-              if (isDynamic) {
-                var dynamicRegex = (0, _routeRegex.getRouteRegex)(route);
-                var dynamicGroups = dynamicRegex.groups;
-                var dynamicMatches = // Try to match the dynamic route against the asPath
-                  (0, _routeMatcher.getRouteMatcher)(dynamicRegex)(
-                    asPathname
-                  ) || // Fall back to reading the values from the href
-                  // TODO: should this take priority; also need to change in the router.
-                  query;
-                interpolatedRoute = route;
-
-                if (
-                  !Object.keys(dynamicGroups).every(function(param) {
-                    var value = dynamicMatches[param] || "";
-                    var _dynamicGroups$param = dynamicGroups[param],
-                      repeat = _dynamicGroups$param.repeat,
-                      optional = _dynamicGroups$param.optional; // support single-level catch-all
-                    // TODO: more robust handling for user-error (passing `/`)
-
-                    var replaced = "["
-                      .concat(repeat ? "..." : "")
-                      .concat(param, "]");
-
-                    if (optional) {
-                      replaced = ""
-                        .concat(!value ? "/" : "", "[")
-                        .concat(replaced, "]");
-                    }
-
-                    if (repeat && !Array.isArray(value)) value = [value];
-                    return (
-                      (optional || param in dynamicMatches) && // Interpolate group into data URL if present
-                      (interpolatedRoute =
-                        interpolatedRoute.replace(
-                          replaced,
-                          repeat
-                            ? value
-                                .map(_escapePathDelimiters["default"])
-                                .join("/")
-                            : (0, _escapePathDelimiters["default"])(value)
-                        ) || "/")
-                    );
-                  })
-                ) {
-                  interpolatedRoute = ""; // did not satisfy all requirements
-                  // n.b. We ignore this error because we handle warning for this case in
-                  // development in the `<Link>` component directly.
-                }
-              }
-
+              var isDynamic = (0, _isDynamic.isDynamicRoute)(route);
+              var interpolatedRoute = isDynamic
+                ? (0, _router.interpolateAs)(hrefPathname, asPathname, query)
+                : "";
               return isDynamic
                 ? interpolatedRoute && getHrefForSlug(interpolatedRoute)
                 : getHrefForSlug(route);
Diff for index.html
@@ -7,7 +7,7 @@
     <noscript data-n-css="true"></noscript>
     <link
       rel="preload"
-      href="/_next/static/chunks/main-4d90bb4e4e7bbc2b2532.module.js"
+      href="/_next/static/chunks/main-5823e90a936c4e01a4bf.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -25,7 +25,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.f48d291f6d1033f6c087.module.js"
+      href="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.b974d4da0fb0482f3ded.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -82,13 +82,13 @@
       src="/_next/static/chunks/polyfills-f73ba3fc145972ef83e9.js"
     ></script>
     <script
-      src="/_next/static/chunks/main-b8d3644a020f586aeb2b.js"
+      src="/_next/static/chunks/main-aeb7939c646600c3a9b3.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/main-4d90bb4e4e7bbc2b2532.module.js"
+      src="/_next/static/chunks/main-5823e90a936c4e01a4bf.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
@@ -118,13 +118,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.abb28f9c6d97000fca82.js"
+      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.dfa789ba6e137b9c7846.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.f48d291f6d1033f6c087.module.js"
+      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.b974d4da0fb0482f3ded.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
Diff for link.html
@@ -7,7 +7,7 @@
     <noscript data-n-css="true"></noscript>
     <link
       rel="preload"
-      href="/_next/static/chunks/main-4d90bb4e4e7bbc2b2532.module.js"
+      href="/_next/static/chunks/main-5823e90a936c4e01a4bf.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -25,7 +25,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.f48d291f6d1033f6c087.module.js"
+      href="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.b974d4da0fb0482f3ded.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -37,7 +37,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/pages/link-e2f1e0e7ed02569239da.module.js"
+      href="/_next/static/chunks/pages/link-cb038f0ac2e648ce4861.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -87,13 +87,13 @@
       src="/_next/static/chunks/polyfills-f73ba3fc145972ef83e9.js"
     ></script>
     <script
-      src="/_next/static/chunks/main-b8d3644a020f586aeb2b.js"
+      src="/_next/static/chunks/main-aeb7939c646600c3a9b3.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/main-4d90bb4e4e7bbc2b2532.module.js"
+      src="/_next/static/chunks/main-5823e90a936c4e01a4bf.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
@@ -123,13 +123,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.abb28f9c6d97000fca82.js"
+      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.dfa789ba6e137b9c7846.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.f48d291f6d1033f6c087.module.js"
+      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.b974d4da0fb0482f3ded.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
@@ -147,13 +147,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/pages/link-46fd48c0b73b2f2d75a4.js"
+      src="/_next/static/chunks/pages/link-32658e75d53af2daa2e0.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/pages/link-e2f1e0e7ed02569239da.module.js"
+      src="/_next/static/chunks/pages/link-cb038f0ac2e648ce4861.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
Diff for withRouter.html
@@ -7,7 +7,7 @@
     <noscript data-n-css="true"></noscript>
     <link
       rel="preload"
-      href="/_next/static/chunks/main-4d90bb4e4e7bbc2b2532.module.js"
+      href="/_next/static/chunks/main-5823e90a936c4e01a4bf.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -25,7 +25,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.f48d291f6d1033f6c087.module.js"
+      href="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.b974d4da0fb0482f3ded.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -82,13 +82,13 @@
       src="/_next/static/chunks/polyfills-f73ba3fc145972ef83e9.js"
     ></script>
     <script
-      src="/_next/static/chunks/main-b8d3644a020f586aeb2b.js"
+      src="/_next/static/chunks/main-aeb7939c646600c3a9b3.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/main-4d90bb4e4e7bbc2b2532.module.js"
+      src="/_next/static/chunks/main-5823e90a936c4e01a4bf.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
@@ -118,13 +118,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.abb28f9c6d97000fca82.js"
+      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.dfa789ba6e137b9c7846.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.f48d291f6d1033f6c087.module.js"
+      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.b974d4da0fb0482f3ded.module.js"
       async=""
       crossorigin="anonymous"
       type="module"

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
buildDuration 13.3s 13.2s -32ms
nodeModulesSize 55.9 MB 55.9 MB ⚠️ +2.17 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
677f882d2ed8..9ff9.js gzip 10.3 kB N/A N/A
framework.HASH.js gzip 39 kB 39 kB
main-e1c4209..e2c9.js gzip 7.32 kB N/A N/A
webpack-e067..f178.js gzip 751 B 751 B
677f882d2ed8..41d1.js gzip N/A 10.5 kB N/A
main-f8f2cfe..033f.js gzip N/A 7.1 kB N/A
Overall change 57.3 kB 57.4 kB ⚠️ +46 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
677f882d2ed8..dule.js gzip 6.13 kB N/A N/A
framework.HA..dule.js gzip 39 kB 39 kB
main-9077898..dule.js gzip 6.38 kB N/A N/A
webpack-07c5..dule.js gzip 751 B 751 B
677f882d2ed8..dule.js gzip N/A 6.41 kB N/A
main-a6f8e84..dule.js gzip N/A 6.16 kB N/A
Overall change 52.2 kB 52.3 kB ⚠️ +58 B
Legacy Client Bundles (polyfills)
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
polyfills-4b..e242.js gzip 31 kB 31 kB
Overall change 31 kB 31 kB
Client Pages Overall increase ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
_app-9a0b9e1..b37e.js gzip 1.28 kB 1.28 kB
_error-ed1b0..8fbd.js gzip 3.44 kB 3.44 kB
hooks-89731c..c609.js gzip 887 B 887 B
index-17468f..5d83.js gzip 227 B 227 B
link-ae98065..267e.js gzip 1.29 kB N/A N/A
routerDirect..924c.js gzip 284 B 284 B
withRouter-7..c13d.js gzip 284 B 284 B
link-d2344ce..8b36.js gzip N/A 1.3 kB N/A
Overall change 7.69 kB 7.71 kB ⚠️ +16 B
Client Pages Modern Overall increase ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
_app-75d3a82..dule.js gzip 625 B 625 B
_error-4469a..dule.js gzip 2.29 kB 2.29 kB
hooks-cbf13f..dule.js gzip 387 B 387 B
index-b9a643..dule.js gzip 226 B 226 B
link-cb244c4..dule.js gzip 1.26 kB N/A N/A
routerDirect..dule.js gzip 284 B 284 B
withRouter-f..dule.js gzip 282 B 282 B
link-f8c0daf..dule.js gzip N/A 1.26 kB N/A
Overall change 5.35 kB 5.36 kB ⚠️ +5 B
Client Build Manifests Overall decrease ✓
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
_buildManifest.js gzip 323 B 322 B -1 B
_buildManife..dule.js gzip 329 B 329 B
Overall change 652 B 651 B -1 B
Serverless bundles Overall increase ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
_error.js 1.03 MB 1.03 MB
404.html 4.22 kB 4.22 kB
hooks.html 3.86 kB 3.86 kB
index.js 1.03 MB 1.03 MB
link.js 1.07 MB 1.08 MB ⚠️ +2.54 kB
routerDirect.js 1.07 MB 1.07 MB ⚠️ +2.51 kB
withRouter.js 1.07 MB 1.07 MB ⚠️ +2.51 kB
Overall change 5.28 MB 5.29 MB ⚠️ +7.56 kB
Commit: 04f8dbd

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.

one debug comment

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.

Great work!

@ijjk
Copy link
Member Author

ijjk commented Sep 2, 2020

Stats from current PR

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
buildDuration 11.6s 11.5s -139ms
nodeModulesSize 55.9 MB 55.9 MB ⚠️ +2.05 kB
Page Load Tests Overall decrease ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
/ failed reqs 0 0
/ total time (seconds) 2.141 2.16 ⚠️ +0.02
/ avg req/sec 1167.56 1157.66 ⚠️ -9.9
/error-in-render failed reqs 0 0
/error-in-render total time (seconds) 1.186 1.266 ⚠️ +0.08
/error-in-render avg req/sec 2107.27 1975.07 ⚠️ -132.2
Client Bundles (main, webpack, commons) Overall increase ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
677f882d2ed8..9ff9.js gzip 10.3 kB 10.5 kB ⚠️ +256 B
framework.HASH.js gzip 39 kB 39 kB
main-e1c4209..e2c9.js gzip 7.32 kB 7.1 kB -221 B
webpack-e067..f178.js gzip 751 B 751 B
Overall change 57.3 kB 57.3 kB ⚠️ +35 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
677f882d2ed8..dule.js gzip 6.13 kB 6.39 kB ⚠️ +267 B
framework.HA..dule.js gzip 39 kB 39 kB
main-9077898..dule.js gzip 6.38 kB 6.16 kB -220 B
webpack-07c5..dule.js gzip 751 B 751 B
Overall change 52.2 kB 52.3 kB ⚠️ +47 B
Legacy Client Bundles (polyfills)
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
polyfills-4b..e242.js gzip 31 kB 31 kB
Overall change 31 kB 31 kB
Client Pages Overall increase ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
_app-9a0b9e1..b37e.js gzip 1.28 kB 1.28 kB
_error-ed1b0..8fbd.js gzip 3.44 kB 3.44 kB
hooks-89731c..c609.js gzip 887 B 887 B
index-17468f..5d83.js gzip 227 B 227 B
link-ae98065..267e.js gzip 1.29 kB 1.3 kB ⚠️ +16 B
routerDirect..924c.js gzip 284 B 284 B
withRouter-7..c13d.js gzip 284 B 284 B
Overall change 7.69 kB 7.71 kB ⚠️ +16 B
Client Pages Modern Overall increase ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
_app-75d3a82..dule.js gzip 625 B 625 B
_error-4469a..dule.js gzip 2.29 kB 2.29 kB
hooks-cbf13f..dule.js gzip 387 B 387 B
index-b9a643..dule.js gzip 226 B 226 B
link-cb244c4..dule.js gzip 1.26 kB 1.26 kB ⚠️ +5 B
routerDirect..dule.js gzip 284 B 284 B
withRouter-f..dule.js gzip 282 B 282 B
Overall change 5.35 kB 5.36 kB ⚠️ +5 B
Client Build Manifests Overall decrease ✓
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
_buildManifest.js gzip 323 B 322 B -1 B
_buildManife..dule.js gzip 329 B 329 B
Overall change 652 B 651 B -1 B
Rendered Page Sizes Overall increase ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
index.html gzip 971 B 972 B ⚠️ +1 B
link.html gzip 976 B 977 B ⚠️ +1 B
withRouter.html gzip 963 B 964 B ⚠️ +1 B
Overall change 2.91 kB 2.91 kB ⚠️ +3 B

Diffs

Diff for _buildManifest.js
@@ -7,7 +7,7 @@ self.__BUILD_MANIFEST = {
   "/hooks": [
     "static\u002Fchunks\u002Fpages\u002Fhooks-8001dc76075832ee8949.js"
   ],
-  "/link": ["static\u002Fchunks\u002Fpages\u002Flink-46fd48c0b73b2f2d75a4.js"],
+  "/link": ["static\u002Fchunks\u002Fpages\u002Flink-32658e75d53af2daa2e0.js"],
   "/routerDirect": [
     "static\u002Fchunks\u002Fpages\u002FrouterDirect-2e9bfd441bd88cd3382e.js"
   ],
Diff for _buildManifest.module.js
@@ -10,7 +10,7 @@ self.__BUILD_MANIFEST = {
     "static\u002Fchunks\u002Fpages\u002Fhooks-56fa58a6f0993d7d36d7.module.js"
   ],
   "/link": [
-    "static\u002Fchunks\u002Fpages\u002Flink-e2f1e0e7ed02569239da.module.js"
+    "static\u002Fchunks\u002Fpages\u002Flink-cb038f0ac2e648ce4861.module.js"
   ],
   "/routerDirect": [
     "static\u002Fchunks\u002Fpages\u002FrouterDirect-368af3dfef3c9cd99dc3.module.js"
Diff for link-46fd48c..b2f2d75a4.js
@@ -216,12 +216,16 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
 
         var _react$default$useMem = _react["default"].useMemo(
             function() {
-              var resolvedHref = (0, _router.resolveHref)(pathname, props.href);
+              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)
-                  : resolvedHref
+                  : resolvedAs || resolvedHref
               };
             },
             [pathname, props.href, props.as]
Diff for link-e2f1e0e..da.module.js
@@ -207,12 +207,16 @@
         var pathname = (router && router.pathname) || "/";
 
         var { href, as } = _react.default.useMemo(() => {
-          var resolvedHref = (0, _router.resolveHref)(pathname, props.href);
+          var [resolvedHref, resolvedAs] = (0, _router.resolveHref)(
+            pathname,
+            props.href,
+            true
+          );
           return {
             href: resolvedHref,
             as: props.as
               ? (0, _router.resolveHref)(pathname, props.as)
-              : resolvedHref
+              : resolvedAs || resolvedHref
           };
         }, [pathname, props.href, props.as]);
Diff for 677f882d2ed8..7000fca82.js
@@ -683,6 +683,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
       exports.addBasePath = addBasePath;
       exports.delBasePath = delBasePath;
       exports.isLocalURL = isLocalURL;
+      exports.interpolateAs = interpolateAs;
       exports.resolveHref = resolveHref;
       exports.markLoadingError = markLoadingError;
       exports["default"] = void 0;
@@ -709,6 +710,10 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
 
       var _routeRegex = __webpack_require__("YTqd");
 
+      var _escapePathDelimiters = _interopRequireDefault(
+        __webpack_require__("fcRV")
+      );
+
       function _interopRequireDefault(obj) {
         return obj && obj.__esModule
           ? obj
@@ -761,12 +766,61 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
           return false;
         }
       }
+
+      function interpolateAs(route, asPathname, query) {
+        var interpolatedRoute = "";
+        var dynamicRegex = (0, _routeRegex.getRouteRegex)(route);
+        var dynamicGroups = dynamicRegex.groups;
+        var dynamicMatches = // Try to match the dynamic route against the asPath
+          (asPathname !== route
+            ? (0, _routeMatcher.getRouteMatcher)(dynamicRegex)(asPathname)
+            : "") || // Fall back to reading the values from the href
+          // TODO: should this take priority; also need to change in the router.
+          query;
+        interpolatedRoute = route;
+
+        if (
+          !Object.keys(dynamicGroups).every(function(param) {
+            var value = dynamicMatches[param] || "";
+            var _dynamicGroups$param = dynamicGroups[param],
+              repeat = _dynamicGroups$param.repeat,
+              optional = _dynamicGroups$param.optional; // support single-level catch-all
+            // TODO: more robust handling for user-error (passing `/`)
+
+            var replaced = "[".concat(repeat ? "..." : "").concat(param, "]");
+
+            if (optional) {
+              replaced = ""
+                .concat(!value ? "/" : "", "[")
+                .concat(replaced, "]");
+            }
+
+            if (repeat && !Array.isArray(value)) value = [value];
+            return (
+              (optional || param in dynamicMatches) && // Interpolate group into data URL if present
+              (interpolatedRoute =
+                interpolatedRoute.replace(
+                  replaced,
+                  repeat
+                    ? value.map(_escapePathDelimiters["default"]).join("/")
+                    : (0, _escapePathDelimiters["default"])(value)
+                ) || "/")
+            );
+          })
+        ) {
+          interpolatedRoute = ""; // did not satisfy all requirements
+          // n.b. We ignore this error because we handle warning for this case in
+          // development in the `<Link>` component directly.
+        }
+
+        return interpolatedRoute;
+      }
       /**
        * Resolves a given hyperlink with a certain router state (basePath not included).
        * Preserves absolute urls.
        */
 
-      function resolveHref(currentPath, href) {
+      function resolveHref(currentPath, href, resolveAs) {
         // we use a dummy base url for relative urls
         var base = new URL(currentPath, "http://n");
         var urlAsString =
@@ -779,13 +833,31 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
           finalUrl.pathname = (0,
           _normalizeTrailingSlash.normalizePathTrailingSlash)(
             finalUrl.pathname
-          ); // if the origin didn't change, it means we received a relative href
+          );
+          var interpolatedAs = "";
+
+          if (
+            (0, _isDynamic.isDynamicRoute)(finalUrl.pathname) &&
+            finalUrl.searchParams &&
+            resolveAs
+          ) {
+            var query = (0, _querystring.searchParamsToUrlQuery)(
+              finalUrl.searchParams
+            );
+            interpolatedAs = interpolateAs(
+              finalUrl.pathname,
+              finalUrl.pathname,
+              query
+            );
+          } // if the origin didn't change, it means we received a relative href
 
-          return finalUrl.origin === base.origin
-            ? finalUrl.href.slice(finalUrl.origin.length)
-            : finalUrl.href;
+          var resolvedHref =
+            finalUrl.origin === base.origin
+              ? finalUrl.href.slice(finalUrl.origin.length)
+              : finalUrl.href;
+          return resolveAs ? [resolvedHref, interpolatedAs] : resolvedHref;
         } catch (_) {
-          return urlAsString;
+          return resolveAs ? [urlAsString] : urlAsString;
         }
       }
 
@@ -1280,8 +1352,12 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                             break;
 
                           case 46:
-                            // Merge params into `query`, overwriting any specified in search
-                            Object.assign(query, routeMatch);
+                            if (route === asPathname) {
+                              as = interpolateAs(route, asPathname, query);
+                            } else {
+                              // Merge params into `query`, overwriting any specified in search
+                              Object.assign(query, routeMatch);
+                            }
 
                           case 47:
                             Router.events.emit("routeChangeStart", as);
@@ -2060,6 +2136,21 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
       /***/
     },
 
+    /***/ fcRV: /***/ function(module, exports, __webpack_require__) {
+      "use strict";
+
+      exports.__esModule = true;
+      exports["default"] = escapePathDelimiters; // escape delimiters used by path-to-regexp
+
+      function escapePathDelimiters(segment) {
+        return segment.replace(/[/#?]/g, function(_char) {
+          return encodeURIComponent(_char);
+        });
+      }
+
+      /***/
+    },
+
     /***/ "g/15": /***/ function(module, exports, __webpack_require__) {
       "use strict";
Diff for 677f882d2ed8..87.module.js
@@ -542,6 +542,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
       exports.addBasePath = addBasePath;
       exports.delBasePath = delBasePath;
       exports.isLocalURL = isLocalURL;
+      exports.interpolateAs = interpolateAs;
       exports.resolveHref = resolveHref;
       exports.markLoadingError = markLoadingError;
       exports.default = void 0;
@@ -568,6 +569,10 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
 
       var _routeRegex = __webpack_require__("YTqd");
 
+      var _escapePathDelimiters = _interopRequireDefault(
+        __webpack_require__("fcRV")
+      );
+
       function _interopRequireDefault(obj) {
         return obj && obj.__esModule
           ? obj
@@ -620,12 +625,59 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
           return false;
         }
       }
+
+      function interpolateAs(route, asPathname, query) {
+        var interpolatedRoute = "";
+        var dynamicRegex = (0, _routeRegex.getRouteRegex)(route);
+        var dynamicGroups = dynamicRegex.groups;
+        var dynamicMatches = // Try to match the dynamic route against the asPath
+          (asPathname !== route
+            ? (0, _routeMatcher.getRouteMatcher)(dynamicRegex)(asPathname)
+            : "") || // Fall back to reading the values from the href
+          // TODO: should this take priority; also need to change in the router.
+          query;
+        interpolatedRoute = route;
+
+        if (
+          !Object.keys(dynamicGroups).every(param => {
+            var value = dynamicMatches[param] || "";
+            var { repeat, optional } = dynamicGroups[param]; // support single-level catch-all
+            // TODO: more robust handling for user-error (passing `/`)
+
+            var replaced = "[".concat(repeat ? "..." : "").concat(param, "]");
+
+            if (optional) {
+              replaced = ""
+                .concat(!value ? "/" : "", "[")
+                .concat(replaced, "]");
+            }
+
+            if (repeat && !Array.isArray(value)) value = [value];
+            return (
+              (optional || param in dynamicMatches) && // Interpolate group into data URL if present
+              (interpolatedRoute =
+                interpolatedRoute.replace(
+                  replaced,
+                  repeat
+                    ? value.map(_escapePathDelimiters.default).join("/")
+                    : (0, _escapePathDelimiters.default)(value)
+                ) || "/")
+            );
+          })
+        ) {
+          interpolatedRoute = ""; // did not satisfy all requirements
+          // n.b. We ignore this error because we handle warning for this case in
+          // development in the `<Link>` component directly.
+        }
+
+        return interpolatedRoute;
+      }
       /**
        * Resolves a given hyperlink with a certain router state (basePath not included).
        * Preserves absolute urls.
        */
 
-      function resolveHref(currentPath, href) {
+      function resolveHref(currentPath, href, resolveAs) {
         // we use a dummy base url for relative urls
         var base = new URL(currentPath, "http://n");
         var urlAsString =
@@ -638,13 +690,31 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
           finalUrl.pathname = (0,
           _normalizeTrailingSlash.normalizePathTrailingSlash)(
             finalUrl.pathname
-          ); // if the origin didn't change, it means we received a relative href
+          );
+          var interpolatedAs = "";
+
+          if (
+            (0, _isDynamic.isDynamicRoute)(finalUrl.pathname) &&
+            finalUrl.searchParams &&
+            resolveAs
+          ) {
+            var query = (0, _querystring.searchParamsToUrlQuery)(
+              finalUrl.searchParams
+            );
+            interpolatedAs = interpolateAs(
+              finalUrl.pathname,
+              finalUrl.pathname,
+              query
+            );
+          } // if the origin didn't change, it means we received a relative href
 
-          return finalUrl.origin === base.origin
-            ? finalUrl.href.slice(finalUrl.origin.length)
-            : finalUrl.href;
+          var resolvedHref =
+            finalUrl.origin === base.origin
+              ? finalUrl.href.slice(finalUrl.origin.length)
+              : finalUrl.href;
+          return resolveAs ? [resolvedHref, interpolatedAs] : resolvedHref;
         } catch (_) {
-          return urlAsString;
+          return resolveAs ? [urlAsString] : urlAsString;
         }
       }
 
@@ -1025,6 +1095,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
                     "Read more: https://err.sh/vercel/next.js/incompatible-href-as"
                 );
               }
+            } else if (route === asPathname) {
+              as = interpolateAs(route, asPathname, query);
             } else {
               // Merge params into `query`, overwriting any specified in search
               Object.assign(query, routeMatch);
@@ -1443,6 +1515,19 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
       /***/
     },
 
+    /***/ fcRV: /***/ function(module, exports, __webpack_require__) {
+      "use strict";
+
+      exports.__esModule = true;
+      exports.default = escapePathDelimiters; // escape delimiters used by path-to-regexp
+
+      function escapePathDelimiters(segment) {
+        return segment.replace(/[/#?]/g, char => encodeURIComponent(char));
+      }
+
+      /***/
+    },
+
     /***/ "g/15": /***/ function(module, exports, __webpack_require__) {
       "use strict";
Diff for main-4d90bb4..32.module.js
@@ -895,19 +895,6 @@
       /***/
     },
 
-    /***/ fcRV: /***/ function(module, exports, __webpack_require__) {
-      "use strict";
-
-      exports.__esModule = true;
-      exports.default = escapePathDelimiters; // escape delimiters used by path-to-regexp
-
-      function escapePathDelimiters(segment) {
-        return segment.replace(/[/#?]/g, char => encodeURIComponent(char));
-      }
-
-      /***/
-    },
-
     /***/ pVnL: /***/ function(module, exports) {
       function _extends() {
         module.exports = _extends =
@@ -1214,10 +1201,6 @@
 
       var _router = __webpack_require__("elyg");
 
-      var _escapePathDelimiters = _interopRequireDefault(
-        __webpack_require__("fcRV")
-      );
-
       var _getAssetPathFromRoute = _interopRequireDefault(
         __webpack_require__("Lab5")
       );
@@ -1228,10 +1211,6 @@
 
       var _querystring = __webpack_require__("3WeD");
 
-      var _routeMatcher = __webpack_require__("gguc");
-
-      var _routeRegex = __webpack_require__("YTqd");
-
       var looseToArray = input => [].slice.call(input);
 
       exports.looseToArray = looseToArray;
@@ -1407,53 +1386,10 @@
             );
           };
 
-          var isDynamic = (0, _isDynamic.isDynamicRoute)(route),
-            interpolatedRoute;
-
-          if (isDynamic) {
-            var dynamicRegex = (0, _routeRegex.getRouteRegex)(route);
-            var dynamicGroups = dynamicRegex.groups;
-            var dynamicMatches = // Try to match the dynamic route against the asPath
-              (0, _routeMatcher.getRouteMatcher)(dynamicRegex)(asPathname) || // Fall back to reading the values from the href
-              // TODO: should this take priority; also need to change in the router.
-              query;
-            interpolatedRoute = route;
-
-            if (
-              !Object.keys(dynamicGroups).every(param => {
-                var value = dynamicMatches[param] || "";
-                var { repeat, optional } = dynamicGroups[param]; // support single-level catch-all
-                // TODO: more robust handling for user-error (passing `/`)
-
-                var replaced = "["
-                  .concat(repeat ? "..." : "")
-                  .concat(param, "]");
-
-                if (optional) {
-                  replaced = ""
-                    .concat(!value ? "/" : "", "[")
-                    .concat(replaced, "]");
-                }
-
-                if (repeat && !Array.isArray(value)) value = [value];
-                return (
-                  (optional || param in dynamicMatches) && // Interpolate group into data URL if present
-                  (interpolatedRoute =
-                    interpolatedRoute.replace(
-                      replaced,
-                      repeat
-                        ? value.map(_escapePathDelimiters.default).join("/")
-                        : (0, _escapePathDelimiters.default)(value)
-                    ) || "/")
-                );
-              })
-            ) {
-              interpolatedRoute = ""; // did not satisfy all requirements
-              // n.b. We ignore this error because we handle warning for this case in
-              // development in the `<Link>` component directly.
-            }
-          }
-
+          var isDynamic = (0, _isDynamic.isDynamicRoute)(route);
+          var interpolatedRoute = isDynamic
+            ? (0, _router.interpolateAs)(hrefPathname, asPathname, query)
+            : "";
           return isDynamic
             ? interpolatedRoute && getHrefForSlug(interpolatedRoute)
             : getHrefForSlug(route);
Diff for main-b8d3644..f586aeb2b.js
@@ -1225,21 +1225,6 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
       /***/
     },
 
-    /***/ fcRV: /***/ function(module, exports, __webpack_require__) {
-      "use strict";
-
-      exports.__esModule = true;
-      exports["default"] = escapePathDelimiters; // escape delimiters used by path-to-regexp
-
-      function escapePathDelimiters(segment) {
-        return segment.replace(/[/#?]/g, function(_char) {
-          return encodeURIComponent(_char);
-        });
-      }
-
-      /***/
-    },
-
     /***/ pVnL: /***/ function(module, exports) {
       function _extends() {
         module.exports = _extends =
@@ -1550,10 +1535,6 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
 
       var _router = __webpack_require__("elyg");
 
-      var _escapePathDelimiters = _interopRequireDefault(
-        __webpack_require__("fcRV")
-      );
-
       var _getAssetPathFromRoute = _interopRequireDefault(
         __webpack_require__("Lab5")
       );
@@ -1564,10 +1545,6 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
 
       var _querystring = __webpack_require__("3WeD");
 
-      var _routeMatcher = __webpack_require__("gguc");
-
-      var _routeRegex = __webpack_require__("YTqd");
-
       var looseToArray = function looseToArray(input) {
         return [].slice.call(input);
       };
@@ -1777,59 +1754,10 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
                 );
               };
 
-              var isDynamic = (0, _isDynamic.isDynamicRoute)(route),
-                interpolatedRoute;
-
-              if (isDynamic) {
-                var dynamicRegex = (0, _routeRegex.getRouteRegex)(route);
-                var dynamicGroups = dynamicRegex.groups;
-                var dynamicMatches = // Try to match the dynamic route against the asPath
-                  (0, _routeMatcher.getRouteMatcher)(dynamicRegex)(
-                    asPathname
-                  ) || // Fall back to reading the values from the href
-                  // TODO: should this take priority; also need to change in the router.
-                  query;
-                interpolatedRoute = route;
-
-                if (
-                  !Object.keys(dynamicGroups).every(function(param) {
-                    var value = dynamicMatches[param] || "";
-                    var _dynamicGroups$param = dynamicGroups[param],
-                      repeat = _dynamicGroups$param.repeat,
-                      optional = _dynamicGroups$param.optional; // support single-level catch-all
-                    // TODO: more robust handling for user-error (passing `/`)
-
-                    var replaced = "["
-                      .concat(repeat ? "..." : "")
-                      .concat(param, "]");
-
-                    if (optional) {
-                      replaced = ""
-                        .concat(!value ? "/" : "", "[")
-                        .concat(replaced, "]");
-                    }
-
-                    if (repeat && !Array.isArray(value)) value = [value];
-                    return (
-                      (optional || param in dynamicMatches) && // Interpolate group into data URL if present
-                      (interpolatedRoute =
-                        interpolatedRoute.replace(
-                          replaced,
-                          repeat
-                            ? value
-                                .map(_escapePathDelimiters["default"])
-                                .join("/")
-                            : (0, _escapePathDelimiters["default"])(value)
-                        ) || "/")
-                    );
-                  })
-                ) {
-                  interpolatedRoute = ""; // did not satisfy all requirements
-                  // n.b. We ignore this error because we handle warning for this case in
-                  // development in the `<Link>` component directly.
-                }
-              }
-
+              var isDynamic = (0, _isDynamic.isDynamicRoute)(route);
+              var interpolatedRoute = isDynamic
+                ? (0, _router.interpolateAs)(hrefPathname, asPathname, query)
+                : "";
               return isDynamic
                 ? interpolatedRoute && getHrefForSlug(interpolatedRoute)
                 : getHrefForSlug(route);
Diff for index.html
@@ -7,7 +7,7 @@
     <noscript data-n-css="true"></noscript>
     <link
       rel="preload"
-      href="/_next/static/chunks/main-4d90bb4e4e7bbc2b2532.module.js"
+      href="/_next/static/chunks/main-5823e90a936c4e01a4bf.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -25,7 +25,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.f48d291f6d1033f6c087.module.js"
+      href="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.f4cf18108dce66b669da.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -82,13 +82,13 @@
       src="/_next/static/chunks/polyfills-f73ba3fc145972ef83e9.js"
     ></script>
     <script
-      src="/_next/static/chunks/main-b8d3644a020f586aeb2b.js"
+      src="/_next/static/chunks/main-aeb7939c646600c3a9b3.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/main-4d90bb4e4e7bbc2b2532.module.js"
+      src="/_next/static/chunks/main-5823e90a936c4e01a4bf.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
@@ -118,13 +118,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.abb28f9c6d97000fca82.js"
+      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.5b5e017fd5e9f2822af2.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.f48d291f6d1033f6c087.module.js"
+      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.f4cf18108dce66b669da.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
Diff for link.html
@@ -7,7 +7,7 @@
     <noscript data-n-css="true"></noscript>
     <link
       rel="preload"
-      href="/_next/static/chunks/main-4d90bb4e4e7bbc2b2532.module.js"
+      href="/_next/static/chunks/main-5823e90a936c4e01a4bf.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -25,7 +25,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.f48d291f6d1033f6c087.module.js"
+      href="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.f4cf18108dce66b669da.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -37,7 +37,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/pages/link-e2f1e0e7ed02569239da.module.js"
+      href="/_next/static/chunks/pages/link-cb038f0ac2e648ce4861.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -87,13 +87,13 @@
       src="/_next/static/chunks/polyfills-f73ba3fc145972ef83e9.js"
     ></script>
     <script
-      src="/_next/static/chunks/main-b8d3644a020f586aeb2b.js"
+      src="/_next/static/chunks/main-aeb7939c646600c3a9b3.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/main-4d90bb4e4e7bbc2b2532.module.js"
+      src="/_next/static/chunks/main-5823e90a936c4e01a4bf.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
@@ -123,13 +123,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.abb28f9c6d97000fca82.js"
+      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.5b5e017fd5e9f2822af2.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.f48d291f6d1033f6c087.module.js"
+      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.f4cf18108dce66b669da.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
@@ -147,13 +147,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/pages/link-46fd48c0b73b2f2d75a4.js"
+      src="/_next/static/chunks/pages/link-32658e75d53af2daa2e0.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/pages/link-e2f1e0e7ed02569239da.module.js"
+      src="/_next/static/chunks/pages/link-cb038f0ac2e648ce4861.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
Diff for withRouter.html
@@ -7,7 +7,7 @@
     <noscript data-n-css="true"></noscript>
     <link
       rel="preload"
-      href="/_next/static/chunks/main-4d90bb4e4e7bbc2b2532.module.js"
+      href="/_next/static/chunks/main-5823e90a936c4e01a4bf.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -25,7 +25,7 @@
     />
     <link
       rel="preload"
-      href="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.f48d291f6d1033f6c087.module.js"
+      href="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.f4cf18108dce66b669da.module.js"
       as="script"
       crossorigin="anonymous"
     />
@@ -82,13 +82,13 @@
       src="/_next/static/chunks/polyfills-f73ba3fc145972ef83e9.js"
     ></script>
     <script
-      src="/_next/static/chunks/main-b8d3644a020f586aeb2b.js"
+      src="/_next/static/chunks/main-aeb7939c646600c3a9b3.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/main-4d90bb4e4e7bbc2b2532.module.js"
+      src="/_next/static/chunks/main-5823e90a936c4e01a4bf.module.js"
       async=""
       crossorigin="anonymous"
       type="module"
@@ -118,13 +118,13 @@
       type="module"
     ></script>
     <script
-      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.abb28f9c6d97000fca82.js"
+      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.5b5e017fd5e9f2822af2.js"
       async=""
       crossorigin="anonymous"
       nomodule=""
     ></script>
     <script
-      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.f48d291f6d1033f6c087.module.js"
+      src="/_next/static/chunks/677f882d2ed86fa3467b8979053c1a4c3f8bc4df.f4cf18108dce66b669da.module.js"
       async=""
       crossorigin="anonymous"
       type="module"

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
buildDuration 13.3s 13.3s -5ms
nodeModulesSize 55.9 MB 55.9 MB ⚠️ +2.05 kB
Client Bundles (main, webpack, commons) Overall increase ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
677f882d2ed8..9ff9.js gzip 10.3 kB N/A N/A
framework.HASH.js gzip 39 kB 39 kB
main-e1c4209..e2c9.js gzip 7.32 kB N/A N/A
webpack-e067..f178.js gzip 751 B 751 B
677f882d2ed8..01b7.js gzip N/A 10.5 kB N/A
main-f8f2cfe..033f.js gzip N/A 7.1 kB N/A
Overall change 57.3 kB 57.3 kB ⚠️ +35 B
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
677f882d2ed8..dule.js gzip 6.13 kB N/A N/A
framework.HA..dule.js gzip 39 kB 39 kB
main-9077898..dule.js gzip 6.38 kB N/A N/A
webpack-07c5..dule.js gzip 751 B 751 B
677f882d2ed8..dule.js gzip N/A 6.39 kB N/A
main-a6f8e84..dule.js gzip N/A 6.16 kB N/A
Overall change 52.2 kB 52.3 kB ⚠️ +47 B
Legacy Client Bundles (polyfills)
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
polyfills-4b..e242.js gzip 31 kB 31 kB
Overall change 31 kB 31 kB
Client Pages Overall increase ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
_app-9a0b9e1..b37e.js gzip 1.28 kB 1.28 kB
_error-ed1b0..8fbd.js gzip 3.44 kB 3.44 kB
hooks-89731c..c609.js gzip 887 B 887 B
index-17468f..5d83.js gzip 227 B 227 B
link-ae98065..267e.js gzip 1.29 kB N/A N/A
routerDirect..924c.js gzip 284 B 284 B
withRouter-7..c13d.js gzip 284 B 284 B
link-d2344ce..8b36.js gzip N/A 1.3 kB N/A
Overall change 7.69 kB 7.71 kB ⚠️ +16 B
Client Pages Modern Overall increase ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
_app-75d3a82..dule.js gzip 625 B 625 B
_error-4469a..dule.js gzip 2.29 kB 2.29 kB
hooks-cbf13f..dule.js gzip 387 B 387 B
index-b9a643..dule.js gzip 226 B 226 B
link-cb244c4..dule.js gzip 1.26 kB N/A N/A
routerDirect..dule.js gzip 284 B 284 B
withRouter-f..dule.js gzip 282 B 282 B
link-f8c0daf..dule.js gzip N/A 1.26 kB N/A
Overall change 5.35 kB 5.36 kB ⚠️ +5 B
Client Build Manifests Overall decrease ✓
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
_buildManifest.js gzip 323 B 322 B -1 B
_buildManife..dule.js gzip 329 B 329 B
Overall change 652 B 651 B -1 B
Serverless bundles Overall increase ⚠️
vercel/next.js canary ijjk/next.js fix/param-interpolation Change
_error.js 1.03 MB 1.03 MB
404.html 4.22 kB 4.22 kB
hooks.html 3.86 kB 3.86 kB
index.js 1.03 MB 1.03 MB
link.js 1.07 MB 1.08 MB ⚠️ +2.5 kB
routerDirect.js 1.07 MB 1.07 MB ⚠️ +2.46 kB
withRouter.js 1.07 MB 1.07 MB ⚠️ +2.46 kB
Overall change 5.28 MB 5.29 MB ⚠️ +7.42 kB
Commit: 2287614

@kodiakhq kodiakhq bot merged commit f8d92a6 into vercel:canary Sep 2, 2020
@ijjk ijjk deleted the fix/param-interpolation branch September 2, 2020 16:26
HitoriSensei pushed a commit to HitoriSensei/next.js that referenced this pull request Sep 26, 2020
This corrects/makes sure interpolating dynamic route values for `href` works correctly. This provides an alternative approach to building the `href` value with `next/link` so that you don't need to worry about encoding the params manually. 

Closes: vercel#13473
Closes: vercel#14959
Closes: vercel#16771
@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
2 participants