Skip to content

Conversation

bgub
Copy link
Contributor

@bgub bgub commented Jul 11, 2025

Typed Links: Turbopack support

This PR replaces the old experimental.typedRoutes implementation with a new approach that works on both Turbopack and Webpack.

Note: a previous version of this PR contained new props for the Link component: path, params, and searchParams. In the interest of bringing typed links support to Turbopack as soon as possible, I've removed that change from this PR and will create a new one later.

Copy link
Contributor Author

bgub commented Jul 11, 2025

@bgub bgub changed the base branch from feat/typed-routes-new to graphite-base/81528 July 14, 2025 22:54
@bgub bgub force-pushed the graphite-base/81528 branch from 9566122 to 639db50 Compare July 15, 2025 04:13
@bgub bgub force-pushed the feat/typed-links branch from f007b0d to 40eda62 Compare July 15, 2025 04:13
@bgub bgub changed the base branch from graphite-base/81528 to feat/typed-routes-new July 15, 2025 04:13
@bgub bgub force-pushed the feat/typed-routes-new branch from 639db50 to cfb2e87 Compare July 15, 2025 23:44
@bgub bgub force-pushed the feat/typed-links branch from 40eda62 to 09d4588 Compare July 15, 2025 23:44
@ijjk ijjk added the Rspack label Jul 15, 2025
@ijjk
Copy link
Member

ijjk commented Jul 15, 2025

Tests Passed

@ijjk
Copy link
Member

ijjk commented Jul 16, 2025

Stats from current PR

Default Build (Increase detected ⚠️)
General
vercel/next.js canary vercel/next.js feat/typed-links Change
buildDuration 23.1s 19.5s N/A
buildDurationCached 18.4s 16.6s N/A
nodeModulesSize 446 MB 446 MB N/A
nextStartRea..uration (ms) 471ms 471ms
Client Bundles (main, webpack)
vercel/next.js canary vercel/next.js feat/typed-links Change
234bef07-HASH.js gzip 54.2 kB 54.2 kB N/A
5194.HASH.js gzip 169 B 169 B
8863-HASH.js gzip 5.27 kB 5.27 kB N/A
9304-HASH.js gzip 45.9 kB 45.3 kB N/A
framework-HASH.js gzip 57.7 kB 57.7 kB N/A
main-app-HASH.js gzip 254 B 253 B N/A
main-HASH.js gzip 36.7 kB 36.5 kB N/A
webpack-HASH.js gzip 1.71 kB 1.71 kB N/A
Overall change 169 B 169 B
Legacy Client Bundles (polyfills)
vercel/next.js canary vercel/next.js feat/typed-links Change
polyfills-HASH.js gzip 39.4 kB 39.4 kB
Overall change 39.4 kB 39.4 kB
Client Pages
vercel/next.js canary vercel/next.js feat/typed-links Change
_app-HASH.js gzip 194 B 193 B N/A
_error-HASH.js gzip 182 B 182 B
amp-HASH.js gzip 502 B 507 B N/A
css-HASH.js gzip 335 B 333 B N/A
dynamic-HASH.js gzip 1.83 kB 1.83 kB N/A
edge-ssr-HASH.js gzip 255 B 255 B
head-HASH.js gzip 350 B 352 B N/A
hooks-HASH.js gzip 385 B 383 B N/A
image-HASH.js gzip 4.65 kB 4.66 kB N/A
index-HASH.js gzip 257 B 259 B N/A
link-HASH.js gzip 2.52 kB 2.52 kB N/A
routerDirect..HASH.js gzip 320 B 318 B N/A
script-HASH.js gzip 387 B 386 B N/A
withRouter-HASH.js gzip 315 B 313 B N/A
1afbb74e6ecf..834.css gzip 106 B 106 B
Overall change 543 B 543 B
Client Build Manifests
vercel/next.js canary vercel/next.js feat/typed-links Change
_buildManifest.js gzip 753 B 751 B N/A
Overall change 0 B 0 B
Rendered Page Sizes
vercel/next.js canary vercel/next.js feat/typed-links Change
index.html gzip 523 B 523 B
link.html gzip 537 B 537 B
withRouter.html gzip 519 B 519 B
Overall change 1.58 kB 1.58 kB
Edge SSR bundle Size
vercel/next.js canary vercel/next.js feat/typed-links Change
edge-ssr.js gzip 120 kB 120 kB N/A
page.js gzip 223 kB 223 kB N/A
Overall change 0 B 0 B
Middleware size Overall increase ⚠️
vercel/next.js canary vercel/next.js feat/typed-links Change
middleware-b..fest.js gzip 673 B 672 B N/A
middleware-r..fest.js gzip 156 B 155 B N/A
middleware.js gzip 32.3 kB 32.6 kB ⚠️ +286 B
edge-runtime..pack.js gzip 853 B 853 B
Overall change 33.2 kB 33.5 kB ⚠️ +286 B
Next Runtimes
vercel/next.js canary vercel/next.js feat/typed-links Change
app-page-exp...dev.js gzip 283 kB 283 kB N/A
app-page-exp..prod.js gzip 156 kB 156 kB
app-page-tur...dev.js gzip 284 kB 284 kB N/A
app-page-tur..prod.js gzip 156 kB 156 kB
app-page-tur...dev.js gzip 272 kB 272 kB N/A
app-page-tur..prod.js gzip 150 kB 150 kB
app-page.run...dev.js gzip 271 kB 271 kB N/A
app-page.run..prod.js gzip 150 kB 150 kB
app-route-ex...dev.js gzip 69.5 kB 69.5 kB
app-route-ex..prod.js gzip 48.8 kB 48.8 kB
app-route-tu...dev.js gzip 69.5 kB 69.5 kB
app-route-tu..prod.js gzip 48.8 kB 48.8 kB
app-route-tu...dev.js gzip 68.9 kB 68.9 kB
app-route-tu..prod.js gzip 48.4 kB 48.4 kB
app-route.ru...dev.js gzip 68.8 kB 68.8 kB
app-route.ru..prod.js gzip 48.4 kB 48.4 kB
dist_client_...dev.js gzip 326 B 326 B
dist_client_...dev.js gzip 328 B 328 B
dist_client_...dev.js gzip 320 B 320 B
dist_client_...dev.js gzip 318 B 318 B
pages-api-tu...dev.js gzip 42.3 kB 42.3 kB
pages-api-tu..prod.js gzip 32.5 kB 32.5 kB
pages-api.ru...dev.js gzip 42.2 kB 42.2 kB
pages-api.ru..prod.js gzip 32.5 kB 32.5 kB
pages-turbo....dev.js gzip 52.3 kB 52.3 kB
pages-turbo...prod.js gzip 39.9 kB 39.9 kB
pages.runtim...dev.js gzip 52.4 kB 52.4 kB
pages.runtim..prod.js gzip 40 kB 40 kB
server.runti..prod.js gzip 59.8 kB 59.8 kB
Overall change 1.48 MB 1.48 MB
build cache Overall increase ⚠️
vercel/next.js canary vercel/next.js feat/typed-links Change
0.pack gzip 2.86 MB 2.86 MB ⚠️ +3.39 kB
index.pack gzip 93 kB 93.5 kB ⚠️ +496 B
Overall change 2.95 MB 2.96 MB ⚠️ +3.89 kB
Diff details
Diff for page.js

Diff too large to display

Diff for middleware.js

Diff too large to display

Diff for edge-ssr.js

Diff too large to display

Diff for amp-HASH.js
@@ -1,17 +1,65 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [5034],
   {
-    /***/ 4105: /***/ (
+    /***/ 6212: /***/ (
+      __unused_webpack_module,
+      __webpack_exports__,
+      __webpack_require__
+    ) => {
+      "use strict";
+      __webpack_require__.r(__webpack_exports__);
+      /* harmony export */ __webpack_require__.d(__webpack_exports__, {
+        /* harmony export */ config: () => /* binding */ config,
+        /* harmony export */ default: () => /* binding */ Amp,
+        /* harmony export */
+      });
+      /* harmony import */ var next_amp__WEBPACK_IMPORTED_MODULE_0__ =
+        __webpack_require__(7023);
+      /* harmony import */ var next_amp__WEBPACK_IMPORTED_MODULE_0___default =
+        /*#__PURE__*/ __webpack_require__.n(
+          next_amp__WEBPACK_IMPORTED_MODULE_0__
+        );
+
+      const config = {
+        amp: "hybrid",
+      };
+      function Amp(props) {
+        return (0, next_amp__WEBPACK_IMPORTED_MODULE_0__.useAmp)()
+          ? "AMP mode"
+          : "normal mode";
+      }
+
+      /***/
+    },
+
+    /***/ 7023: /***/ (
       module,
       __unused_webpack_exports,
       __webpack_require__
     ) => {
-      module.exports = __webpack_require__(4642);
+      module.exports = __webpack_require__(9926);
+
+      /***/
+    },
+
+    /***/ 8647: /***/ (
+      __unused_webpack_module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      (window.__NEXT_P = window.__NEXT_P || []).push([
+        "/amp",
+        function () {
+          return __webpack_require__(6212);
+        },
+      ]);
+      if (false) {
+      }
 
       /***/
     },
 
-    /***/ 4642: /***/ (module, exports, __webpack_require__) => {
+    /***/ 9926: /***/ (module, exports, __webpack_require__) => {
       "use strict";
 
       Object.defineProperty(exports, "__esModule", {
@@ -27,8 +75,8 @@
       const _react = /*#__PURE__*/ _interop_require_default._(
         __webpack_require__(5977)
       );
-      const _ampcontextsharedruntime = __webpack_require__(8358);
-      const _ampmode = __webpack_require__(242);
+      const _ampcontextsharedruntime = __webpack_require__(5418);
+      const _ampmode = __webpack_require__(3494);
       function useAmp() {
         // Don't assign the context value to a variable to save bytes
         return (0, _ampmode.isInAmpMode)(
@@ -49,61 +97,13 @@
 
       /***/
     },
-
-    /***/ 5261: /***/ (
-      __unused_webpack_module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      (window.__NEXT_P = window.__NEXT_P || []).push([
-        "/amp",
-        function () {
-          return __webpack_require__(9550);
-        },
-      ]);
-      if (false) {
-      }
-
-      /***/
-    },
-
-    /***/ 9550: /***/ (
-      __unused_webpack_module,
-      __webpack_exports__,
-      __webpack_require__
-    ) => {
-      "use strict";
-      __webpack_require__.r(__webpack_exports__);
-      /* harmony export */ __webpack_require__.d(__webpack_exports__, {
-        /* harmony export */ config: () => /* binding */ config,
-        /* harmony export */ default: () => /* binding */ Amp,
-        /* harmony export */
-      });
-      /* harmony import */ var next_amp__WEBPACK_IMPORTED_MODULE_0__ =
-        __webpack_require__(4105);
-      /* harmony import */ var next_amp__WEBPACK_IMPORTED_MODULE_0___default =
-        /*#__PURE__*/ __webpack_require__.n(
-          next_amp__WEBPACK_IMPORTED_MODULE_0__
-        );
-
-      const config = {
-        amp: "hybrid",
-      };
-      function Amp(props) {
-        return (0, next_amp__WEBPACK_IMPORTED_MODULE_0__.useAmp)()
-          ? "AMP mode"
-          : "normal mode";
-      }
-
-      /***/
-    },
   },
   /******/ (__webpack_require__) => {
     // webpackRuntimeModules
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(5261)
+      __webpack_exec__(8647)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for css-HASH.js
@@ -1,7 +1,14 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [9813],
   {
-    /***/ 5267: /***/ (
+    /***/ 1978: /***/ (module) => {
+      // extracted by mini-css-extract-plugin
+      module.exports = { helloWorld: "css_helloWorld__aUdUq" };
+
+      /***/
+    },
+
+    /***/ 6941: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -15,7 +22,7 @@
       /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
         __webpack_require__(7765);
       /* harmony import */ var _css_module_css__WEBPACK_IMPORTED_MODULE_1__ =
-        __webpack_require__(6320);
+        __webpack_require__(1978);
       /* harmony import */ var _css_module_css__WEBPACK_IMPORTED_MODULE_1___default =
         /*#__PURE__*/ __webpack_require__.n(
           _css_module_css__WEBPACK_IMPORTED_MODULE_1__
@@ -35,14 +42,7 @@
       /***/
     },
 
-    /***/ 6320: /***/ (module) => {
-      // extracted by mini-css-extract-plugin
-      module.exports = { helloWorld: "css_helloWorld__aUdUq" };
-
-      /***/
-    },
-
-    /***/ 9643: /***/ (
+    /***/ 8685: /***/ (
       __unused_webpack_module,
       __unused_webpack_exports,
       __webpack_require__
@@ -50,7 +50,7 @@
       (window.__NEXT_P = window.__NEXT_P || []).push([
         "/css",
         function () {
-          return __webpack_require__(5267);
+          return __webpack_require__(6941);
         },
       ]);
       if (false) {
@@ -64,7 +64,7 @@
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(9643)
+      __webpack_exec__(8685)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for dynamic-HASH.js
@@ -1,17 +1,63 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [2291],
   {
-    /***/ 2406: /***/ (
-      module,
-      __unused_webpack_exports,
+    /***/ 2839: /***/ (
+      __unused_webpack_module,
+      __webpack_exports__,
       __webpack_require__
     ) => {
-      module.exports = __webpack_require__(8949);
+      "use strict";
+      __webpack_require__.r(__webpack_exports__);
+      /* harmony export */ __webpack_require__.d(__webpack_exports__, {
+        /* harmony export */ __N_SSP: () => /* binding */ __N_SSP,
+        /* harmony export */ default: () => __WEBPACK_DEFAULT_EXPORT__,
+        /* harmony export */
+      });
+      /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
+        __webpack_require__(7765);
+      /* harmony import */ var next_dynamic__WEBPACK_IMPORTED_MODULE_1__ =
+        __webpack_require__(7444);
+      /* harmony import */ var next_dynamic__WEBPACK_IMPORTED_MODULE_1___default =
+        /*#__PURE__*/ __webpack_require__.n(
+          next_dynamic__WEBPACK_IMPORTED_MODULE_1__
+        );
+
+      const DynamicHello = next_dynamic__WEBPACK_IMPORTED_MODULE_1___default()(
+        () =>
+          __webpack_require__
+            .e(/* import() */ 1376)
+            .then(__webpack_require__.bind(__webpack_require__, 1376))
+            .then((mod) => mod.Hello),
+        {
+          loadableGenerated: {
+            webpack: () => [/*require.resolve*/ 1376],
+          },
+        }
+      );
+      const Page = () =>
+        /*#__PURE__*/ (0, react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(
+          react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment,
+          {
+            children: [
+              /*#__PURE__*/ (0,
+              react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("p", {
+                children: "testing next/dynamic size",
+              }),
+              /*#__PURE__*/ (0,
+              react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(
+                DynamicHello,
+                {}
+              ),
+            ],
+          }
+        );
+      var __N_SSP = true;
+      /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = Page;
 
       /***/
     },
 
-    /***/ 4466: /***/ (
+    /***/ 4478: /***/ (
       __unused_webpack_module,
       exports,
       __webpack_require__
@@ -53,7 +99,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
       const _react = /*#__PURE__*/ _interop_require_default._(
         __webpack_require__(5977)
       );
-      const _loadablecontextsharedruntime = __webpack_require__(8452);
+      const _loadablecontextsharedruntime = __webpack_require__(5792);
       function resolve(obj) {
         return obj && obj.default ? obj.default : obj;
       }
@@ -288,63 +334,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
       /***/
     },
 
-    /***/ 4545: /***/ (
-      __unused_webpack_module,
-      __webpack_exports__,
-      __webpack_require__
-    ) => {
-      "use strict";
-      __webpack_require__.r(__webpack_exports__);
-      /* harmony export */ __webpack_require__.d(__webpack_exports__, {
-        /* harmony export */ __N_SSP: () => /* binding */ __N_SSP,
-        /* harmony export */ default: () => __WEBPACK_DEFAULT_EXPORT__,
-        /* harmony export */
-      });
-      /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
-        __webpack_require__(7765);
-      /* harmony import */ var next_dynamic__WEBPACK_IMPORTED_MODULE_1__ =
-        __webpack_require__(2406);
-      /* harmony import */ var next_dynamic__WEBPACK_IMPORTED_MODULE_1___default =
-        /*#__PURE__*/ __webpack_require__.n(
-          next_dynamic__WEBPACK_IMPORTED_MODULE_1__
-        );
-
-      const DynamicHello = next_dynamic__WEBPACK_IMPORTED_MODULE_1___default()(
-        () =>
-          __webpack_require__
-            .e(/* import() */ 5194)
-            .then(__webpack_require__.bind(__webpack_require__, 5194))
-            .then((mod) => mod.Hello),
-        {
-          loadableGenerated: {
-            webpack: () => [/*require.resolve*/ 5194],
-          },
-        }
-      );
-      const Page = () =>
-        /*#__PURE__*/ (0, react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(
-          react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment,
-          {
-            children: [
-              /*#__PURE__*/ (0,
-              react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("p", {
-                children: "testing next/dynamic size",
-              }),
-              /*#__PURE__*/ (0,
-              react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(
-                DynamicHello,
-                {}
-              ),
-            ],
-          }
-        );
-      var __N_SSP = true;
-      /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = Page;
-
-      /***/
-    },
-
-    /***/ 8452: /***/ (
+    /***/ 5792: /***/ (
       __unused_webpack_module,
       exports,
       __webpack_require__
@@ -371,24 +361,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
       /***/
     },
 
-    /***/ 8931: /***/ (
-      __unused_webpack_module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      (window.__NEXT_P = window.__NEXT_P || []).push([
-        "/dynamic",
-        function () {
-          return __webpack_require__(4545);
-        },
-      ]);
-      if (false) {
-      }
-
-      /***/
-    },
-
-    /***/ 8949: /***/ (module, exports, __webpack_require__) => {
+    /***/ 6153: /***/ (module, exports, __webpack_require__) => {
       "use strict";
 
       Object.defineProperty(exports, "__esModule", {
@@ -421,7 +394,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
         __webpack_require__(5977)
       );
       const _loadablesharedruntime = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(4466)
+        __webpack_require__(4478)
       );
       const isServerSide = "object" === "undefined";
       // Normalize loader to return the module as form { default: Component } for `React.lazy`.
@@ -521,13 +494,40 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
 
       /***/
     },
+
+    /***/ 7444: /***/ (
+      module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      module.exports = __webpack_require__(6153);
+
+      /***/
+    },
+
+    /***/ 9805: /***/ (
+      __unused_webpack_module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      (window.__NEXT_P = window.__NEXT_P || []).push([
+        "/dynamic",
+        function () {
+          return __webpack_require__(2839);
+        },
+      ]);
+      if (false) {
+      }
+
+      /***/
+    },
   },
   /******/ (__webpack_require__) => {
     // webpackRuntimeModules
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(8931)
+      __webpack_exec__(9805)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for edge-ssr-HASH.js
@@ -1,24 +1,7 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [676],
   {
-    /***/ 4717: /***/ (
-      __unused_webpack_module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      (window.__NEXT_P = window.__NEXT_P || []).push([
-        "/edge-ssr",
-        function () {
-          return __webpack_require__(7776);
-        },
-      ]);
-      if (false) {
-      }
-
-      /***/
-    },
-
-    /***/ 7776: /***/ (
+    /***/ 170: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -37,13 +20,30 @@
 
       /***/
     },
+
+    /***/ 8079: /***/ (
+      __unused_webpack_module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      (window.__NEXT_P = window.__NEXT_P || []).push([
+        "/edge-ssr",
+        function () {
+          return __webpack_require__(170);
+        },
+      ]);
+      if (false) {
+      }
+
+      /***/
+    },
   },
   /******/ (__webpack_require__) => {
     // webpackRuntimeModules
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(4717)
+      __webpack_exec__(8079)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for head-HASH.js
@@ -1,34 +1,17 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [5350],
   {
-    /***/ 943: /***/ (
+    /***/ 1177: /***/ (
       module,
       __unused_webpack_exports,
       __webpack_require__
     ) => {
-      module.exports = __webpack_require__(2554);
+      module.exports = __webpack_require__(8366);
 
       /***/
     },
 
-    /***/ 3829: /***/ (
-      __unused_webpack_module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      (window.__NEXT_P = window.__NEXT_P || []).push([
-        "/head",
-        function () {
-          return __webpack_require__(4662);
-        },
-      ]);
-      if (false) {
-      }
-
-      /***/
-    },
-
-    /***/ 4662: /***/ (
+    /***/ 1992: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -43,7 +26,7 @@
       /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
         __webpack_require__(7765);
       /* harmony import */ var next_head__WEBPACK_IMPORTED_MODULE_1__ =
-        __webpack_require__(943);
+        __webpack_require__(1177);
       /* harmony import */ var next_head__WEBPACK_IMPORTED_MODULE_1___default =
         /*#__PURE__*/ __webpack_require__.n(
           next_head__WEBPACK_IMPORTED_MODULE_1__
@@ -76,13 +59,30 @@
 
       /***/
     },
+
+    /***/ 8751: /***/ (
+      __unused_webpack_module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      (window.__NEXT_P = window.__NEXT_P || []).push([
+        "/head",
+        function () {
+          return __webpack_require__(1992);
+        },
+      ]);
+      if (false) {
+      }
+
+      /***/
+    },
   },
   /******/ (__webpack_require__) => {
     // webpackRuntimeModules
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(3829)
+      __webpack_exec__(8751)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for hooks-HASH.js
@@ -1,7 +1,24 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [9804],
   {
-    /***/ 2452: /***/ (
+    /***/ 2227: /***/ (
+      __unused_webpack_module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      (window.__NEXT_P = window.__NEXT_P || []).push([
+        "/hooks",
+        function () {
+          return __webpack_require__(2770);
+        },
+      ]);
+      if (false) {
+      }
+
+      /***/
+    },
+
+    /***/ 2770: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -59,30 +76,13 @@
 
       /***/
     },
-
-    /***/ 6105: /***/ (
-      __unused_webpack_module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      (window.__NEXT_P = window.__NEXT_P || []).push([
-        "/hooks",
-        function () {
-          return __webpack_require__(2452);
-        },
-      ]);
-      if (false) {
-      }
-
-      /***/
-    },
   },
   /******/ (__webpack_require__) => {
     // webpackRuntimeModules
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(6105)
+      __webpack_exec__(2227)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for image-HASH.js

Diff too large to display

Diff for link-HASH.js
@@ -1,143 +1,82 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [4672],
   {
-    /***/ 1585: /***/ (module, exports, __webpack_require__) => {
+    /***/ 2346: /***/ (__unused_webpack_module, exports) => {
       "use strict";
 
       Object.defineProperty(exports, "__esModule", {
         value: true,
       });
-      Object.defineProperty(exports, "useIntersection", {
+      Object.defineProperty(exports, "errorOnce", {
         enumerable: true,
         get: function () {
-          return useIntersection;
+          return errorOnce;
         },
       });
-      const _react = __webpack_require__(5977);
-      const _requestidlecallback = __webpack_require__(356);
-      const hasIntersectionObserver =
-        typeof IntersectionObserver === "function";
-      const observers = new Map();
-      const idList = [];
-      function createObserver(options) {
-        const id = {
-          root: options.root || null,
-          margin: options.rootMargin || "",
-        };
-        const existing = idList.find(
-          (obj) => obj.root === id.root && obj.margin === id.margin
-        );
-        let instance;
-        if (existing) {
-          instance = observers.get(existing);
-          if (instance) {
-            return instance;
-          }
-        }
-        const elements = new Map();
-        const observer = new IntersectionObserver((entries) => {
-          entries.forEach((entry) => {
-            const callback = elements.get(entry.target);
-            const isVisible =
-              entry.isIntersecting || entry.intersectionRatio > 0;
-            if (callback && isVisible) {
-              callback(isVisible);
-            }
-          });
-        }, options);
-        instance = {
-          id,
-          observer,
-          elements,
-        };
-        idList.push(id);
-        observers.set(id, instance);
-        return instance;
-      }
-      function observe(element, callback, options) {
-        const { id, observer, elements } = createObserver(options);
-        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);
-            const index = idList.findIndex(
-              (obj) => obj.root === id.root && obj.margin === id.margin
-            );
-            if (index > -1) {
-              idList.splice(index, 1);
-            }
-          }
-        };
-      }
-      function useIntersection(param) {
-        let { rootRef, rootMargin, disabled } = param;
-        const isDisabled = disabled || !hasIntersectionObserver;
-        const [visible, setVisible] = (0, _react.useState)(false);
-        const elementRef = (0, _react.useRef)(null);
-        const setElement = (0, _react.useCallback)((element) => {
-          elementRef.current = element;
-        }, []);
-        (0, _react.useEffect)(() => {
-          if (hasIntersectionObserver) {
-            if (isDisabled || visible) return;
-            const element = elementRef.current;
-            if (element && element.tagName) {
-              const unobserve = observe(
-                element,
-                (isVisible) => isVisible && setVisible(isVisible),
-                {
-                  root: rootRef == null ? void 0 : rootRef.current,
-                  rootMargin,
-                }
-              );
-              return unobserve;
-            }
-          } else {
-            if (!visible) {
-              const idleCallback = (0,
-              _requestidlecallback.requestIdleCallback)(() => setVisible(true));
-              return () =>
-                (0, _requestidlecallback.cancelIdleCallback)(idleCallback);
-            }
-          }
-          // eslint-disable-next-line react-hooks/exhaustive-deps
-        }, [isDisabled, rootMargin, rootRef, visible, elementRef.current]);
-        const resetVisible = (0, _react.useCallback)(() => {
-          setVisible(false);
-        }, []);
-        return [setElement, visible, resetVisible];
-      }
-      if (
-        (typeof exports.default === "function" ||
-          (typeof exports.default === "object" && exports.default !== null)) &&
-        typeof exports.default.__esModule === "undefined"
-      ) {
-        Object.defineProperty(exports.default, "__esModule", {
-          value: true,
-        });
-        Object.assign(exports.default, exports);
-        module.exports = exports.default;
-      } //# sourceMappingURL=use-intersection.js.map
+      let errorOnce = (_) => {};
+      if (false) {
+      } //# sourceMappingURL=error-once.js.map
 
       /***/
     },
 
-    /***/ 2621: /***/ (
+    /***/ 2783: /***/ (
       module,
       __unused_webpack_exports,
       __webpack_require__
     ) => {
-      module.exports = __webpack_require__(5410);
+      module.exports = __webpack_require__(5926);
 
       /***/
     },
 
-    /***/ 5410: /***/ (module, exports, __webpack_require__) => {
+    /***/ 4174: /***/ (
+      __unused_webpack_module,
+      __webpack_exports__,
+      __webpack_require__
+    ) => {
+      "use strict";
+      __webpack_require__.r(__webpack_exports__);
+      /* harmony export */ __webpack_require__.d(__webpack_exports__, {
+        /* harmony export */ __N_SSP: () => /* binding */ __N_SSP,
+        /* harmony export */ default: () => __WEBPACK_DEFAULT_EXPORT__,
+        /* harmony export */
+      });
+      /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
+        __webpack_require__(7765);
+      /* harmony import */ var next_link__WEBPACK_IMPORTED_MODULE_1__ =
+        __webpack_require__(2783);
+      /* harmony import */ var next_link__WEBPACK_IMPORTED_MODULE_1___default =
+        /*#__PURE__*/ __webpack_require__.n(
+          next_link__WEBPACK_IMPORTED_MODULE_1__
+        );
+
+      function aLink(props) {
+        return /*#__PURE__*/ (0,
+        react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)("div", {
+          children: [
+            /*#__PURE__*/ (0,
+            react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("h3", {
+              children: "A Link page!",
+            }),
+            /*#__PURE__*/ (0,
+            react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(
+              next_link__WEBPACK_IMPORTED_MODULE_1___default(),
+              {
+                href: "/",
+                children: "Go to /",
+              }
+            ),
+          ],
+        });
+      }
+      var __N_SSP = true;
+      /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = aLink;
+
+      /***/
+    },
+
+    /***/ 5926: /***/ (module, exports, __webpack_require__) => {
       "use strict";
       /* __next_internal_client_entry_do_not_use__  cjs */
       Object.defineProperty(exports, "__esModule", {
@@ -164,17 +103,17 @@
       const _react = /*#__PURE__*/ _interop_require_wildcard._(
         __webpack_require__(5977)
       );
-      const _resolvehref = __webpack_require__(224);
-      const _islocalurl = __webpack_require__(7746);
-      const _formaturl = __webpack_require__(315);
-      const _utils = __webpack_require__(8709);
-      const _addlocale = __webpack_require__(6358);
-      const _routercontextsharedruntime = __webpack_require__(4095);
-      const _useintersection = __webpack_require__(1585);
-      const _getdomainlocale = __webpack_require__(8802);
-      const _addbasepath = __webpack_require__(6151);
-      const _usemergedref = __webpack_require__(9100);
-      const _erroronce = __webpack_require__(9574);
+      const _resolvehref = __webpack_require__(6708);
+      const _islocalurl = __webpack_require__(6526);
+      const _formaturl = __webpack_require__(5575);
+      const _utils = __webpack_require__(3497);
+      const _addlocale = __webpack_require__(722);
+      const _routercontextsharedruntime = __webpack_require__(1235);
+      const _useintersection = __webpack_require__(8069);
+      const _getdomainlocale = __webpack_require__(9734);
+      const _addbasepath = __webpack_require__(4419);
+      const _usemergedref = __webpack_require__(6136);
+      const _erroronce = __webpack_require__(2346);
       const prefetched = new Set();
       function prefetch(router, href, as, options) {
         if (false) {
@@ -563,43 +502,7 @@
       /***/
     },
 
-    /***/ 8802: /***/ (module, exports, __webpack_require__) => {
-      "use strict";
-
-      Object.defineProperty(exports, "__esModule", {
-        value: true,
-      });
-      Object.defineProperty(exports, "getDomainLocale", {
-        enumerable: true,
-        get: function () {
-          return getDomainLocale;
-        },
-      });
-      const _normalizetrailingslash = __webpack_require__(1652);
-      const basePath =
-        /* unused pure expression or super */ null && (false || "");
-      function getDomainLocale(path, locale, locales, domainLocales) {
-        if (false) {
-        } else {
-          return false;
-        }
-      }
-      if (
-        (typeof exports.default === "function" ||
-          (typeof exports.default === "object" && exports.default !== null)) &&
-        typeof exports.default.__esModule === "undefined"
-      ) {
-        Object.defineProperty(exports.default, "__esModule", {
-          value: true,
-        });
-        Object.assign(exports.default, exports);
-        module.exports = exports.default;
-      } //# sourceMappingURL=get-domain-locale.js.map
-
-      /***/
-    },
-
-    /***/ 9100: /***/ (module, exports, __webpack_require__) => {
+    /***/ 6136: /***/ (module, exports, __webpack_require__) => {
       "use strict";
 
       Object.defineProperty(exports, "__esModule", {
@@ -677,26 +580,7 @@
       /***/
     },
 
-    /***/ 9574: /***/ (__unused_webpack_module, exports) => {
-      "use strict";
-
-      Object.defineProperty(exports, "__esModule", {
-        value: true,
-      });
-      Object.defineProperty(exports, "errorOnce", {
-        enumerable: true,
-        get: function () {
-          return errorOnce;
-        },
-      });
-      let errorOnce = (_) => {};
-      if (false) {
-      } //# sourceMappingURL=error-once.js.map
-
-      /***/
-    },
-
-    /***/ 9693: /***/ (
+    /***/ 7047: /***/ (
       __unused_webpack_module,
       __unused_webpack_exports,
       __webpack_require__
@@ -704,7 +588,7 @@
       (window.__NEXT_P = window.__NEXT_P || []).push([
         "/link",
         function () {
-          return __webpack_require__(9948);
+          return __webpack_require__(4174);
         },
       ]);
       if (false) {
@@ -713,48 +597,164 @@
       /***/
     },
 
-    /***/ 9948: /***/ (
-      __unused_webpack_module,
-      __webpack_exports__,
-      __webpack_require__
-    ) => {
+    /***/ 8069: /***/ (module, exports, __webpack_require__) => {
       "use strict";
-      __webpack_require__.r(__webpack_exports__);
-      /* harmony export */ __webpack_require__.d(__webpack_exports__, {
-        /* harmony export */ __N_SSP: () => /* binding */ __N_SSP,
-        /* harmony export */ default: () => __WEBPACK_DEFAULT_EXPORT__,
-        /* harmony export */
+
+      Object.defineProperty(exports, "__esModule", {
+        value: true,
       });
-      /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
-        __webpack_require__(7765);
-      /* harmony import */ var next_link__WEBPACK_IMPORTED_MODULE_1__ =
-        __webpack_require__(2621);
-      /* harmony import */ var next_link__WEBPACK_IMPORTED_MODULE_1___default =
-        /*#__PURE__*/ __webpack_require__.n(
-          next_link__WEBPACK_IMPORTED_MODULE_1__
+      Object.defineProperty(exports, "useIntersection", {
+        enumerable: true,
+        get: function () {
+          return useIntersection;
+        },
+      });
+      const _react = __webpack_require__(5977);
+      const _requestidlecallback = __webpack_require__(3432);
+      const hasIntersectionObserver =
+        typeof IntersectionObserver === "function";
+      const observers = new Map();
+      const idList = [];
+      function createObserver(options) {
+        const id = {
+          root: options.root || null,
+          margin: options.rootMargin || "",
+        };
+        const existing = idList.find(
+          (obj) => obj.root === id.root && obj.margin === id.margin
         );
-
-      function aLink(props) {
-        return /*#__PURE__*/ (0,
-        react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)("div", {
-          children: [
-            /*#__PURE__*/ (0,
-            react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("h3", {
-              children: "A Link page!",
-            }),
-            /*#__PURE__*/ (0,
-            react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(
-              next_link__WEBPACK_IMPORTED_MODULE_1___default(),
-              {
-                href: "/",
-                children: "Go to /",
-              }
-            ),
-          ],
+        let instance;
+        if (existing) {
+          instance = observers.get(existing);
+          if (instance) {
+            return instance;
+          }
+        }
+        const elements = new Map();
+        const observer = new IntersectionObserver((entries) => {
+          entries.forEach((entry) => {
+            const callback = elements.get(entry.target);
+            const isVisible =
+              entry.isIntersecting || entry.intersectionRatio > 0;
+            if (callback && isVisible) {
+              callback(isVisible);
+            }
+          });
+        }, options);
+        instance = {
+          id,
+          observer,
+          elements,
+        };
+        idList.push(id);
+        observers.set(id, instance);
+        return instance;
+      }
+      function observe(element, callback, options) {
+        const { id, observer, elements } = createObserver(options);
+        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);
+            const index = idList.findIndex(
+              (obj) => obj.root === id.root && obj.margin === id.margin
+            );
+            if (index > -1) {
+              idList.splice(index, 1);
+            }
+          }
+        };
+      }
+      function useIntersection(param) {
+        let { rootRef, rootMargin, disabled } = param;
+        const isDisabled = disabled || !hasIntersectionObserver;
+        const [visible, setVisible] = (0, _react.useState)(false);
+        const elementRef = (0, _react.useRef)(null);
+        const setElement = (0, _react.useCallback)((element) => {
+          elementRef.current = element;
+        }, []);
+        (0, _react.useEffect)(() => {
+          if (hasIntersectionObserver) {
+            if (isDisabled || visible) return;
+            const element = elementRef.current;
+            if (element && element.tagName) {
+              const unobserve = observe(
+                element,
+                (isVisible) => isVisible && setVisible(isVisible),
+                {
+                  root: rootRef == null ? void 0 : rootRef.current,
+                  rootMargin,
+                }
+              );
+              return unobserve;
+            }
+          } else {
+            if (!visible) {
+              const idleCallback = (0,
+              _requestidlecallback.requestIdleCallback)(() => setVisible(true));
+              return () =>
+                (0, _requestidlecallback.cancelIdleCallback)(idleCallback);
+            }
+          }
+          // eslint-disable-next-line react-hooks/exhaustive-deps
+        }, [isDisabled, rootMargin, rootRef, visible, elementRef.current]);
+        const resetVisible = (0, _react.useCallback)(() => {
+          setVisible(false);
+        }, []);
+        return [setElement, visible, resetVisible];
+      }
+      if (
+        (typeof exports.default === "function" ||
+          (typeof exports.default === "object" && exports.default !== null)) &&
+        typeof exports.default.__esModule === "undefined"
+      ) {
+        Object.defineProperty(exports.default, "__esModule", {
+          value: true,
         });
+        Object.assign(exports.default, exports);
+        module.exports = exports.default;
+      } //# sourceMappingURL=use-intersection.js.map
+
+      /***/
+    },
+
+    /***/ 9734: /***/ (module, exports, __webpack_require__) => {
+      "use strict";
+
+      Object.defineProperty(exports, "__esModule", {
+        value: true,
+      });
+      Object.defineProperty(exports, "getDomainLocale", {
+        enumerable: true,
+        get: function () {
+          return getDomainLocale;
+        },
+      });
+      const _normalizetrailingslash = __webpack_require__(504);
+      const basePath =
+        /* unused pure expression or super */ null && (false || "");
+      function getDomainLocale(path, locale, locales, domainLocales) {
+        if (false) {
+        } else {
+          return false;
+        }
       }
-      var __N_SSP = true;
-      /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = aLink;
+      if (
+        (typeof exports.default === "function" ||
+          (typeof exports.default === "object" && exports.default !== null)) &&
+        typeof exports.default.__esModule === "undefined"
+      ) {
+        Object.defineProperty(exports.default, "__esModule", {
+          value: true,
+        });
+        Object.assign(exports.default, exports);
+        module.exports = exports.default;
+      } //# sourceMappingURL=get-domain-locale.js.map
 
       /***/
     },
@@ -764,7 +764,7 @@
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(9693)
+      __webpack_exec__(7047)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for script-HASH.js
@@ -1,7 +1,34 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [1209],
   {
-    /***/ 3699: /***/ (
+    /***/ 1008: /***/ (
+      module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      module.exports = __webpack_require__(2817);
+
+      /***/
+    },
+
+    /***/ 6951: /***/ (
+      __unused_webpack_module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      (window.__NEXT_P = window.__NEXT_P || []).push([
+        "/script",
+        function () {
+          return __webpack_require__(8889);
+        },
+      ]);
+      if (false) {
+      }
+
+      /***/
+    },
+
+    /***/ 8889: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -16,7 +43,7 @@
       /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
         __webpack_require__(7765);
       /* harmony import */ var next_script__WEBPACK_IMPORTED_MODULE_1__ =
-        __webpack_require__(4802);
+        __webpack_require__(1008);
       /* harmony import */ var next_script__WEBPACK_IMPORTED_MODULE_1___default =
         /*#__PURE__*/ __webpack_require__.n(
           next_script__WEBPACK_IMPORTED_MODULE_1__
@@ -48,40 +75,13 @@
 
       /***/
     },
-
-    /***/ 4802: /***/ (
-      module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      module.exports = __webpack_require__(8661);
-
-      /***/
-    },
-
-    /***/ 7861: /***/ (
-      __unused_webpack_module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      (window.__NEXT_P = window.__NEXT_P || []).push([
-        "/script",
-        function () {
-          return __webpack_require__(3699);
-        },
-      ]);
-      if (false) {
-      }
-
-      /***/
-    },
   },
   /******/ (__webpack_require__) => {
     // webpackRuntimeModules
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(7861)
+      __webpack_exec__(6951)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for 8863-HASH.js
@@ -1,8 +1,33 @@
 "use strict";
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
-  [8863],
+  [7009],
   {
-    /***/ 22: /***/ (module, exports, __webpack_require__) => {
+    /***/ 414: /***/ (
+      __unused_webpack_module,
+      exports,
+      __webpack_require__
+    ) => {
+      Object.defineProperty(exports, "__esModule", {
+        value: true,
+      });
+      Object.defineProperty(exports, "AmpStateContext", {
+        enumerable: true,
+        get: function () {
+          return AmpStateContext;
+        },
+      });
+      const _interop_require_default = __webpack_require__(2726);
+      const _react = /*#__PURE__*/ _interop_require_default._(
+        __webpack_require__(2224)
+      );
+      const AmpStateContext = _react.default.createContext({});
+      if (false) {
+      } //# sourceMappingURL=amp-context.shared-runtime.js.map
+
+      /***/
+    },
+
+    /***/ 1912: /***/ (module, exports, __webpack_require__) => {
       Object.defineProperty(exports, "__esModule", {
         value: true,
       });
@@ -12,7 +37,7 @@
           return useMergedRef;
         },
       });
-      const _react = __webpack_require__(2786);
+      const _react = __webpack_require__(2224);
       function useMergedRef(refA, refB) {
         const cleanupA = (0, _react.useRef)(null);
         const cleanupB = (0, _react.useRef)(null);
@@ -78,56 +103,99 @@
       /***/
     },
 
-    /***/ 936: /***/ (__unused_webpack_module, exports) => {
+    /***/ 2843: /***/ (
+      __unused_webpack_module,
+      exports,
+      __webpack_require__
+    ) => {
       Object.defineProperty(exports, "__esModule", {
         value: true,
       });
-      0 && 0;
-      function _export(target, all) {
-        for (var name in all)
-          Object.defineProperty(target, name, {
-            enumerable: true,
-            get: all[name],
-          });
-      }
-      _export(exports, {
-        VALID_LOADERS: function () {
-          return VALID_LOADERS;
+      Object.defineProperty(exports, "RouterContext", {
+        enumerable: true,
+        get: function () {
+          return RouterContext;
         },
-        imageConfigDefault: function () {
-          return imageConfigDefault;
+      });
+      const _interop_require_default = __webpack_require__(2726);
+      const _react = /*#__PURE__*/ _interop_require_default._(
+        __webpack_require__(2224)
+      );
+      const RouterContext = _react.default.createContext(null);
+      if (false) {
+      } //# sourceMappingURL=router-context.shared-runtime.js.map
+
+      /***/
+    },
+
+    /***/ 3003: /***/ (__unused_webpack_module, exports) => {
+      Object.defineProperty(exports, "__esModule", {
+        value: true,
+      });
+      Object.defineProperty(exports, "default", {
+        enumerable: true,
+        get: function () {
+          return _default;
         },
       });
-      const VALID_LOADERS = [
-        "default",
-        "imgix",
-        "cloudinary",
-        "akamai",
-        "custom",
-      ];
-      const imageConfigDefault = {
-        deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
-        imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
-        path: "/_next/image",
-        loader: "default",
-        loaderFile: "",
-        domains: [],
-        disableStaticImages: false,
-        minimumCacheTTL: 60,
-        formats: ["image/webp"],
-        dangerouslyAllowSVG: false,
-        contentSecurityPolicy: "script-src 'none'; frame-src 'none'; sandbox;",
-        contentDispositionType: "attachment",
-        localPatterns: undefined,
-        remotePatterns: [],
-        qualities: undefined,
-        unoptimized: false,
-      }; //# sourceMappingURL=image-config.js.map
+      const DEFAULT_Q = 75;
+      function defaultLoader(param) {
+        let { config, src, width, quality } = param;
+        var _config_qualities;
+        if (false) {
+        }
+        const q =
+          quality ||
+          ((_config_qualities = config.qualities) == null
+            ? void 0
+            : _config_qualities.reduce((prev, cur) =>
+                Math.abs(cur - DEFAULT_Q) < Math.abs(prev - DEFAULT_Q)
+                  ? cur
+                  : prev
+              )) ||
+          DEFAULT_Q;
+        return (
+          config.path +
+          "?url=" +
+          encodeURIComponent(src) +
+          "&w=" +
+          width +
+          "&q=" +
+          q +
+          (src.startsWith("/_next/static/media/") && false ? 0 : "")
+        );
+      }
+      // We use this to determine if the import is the default loader
+      // or a custom loader defined by the user in next.config.js
+      defaultLoader.__next_img_default = true;
+      const _default = defaultLoader; //# sourceMappingURL=image-loader.js.map
 
       /***/
     },
 
-    /***/ 1268: /***/ (__unused_webpack_module, exports) => {
+    /***/ 3810: /***/ (__unused_webpack_module, exports) => {
+      Object.defineProperty(exports, "__esModule", {
+        value: true,
+      });
+      Object.defineProperty(exports, "isInAmpMode", {
+        enumerable: true,
+        get: function () {
+          return isInAmpMode;
+        },
+      });
+      function isInAmpMode(param) {
+        let {
+          ampFirst = false,
+          hybrid = false,
+          hasQuery = false,
+        } = param === void 0 ? {} : param;
+        return ampFirst || (hybrid && hasQuery);
+      } //# sourceMappingURL=amp-mode.js.map
+
+      /***/
+    },
+
+    /***/ 5218: /***/ (__unused_webpack_module, exports) => {
       /**
        * A shared function, used on both client and server, to generate a SVG blur placeholder.
        */
@@ -181,7 +249,7 @@
       /***/
     },
 
-    /***/ 1796: /***/ (module, exports, __webpack_require__) => {
+    /***/ 5402: /***/ (module, exports, __webpack_require__) => {
       /* __next_internal_client_entry_do_not_use__  cjs */
       Object.defineProperty(exports, "__esModule", {
         value: true,
@@ -202,19 +270,19 @@
           return defaultHead;
         },
       });
-      const _interop_require_default = __webpack_require__(8182);
-      const _interop_require_wildcard = __webpack_require__(8319);
-      const _jsxruntime = __webpack_require__(1050);
+      const _interop_require_default = __webpack_require__(2726);
+      const _interop_require_wildcard = __webpack_require__(2527);
+      const _jsxruntime = __webpack_require__(8204);
       const _react = /*#__PURE__*/ _interop_require_wildcard._(
-        __webpack_require__(2786)
+        __webpack_require__(2224)
       );
       const _sideeffect = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(5581)
+        __webpack_require__(9319)
       );
-      const _ampcontextsharedruntime = __webpack_require__(3800);
-      const _headmanagercontextsharedruntime = __webpack_require__(4950);
-      const _ampmode = __webpack_require__(7824);
-      const _warnonce = __webpack_require__(2854);
+      const _ampcontextsharedruntime = __webpack_require__(414);
+      const _headmanagercontextsharedruntime = __webpack_require__(3100);
+      const _ampmode = __webpack_require__(3810);
+      const _warnonce = __webpack_require__(4504);
       function defaultHead(inAmpMode) {
         if (inAmpMode === void 0) inAmpMode = false;
         const head = [
@@ -379,7 +447,7 @@
       /***/
     },
 
-    /***/ 2843: /***/ (
+    /***/ 6745: /***/ (
       __unused_webpack_module,
       exports,
       __webpack_require__
@@ -393,9 +461,9 @@
           return getImgProps;
         },
       });
-      const _warnonce = __webpack_require__(2854);
-      const _imageblursvg = __webpack_require__(1268);
-      const _imageconfig = __webpack_require__(936);
+      const _warnonce = __webpack_require__(4504);
+      const _imageblursvg = __webpack_require__(5218);
+      const _imageconfig = __webpack_require__(9278);
       const VALID_LOADING_VALUES =
         /* unused pure expression or super */ null && [
           "lazy",
@@ -822,245 +890,7 @@
       /***/
     },
 
-    /***/ 3800: /***/ (
-      __unused_webpack_module,
-      exports,
-      __webpack_require__
-    ) => {
-      Object.defineProperty(exports, "__esModule", {
-        value: true,
-      });
-      Object.defineProperty(exports, "AmpStateContext", {
-        enumerable: true,
-        get: function () {
-          return AmpStateContext;
-        },
-      });
-      const _interop_require_default = __webpack_require__(8182);
-      const _react = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(2786)
-      );
-      const AmpStateContext = _react.default.createContext({});
-      if (false) {
-      } //# sourceMappingURL=amp-context.shared-runtime.js.map
-
-      /***/
-    },
-
-    /***/ 5581: /***/ (
-      __unused_webpack_module,
-      exports,
-      __webpack_require__
-    ) => {
-      Object.defineProperty(exports, "__esModule", {
-        value: true,
-      });
-      Object.defineProperty(exports, "default", {
-        enumerable: true,
-        get: function () {
-          return SideEffect;
-        },
-      });
-      const _react = __webpack_require__(2786);
-      const isServer = "object" === "undefined";
-      const useClientOnlyLayoutEffect = isServer
-        ? () => {}
-        : _react.useLayoutEffect;
-      const useClientOnlyEffect = isServer ? () => {} : _react.useEffect;
-      function SideEffect(props) {
-        const { headManager, reduceComponentsToState } = props;
-        function emitChange() {
-          if (headManager && headManager.mountedInstances) {
-            const headElements = _react.Children.toArray(
-              Array.from(headManager.mountedInstances).filter(Boolean)
-            );
-            headManager.updateHead(
-              reduceComponentsToState(headElements, props)
-            );
-          }
-        }
-        if (isServer) {
-          var _headManager_mountedInstances;
-          headManager == null
-            ? void 0
-            : (_headManager_mountedInstances = headManager.mountedInstances) ==
-              null
-            ? void 0
-            : _headManager_mountedInstances.add(props.children);
-          emitChange();
-        }
-        useClientOnlyLayoutEffect(() => {
-          var _headManager_mountedInstances;
-          headManager == null
-            ? void 0
-            : (_headManager_mountedInstances = headManager.mountedInstances) ==
-              null
-            ? void 0
-            : _headManager_mountedInstances.add(props.children);
-          return () => {
-            var _headManager_mountedInstances;
-            headManager == null
-              ? void 0
-              : (_headManager_mountedInstances =
-                  headManager.mountedInstances) == null
-              ? void 0
-              : _headManager_mountedInstances.delete(props.children);
-          };
-        });
-        // We need to call `updateHead` method whenever the `SideEffect` is trigger in all
-        // life-cycles: mount, update, unmount. However, if there are multiple `SideEffect`s
-        // being rendered, we only trigger the method from the last one.
-        // This is ensured by keeping the last unflushed `updateHead` in the `_pendingUpdate`
-        // singleton in the layout effect pass, and actually trigger it in the effect pass.
-        useClientOnlyLayoutEffect(() => {
-          if (headManager) {
-            headManager._pendingUpdate = emitChange;
-          }
-          return () => {
-            if (headManager) {
-              headManager._pendingUpdate = emitChange;
-            }
-          };
-        });
-        useClientOnlyEffect(() => {
-          if (headManager && headManager._pendingUpdate) {
-            headManager._pendingUpdate();
-            headManager._pendingUpdate = null;
-          }
-          return () => {
-            if (headManager && headManager._pendingUpdate) {
-              headManager._pendingUpdate();
-              headManager._pendingUpdate = null;
-            }
-          };
-        });
-        return null;
-      } //# sourceMappingURL=side-effect.js.map
-
-      /***/
-    },
-
-    /***/ 7053: /***/ (
-      __unused_webpack_module,
-      exports,
-      __webpack_require__
-    ) => {
-      Object.defineProperty(exports, "__esModule", {
-        value: true,
-      });
-      Object.defineProperty(exports, "RouterContext", {
-        enumerable: true,
-        get: function () {
-          return RouterContext;
-        },
-      });
-      const _interop_require_default = __webpack_require__(8182);
-      const _react = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(2786)
-      );
-      const RouterContext = _react.default.createContext(null);
-      if (false) {
-      } //# sourceMappingURL=router-context.shared-runtime.js.map
-
-      /***/
-    },
-
-    /***/ 7281: /***/ (__unused_webpack_module, exports) => {
-      Object.defineProperty(exports, "__esModule", {
-        value: true,
-      });
-      Object.defineProperty(exports, "default", {
-        enumerable: true,
-        get: function () {
-          return _default;
-        },
-      });
-      const DEFAULT_Q = 75;
-      function defaultLoader(param) {
-        let { config, src, width, quality } = param;
-        var _config_qualities;
-        if (false) {
-        }
-        const q =
-          quality ||
-          ((_config_qualities = config.qualities) == null
-            ? void 0
-            : _config_qualities.reduce((prev, cur) =>
-                Math.abs(cur - DEFAULT_Q) < Math.abs(prev - DEFAULT_Q)
-                  ? cur
-                  : prev
-              )) ||
-          DEFAULT_Q;
-        return (
-          config.path +
-          "?url=" +
-          encodeURIComponent(src) +
-          "&w=" +
-          width +
-          "&q=" +
-          q +
-          (src.startsWith("/_next/static/media/") && false ? 0 : "")
-        );
-      }
-      // We use this to determine if the import is the default loader
-      // or a custom loader defined by the user in next.config.js
-      defaultLoader.__next_img_default = true;
-      const _default = defaultLoader; //# sourceMappingURL=image-loader.js.map
-
-      /***/
-    },
-
-    /***/ 7480: /***/ (
-      __unused_webpack_module,
-      exports,
-      __webpack_require__
-    ) => {
-      Object.defineProperty(exports, "__esModule", {
-        value: true,
-      });
-      Object.defineProperty(exports, "ImageConfigContext", {
-        enumerable: true,
-        get: function () {
-          return ImageConfigContext;
-        },
-      });
-      const _interop_require_default = __webpack_require__(8182);
-      const _react = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(2786)
-      );
-      const _imageconfig = __webpack_require__(936);
-      const ImageConfigContext = _react.default.createContext(
-        _imageconfig.imageConfigDefault
-      );
-      if (false) {
-      } //# sourceMappingURL=image-config-context.shared-runtime.js.map
-
-      /***/
-    },
-
-    /***/ 7824: /***/ (__unused_webpack_module, exports) => {
-      Object.defineProperty(exports, "__esModule", {
-        value: true,
-      });
-      Object.defineProperty(exports, "isInAmpMode", {
-        enumerable: true,
-        get: function () {
-          return isInAmpMode;
-        },
-      });
-      function isInAmpMode(param) {
-        let {
-          ampFirst = false,
-          hybrid = false,
-          hasQuery = false,
-        } = param === void 0 ? {} : param;
-        return ampFirst || (hybrid && hasQuery);
-      } //# sourceMappingURL=amp-mode.js.map
-
-      /***/
-    },
-
-    /***/ 8863: /***/ (module, exports, __webpack_require__) => {
+    /***/ 7009: /***/ (module, exports, __webpack_require__) => {
       /* __next_internal_client_entry_do_not_use__  cjs */
       Object.defineProperty(exports, "__esModule", {
         value: true,
@@ -1071,27 +901,27 @@
           return Image;
         },
       });
-      const _interop_require_default = __webpack_require__(8182);
-      const _interop_require_wildcard = __webpack_require__(8319);
-      const _jsxruntime = __webpack_require__(1050);
+      const _interop_require_default = __webpack_require__(2726);
+      const _interop_require_wildcard = __webpack_require__(2527);
+      const _jsxruntime = __webpack_require__(8204);
       const _react = /*#__PURE__*/ _interop_require_wildcard._(
-        __webpack_require__(2786)
+        __webpack_require__(2224)
       );
       const _reactdom = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(1407)
+        __webpack_require__(1345)
       );
       const _head = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(1796)
+        __webpack_require__(5402)
       );
-      const _getimgprops = __webpack_require__(2843);
-      const _imageconfig = __webpack_require__(936);
-      const _imageconfigcontextsharedruntime = __webpack_require__(7480);
-      const _warnonce = __webpack_require__(2854);
-      const _routercontextsharedruntime = __webpack_require__(7053);
+      const _getimgprops = __webpack_require__(6745);
+      const _imageconfig = __webpack_require__(9278);
+      const _imageconfigcontextsharedruntime = __webpack_require__(9690);
+      const _warnonce = __webpack_require__(4504);
+      const _routercontextsharedruntime = __webpack_require__(2843);
       const _imageloader = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(7281)
+        __webpack_require__(3003)
       );
-      const _usemergedref = __webpack_require__(22);
+      const _usemergedref = __webpack_require__(1912);
       // This is replaced by webpack define plugin
       const configEnv = {
         deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
@@ -1416,5 +1246,175 @@
 
       /***/
     },
+
+    /***/ 9278: /***/ (__unused_webpack_module, exports) => {
+      Object.defineProperty(exports, "__esModule", {
+        value: true,
+      });
+      0 && 0;
+      function _export(target, all) {
+        for (var name in all)
+          Object.defineProperty(target, name, {
+            enumerable: true,
+            get: all[name],
+          });
+      }
+      _export(exports, {
+        VALID_LOADERS: function () {
+          return VALID_LOADERS;
+        },
+        imageConfigDefault: function () {
+          return imageConfigDefault;
+        },
+      });
+      const VALID_LOADERS = [
+        "default",
+        "imgix",
+        "cloudinary",
+        "akamai",
+        "custom",
+      ];
+      const imageConfigDefault = {
+        deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
+        imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
+        path: "/_next/image",
+        loader: "default",
+        loaderFile: "",
+        domains: [],
+        disableStaticImages: false,
+        minimumCacheTTL: 60,
+        formats: ["image/webp"],
+        dangerouslyAllowSVG: false,
+        contentSecurityPolicy: "script-src 'none'; frame-src 'none'; sandbox;",
+        contentDispositionType: "attachment",
+        localPatterns: undefined,
+        remotePatterns: [],
+        qualities: undefined,
+        unoptimized: false,
+      }; //# sourceMappingURL=image-config.js.map
+
+      /***/
+    },
+
+    /***/ 9319: /***/ (
+      __unused_webpack_module,
+      exports,
+      __webpack_require__
+    ) => {
+      Object.defineProperty(exports, "__esModule", {
+        value: true,
+      });
+      Object.defineProperty(exports, "default", {
+        enumerable: true,
+        get: function () {
+          return SideEffect;
+        },
+      });
+      const _react = __webpack_require__(2224);
+      const isServer = "object" === "undefined";
+      const useClientOnlyLayoutEffect = isServer
+        ? () => {}
+        : _react.useLayoutEffect;
+      const useClientOnlyEffect = isServer ? () => {} : _react.useEffect;
+      function SideEffect(props) {
+        const { headManager, reduceComponentsToState } = props;
+        function emitChange() {
+          if (headManager && headManager.mountedInstances) {
+            const headElements = _react.Children.toArray(
+              Array.from(headManager.mountedInstances).filter(Boolean)
+            );
+            headManager.updateHead(
+              reduceComponentsToState(headElements, props)
+            );
+          }
+        }
+        if (isServer) {
+          var _headManager_mountedInstances;
+          headManager == null
+            ? void 0
+            : (_headManager_mountedInstances = headManager.mountedInstances) ==
+              null
+            ? void 0
+            : _headManager_mountedInstances.add(props.children);
+          emitChange();
+        }
+        useClientOnlyLayoutEffect(() => {
+          var _headManager_mountedInstances;
+          headManager == null
+            ? void 0
+            : (_headManager_mountedInstances = headManager.mountedInstances) ==
+              null
+            ? void 0
+            : _headManager_mountedInstances.add(props.children);
+          return () => {
+            var _headManager_mountedInstances;
+            headManager == null
+              ? void 0
+              : (_headManager_mountedInstances =
+                  headManager.mountedInstances) == null
+              ? void 0
+              : _headManager_mountedInstances.delete(props.children);
+          };
+        });
+        // We need to call `updateHead` method whenever the `SideEffect` is trigger in all
+        // life-cycles: mount, update, unmount. However, if there are multiple `SideEffect`s
+        // being rendered, we only trigger the method from the last one.
+        // This is ensured by keeping the last unflushed `updateHead` in the `_pendingUpdate`
+        // singleton in the layout effect pass, and actually trigger it in the effect pass.
+        useClientOnlyLayoutEffect(() => {
+          if (headManager) {
+            headManager._pendingUpdate = emitChange;
+          }
+          return () => {
+            if (headManager) {
+              headManager._pendingUpdate = emitChange;
+            }
+          };
+        });
+        useClientOnlyEffect(() => {
+          if (headManager && headManager._pendingUpdate) {
+            headManager._pendingUpdate();
+            headManager._pendingUpdate = null;
+          }
+          return () => {
+            if (headManager && headManager._pendingUpdate) {
+              headManager._pendingUpdate();
+              headManager._pendingUpdate = null;
+            }
+          };
+        });
+        return null;
+      } //# sourceMappingURL=side-effect.js.map
+
+      /***/
+    },
+
+    /***/ 9690: /***/ (
+      __unused_webpack_module,
+      exports,
+      __webpack_require__
+    ) => {
+      Object.defineProperty(exports, "__esModule", {
+        value: true,
+      });
+      Object.defineProperty(exports, "ImageConfigContext", {
+        enumerable: true,
+        get: function () {
+          return ImageConfigContext;
+        },
+      });
+      const _interop_require_default = __webpack_require__(2726);
+      const _react = /*#__PURE__*/ _interop_require_default._(
+        __webpack_require__(2224)
+      );
+      const _imageconfig = __webpack_require__(9278);
+      const ImageConfigContext = _react.default.createContext(
+        _imageconfig.imageConfigDefault
+      );
+      if (false) {
+      } //# sourceMappingURL=image-config-context.shared-runtime.js.map
+
+      /***/
+    },
   },
 ]);
Diff for 9304-HASH.js

Diff too large to display

Diff for main-HASH.js

Diff too large to display

Diff for main-app-HASH.js
@@ -1,64 +1,64 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [4977],
   {
-    /***/ 3228: /***/ () => {
-      /* (ignored) */
-      /***/
-    },
-
-    /***/ 5783: /***/ (
+    /***/ 627: /***/ (
       __unused_webpack_module,
       __unused_webpack_exports,
       __webpack_require__
     ) => {
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 2374, 23)
+        __webpack_require__.t.bind(__webpack_require__, 2816, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 2673, 23)
+        __webpack_require__.t.bind(__webpack_require__, 3319, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 4710, 23)
+        __webpack_require__.t.bind(__webpack_require__, 3564, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 9138, 23)
+        __webpack_require__.t.bind(__webpack_require__, 4932, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 9207, 23)
+        __webpack_require__.t.bind(__webpack_require__, 4549, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 4379, 23)
+        __webpack_require__.t.bind(__webpack_require__, 3877, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 631, 23)
+        __webpack_require__.t.bind(__webpack_require__, 6769, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 6231, 23)
+        __webpack_require__.t.bind(__webpack_require__, 5521, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 4706, 23)
+        __webpack_require__.t.bind(__webpack_require__, 9520, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 7121, 23)
+        __webpack_require__.t.bind(__webpack_require__, 5947, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 6594, 23)
+        __webpack_require__.t.bind(__webpack_require__, 1720, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.bind(__webpack_require__, 2231)
+        __webpack_require__.bind(__webpack_require__, 977)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 9683, 23)
+        __webpack_require__.t.bind(__webpack_require__, 7569, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 174, 23)
+        __webpack_require__.t.bind(__webpack_require__, 1504, 23)
       );
       Promise.resolve(/* import() eager */).then(
-        __webpack_require__.t.bind(__webpack_require__, 3496, 23)
+        __webpack_require__.t.bind(__webpack_require__, 4186, 23)
       );
 
       /***/
     },
+
+    /***/ 3550: /***/ () => {
+      /* (ignored) */
+      /***/
+    },
   },
   /******/ (__webpack_require__) => {
     // webpackRuntimeModules
@@ -66,8 +66,8 @@
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(
       0,
-      [5862, 9304],
-      () => (__webpack_exec__(7007), __webpack_exec__(5783))
+      [3008, 2426],
+      () => (__webpack_exec__(6401), __webpack_exec__(627))
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Commit: 8fb7166

@bgub bgub requested review from feedthejim and ijjk July 16, 2025 21:24
@karlhorky
Copy link
Contributor

karlhorky commented Jul 17, 2025

  • Backwards compatibility - all existing href usage unchanged

@bgub To be clear, I'm assuming this means href props become *untyped* with experimental.typedRoutes, right?

Reading the PR description and changes, I'm assuming that the current experimental.typedRoutes functionality of providing TS type errors on simple href strings like the ones below will be removed, correct?

// Current experimental.typedRoutes functionality

// ✅
<Link href="/about" />

// ❌ Type '"/aboot"' is not assignable to type ...
<Link href="/aboot" />

// ✅
<Link href="/projects/${slug}" />

// ❌ Type '`/projectsss/${string}`' is not assignable to type ...
<Link href="/projectsss/${slug}" />

// ✅
<Link href="/projects/${projectSlug}/tasks/${taskSlug}" />

// ❌ Type '`/projectsss/${string}`/tasks/${string}' is not assignable to type ...
<Link href="/projectsss/${projectSlug}/tasks/${taskSlug}" />

As far as I can tell, the new version would be like this:

// New experimental.typedRoutes functionality

// ✅
<Link path="/about" />

// ❌ Type '"/aboot"' is not assignable to type ...
<Link path="/aboot" />

// ✅
<Link path="/projects/[slug]" params={{ slug: slug }} />

// ❌ Type '`/projectsss/${string}`' is not assignable to type ...
<Link path="/projectsss/[slug]" params={{ slug: slug }} />

// ✅
<Link path="/projects/[projectSlug]/tasks/[taskSlug]" params={{
  projectSlug: projectSlug,
  taskSlug: taskSlug,
}} />

// ❌ Type '`/projectsss/${string}`/tasks/${string}' is not assignable to type ...
<Link path="/projectsss/[projectSlug]/tasks/[taskSlug]" params={{
  projectSlug: projectSlug,
  taskSlug: taskSlug,
}} />

The new API makes things much more verbose and complex 🤔 Even with using object shorthand notation:

<Link path="/projects/[projectSlug]/tasks/[taskSlug]" params={{ projectSlug, taskSlug }} />

Single href strings are really great for learning and ergonomics, too bad if we would have to lose them.

@controversial
Copy link
Contributor

controversial commented Jul 17, 2025

Yes, I believe that’s correct @karlhorky

there’s definitely some benefit in making the route you want to link to be “explicit” (similar to the old as prop from Next <10)

but I’m curious too about the reason for removing the old typedRoutes behavior; I was also fond of the old behavior where href strings were type checked to match valid route patterns. It always worked well in my experience and the generated types didn’t seem excessively complex to me

@bgub bgub force-pushed the feat/typed-links branch from 2cce6b3 to e5bff32 Compare July 21, 2025 23:41
@bgub bgub force-pushed the feat/typed-routes-new branch from cfb2e87 to 793b67e Compare July 21, 2025 23:41
@bgub bgub changed the title feat: initial typed links support feat: Turbopack typed links + new Link props Jul 22, 2025
@bgub
Copy link
Contributor Author

bgub commented Jul 22, 2025

@karlhorky @controversial thanks for the feedback! I've updated the PR so that the href prop remains typed.

@bgub bgub force-pushed the feat/typed-links branch from 42d87c0 to 5c18c3c Compare July 22, 2025 04:50
@bgub bgub marked this pull request as ready for review July 22, 2025 04:56
Copy link
Member

@lubieowoce lubieowoce left a comment

Choose a reason for hiding this comment

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

I don't see any tests that actually check if typescript rejects invalid <Link href>, router.push, or <Form action>.
We used to have pretty comprehensive tests for this in
test/integration/app-types/src/app/type-checks/, which you're removing in #81396. I think we should just adapt the existing tests to work here instead of getting rid of them wholesale

@bgub bgub force-pushed the feat/typed-links branch from 903ec2d to b32d59f Compare July 23, 2025 21:31
@bgub bgub force-pushed the feat/typed-routes-new branch from d0cab0c to 723c4c2 Compare July 23, 2025 21:31
@bgub bgub force-pushed the feat/typed-links branch from b32d59f to a17f6c3 Compare July 23, 2025 21:36
@bgub bgub changed the base branch from feat/typed-routes-new to graphite-base/81528 August 1, 2025 22:26
@bgub bgub force-pushed the graphite-base/81528 branch from cf60561 to 4528d99 Compare August 1, 2025 22:40
@bgub bgub force-pushed the feat/typed-links branch from fe46a63 to 0334145 Compare August 1, 2025 22:40
@bgub bgub changed the base branch from graphite-base/81528 to feat/typed-routes-new August 1, 2025 22:40
@bgub bgub changed the base branch from feat/typed-routes-new to graphite-base/81528 August 2, 2025 00:01
@bgub bgub force-pushed the graphite-base/81528 branch from 4528d99 to deec259 Compare August 2, 2025 00:19
@bgub bgub force-pushed the feat/typed-links branch from 0334145 to 61706a8 Compare August 2, 2025 00:19
@bgub bgub changed the base branch from graphite-base/81528 to feat/typed-routes-new August 2, 2025 00:20
Base automatically changed from feat/typed-routes-new to canary August 2, 2025 01:06
@bgub bgub force-pushed the feat/typed-links branch from 61706a8 to 96aad91 Compare August 2, 2025 01:11
@bgub bgub force-pushed the feat/typed-links branch from 96aad91 to 9919edd Compare August 2, 2025 06:49
Copy link
Contributor Author

bgub commented Aug 2, 2025

@lubieowoce: good point, I restored the app/type-checks tests and made sure they were passing. This actually led to me finding a few bugs too (well, implementation differences from Shu's version).

@eps1lon: it works with next typegen, which we merged as part of #81396 🚀

@bgub
Copy link
Contributor Author

bgub commented Aug 2, 2025

I just went through and polished these changes. A few differences since the last version:

  • Squashed commits
  • We now generate a separate .next/types/link.d.ts file (since routes.d.ts contains an export type statement, which causes TS to not treat it strictly as an ambient type declaration file, so type augmenting was breaking)
  • Switched over to mirror @shuding's original parsing of path-to-regexp strings. This brings more reliability + keeps behavior the same as the previous experimental.typedRoutes implementation, at the cost of optional parameters like :slug? not working anymore (which imo is a good thing since we don't have optional dynamic single segments in Next.js anyways).

@bgub bgub force-pushed the feat/typed-links branch from 9919edd to ec67a97 Compare August 2, 2025 07:10
@bgub bgub force-pushed the feat/typed-links branch 2 times, most recently from d14a06d to b7f64a4 Compare August 12, 2025 07:22
@bgub bgub force-pushed the feat/typed-links branch from b7f64a4 to 8fb7166 Compare August 12, 2025 17:02
@ijjk ijjk enabled auto-merge (squash) August 12, 2025 17:25
@ijjk ijjk merged commit 1faf032 into canary Aug 12, 2025
177 of 178 checks passed
@ijjk ijjk deleted the feat/typed-links branch August 12, 2025 17:28
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 27, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants