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

Dynamic APIs #60645

Merged
merged 4 commits into from
Jan 24, 2024
Merged

Dynamic APIs #60645

merged 4 commits into from
Jan 24, 2024

Conversation

gnoff
Copy link
Contributor

@gnoff gnoff commented Jan 14, 2024

formalizes the concept of dynamic APIs inside Next to allow for varying semantics beyond just staticGenerationBailout.

Dynamic APIs

markCurrentScopeAsDynamic

useful to bail out of default caching semantics but does not imply a Request specific data source was read. critically, this semantic is ignored if you are inside a cache scope

trackDynamicDataAccessed

Must be called before reading any data source that is derived from Request specific data. Currently this is cookies(), headers(), and searchParams. This kind of data access inside a cache scope is forbidden (it always should have been, but now it will error).

trackDynamicFetch

This one is unideal but the complexity of patch-fetch's current implementation necessitates it for now. Essentially it will postpone if we are prerendering. Long term this should be eliminated with a refactor of patch fetch.

Other Improvements

Also removes the staticGenerationBailout implementation as it has been replaced with more specific logic in the places it was previously being used.

One area that has also been enhanced is the proxy for app-route modules. Previously we proxied the Request every time however when we are doing non-static generation executions we generally don't want the overhead of wrapping the request. In the refactor here I also improved the runtime performance by using static proxy handlers and I believe I also fixed a few bugs related to clone and url

In general there has been a bit of refactoring to clarify how we should handle various render/execution states and a reduction in implicit side effects for proper execution.

Another callout to notice is that app-route modules do not attempt a static generation if they are force-dynamic regardless of the PPR setting. Previously the PPR setting would opt them into this code path which is not necessary because PPR itself does not work for routes, only pages.

Closes NEXT-2099

@ijjk
Copy link
Member

ijjk commented Jan 14, 2024

Tests Passed

@ijjk
Copy link
Member

ijjk commented Jan 14, 2024

Stats from current PR

Default Build (Increase detected ⚠️)
General
vercel/next.js canary gnoff/next.js dynamic-apis Change
buildDuration 13.6s 13.5s N/A
buildDurationCached 7.2s 6.2s N/A
nodeModulesSize 200 MB 200 MB N/A
nextStartRea..uration (ms) 445ms 461ms N/A
Client Bundles (main, webpack) Overall increase ⚠️
vercel/next.js canary gnoff/next.js dynamic-apis Change
193.HASH.js gzip 181 B 182 B N/A
3f784ff6-HASH.js gzip 53.4 kB 53.4 kB
433-HASH.js gzip 29 kB 29.8 kB ⚠️ +832 B
framework-HASH.js gzip 45.2 kB 45.2 kB
main-app-HASH.js gzip 239 B 242 B N/A
main-HASH.js gzip 31.8 kB 31.8 kB N/A
webpack-HASH.js gzip 1.7 kB 1.7 kB N/A
Overall change 128 kB 128 kB ⚠️ +832 B
Legacy Client Bundles (polyfills)
vercel/next.js canary gnoff/next.js dynamic-apis Change
polyfills-HASH.js gzip 31 kB 31 kB
Overall change 31 kB 31 kB
Client Pages
vercel/next.js canary gnoff/next.js dynamic-apis Change
_app-HASH.js gzip 194 B 195 B N/A
_error-HASH.js gzip 183 B 181 B N/A
amp-HASH.js gzip 504 B 502 B N/A
css-HASH.js gzip 321 B 321 B
dynamic-HASH.js gzip 2.5 kB 2.5 kB N/A
edge-ssr-HASH.js gzip 255 B 253 B N/A
head-HASH.js gzip 350 B 349 B N/A
hooks-HASH.js gzip 369 B 369 B
image-HASH.js gzip 4.18 kB 4.18 kB N/A
index-HASH.js gzip 255 B 256 B N/A
link-HASH.js gzip 2.61 kB 2.61 kB N/A
routerDirect..HASH.js gzip 312 B 311 B N/A
script-HASH.js gzip 385 B 383 B N/A
withRouter-HASH.js gzip 307 B 308 B N/A
1afbb74e6ecf..834.css gzip 106 B 106 B
Overall change 796 B 796 B
Client Build Manifests
vercel/next.js canary gnoff/next.js dynamic-apis Change
_buildManifest.js gzip 484 B 486 B N/A
Overall change 0 B 0 B
Rendered Page Sizes
vercel/next.js canary gnoff/next.js dynamic-apis Change
index.html gzip 528 B 525 B N/A
link.html gzip 540 B 538 B N/A
withRouter.html gzip 524 B 522 B N/A
Overall change 0 B 0 B
Edge SSR bundle Size Overall increase ⚠️
vercel/next.js canary gnoff/next.js dynamic-apis Change
edge-ssr.js gzip 94 kB 94 kB N/A
page.js gzip 149 kB 149 kB ⚠️ +803 B
Overall change 149 kB 149 kB ⚠️ +803 B
Middleware size
vercel/next.js canary gnoff/next.js dynamic-apis Change
middleware-b..fest.js gzip 625 B 626 B N/A
middleware-r..fest.js gzip 151 B 151 B
middleware.js gzip 37.5 kB 37.6 kB N/A
edge-runtime..pack.js gzip 1.92 kB 1.92 kB
Overall change 2.07 kB 2.07 kB
Next Runtimes
vercel/next.js canary gnoff/next.js dynamic-apis Change
app-page-exp...dev.js gzip 169 kB 170 kB N/A
app-page-exp..prod.js gzip 95.6 kB 95.6 kB N/A
app-page-tur..prod.js gzip 96.3 kB 96.3 kB N/A
app-page-tur..prod.js gzip 90.9 kB 90.9 kB N/A
app-page.run...dev.js gzip 142 kB 142 kB N/A
app-page.run..prod.js gzip 90.2 kB 90.2 kB N/A
app-route-ex...dev.js gzip 24.2 kB 22.2 kB N/A
app-route-ex..prod.js gzip 16.9 kB 14.9 kB N/A
app-route-tu..prod.js gzip 16.9 kB 14.9 kB N/A
app-route-tu..prod.js gzip 16.4 kB 14.5 kB N/A
app-route.ru...dev.js gzip 23.6 kB 21.6 kB N/A
app-route.ru..prod.js gzip 16.4 kB 14.5 kB N/A
pages-api-tu..prod.js gzip 9.41 kB 9.41 kB
pages-api.ru...dev.js gzip 9.68 kB 9.68 kB
pages-api.ru..prod.js gzip 9.4 kB 9.4 kB
pages-turbo...prod.js gzip 22 kB 22 kB
pages.runtim...dev.js gzip 22.6 kB 22.6 kB
pages.runtim..prod.js gzip 22 kB 22 kB
server.runti..prod.js gzip 49.7 kB 49.7 kB
Overall change 145 kB 145 kB
Diff details
Diff for page.js

Diff too large to display

Diff for middleware.js
@@ -16,7 +16,7 @@
       /***/
     },
 
-    /***/ 1356: /***/ (
+    /***/ 7591: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -35,7 +35,7 @@
       __webpack_require__.r(middleware_namespaceObject);
       __webpack_require__.d(middleware_namespaceObject, {
         default: () => middleware,
-      }); // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/globals.js
+      }); // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/globals.js
 
       async function registerInstrumentation() {
         if (
@@ -105,7 +105,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
         // Eagerly fire instrumentation hook to make the startup faster.
         void ensureInstrumentationRegistered();
       }
-      enhanceGlobals(); //# sourceMappingURL=globals.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/error.js
+      enhanceGlobals(); //# sourceMappingURL=globals.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/error.js
 
       class PageSignatureError extends Error {
         constructor({ page }) {
@@ -132,7 +132,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
   Read more: https://nextjs.org/docs/messages/middleware-parse-user-agent
   `);
         }
-      } //# sourceMappingURL=error.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/utils.js
+      } //# sourceMappingURL=error.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/utils.js
 
       /**
        * Converts a Node.js IncomingHttpHeaders object to a Headers object. Any
@@ -267,7 +267,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
             }
           );
         }
-      } //# sourceMappingURL=utils.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/spec-extension/fetch-event.js
+      } //# sourceMappingURL=utils.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/spec-extension/fetch-event.js
 
       const responseSymbol = Symbol("response");
       const passThroughSymbol = Symbol("passThrough");
@@ -313,7 +313,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
             page: this.sourcePage,
           });
         }
-      } //# sourceMappingURL=fetch-event.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/i18n/detect-domain-locale.js
+      } //# sourceMappingURL=fetch-event.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/i18n/detect-domain-locale.js
 
       function detectDomainLocale(domainItems, hostname, detectedLocale) {
         if (!domainItems) return;
@@ -339,7 +339,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
             return item;
           }
         }
-      } //# sourceMappingURL=detect-domain-locale.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/router/utils/remove-trailing-slash.js
+      } //# sourceMappingURL=detect-domain-locale.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/router/utils/remove-trailing-slash.js
 
       /**
        * Removes the trailing slash for a given route or page path. Preserves the
@@ -349,7 +349,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
        *   - `/` -> `/`
        */ function removeTrailingSlash(route) {
         return route.replace(/\/$/, "") || "/";
-      } //# sourceMappingURL=remove-trailing-slash.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/router/utils/parse-path.js
+      } //# sourceMappingURL=remove-trailing-slash.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/router/utils/parse-path.js
 
       /**
        * Given a path this function will find the pathname, query and hash and return
@@ -377,7 +377,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
           query: "",
           hash: "",
         };
-      } //# sourceMappingURL=parse-path.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/router/utils/add-path-prefix.js
+      } //# sourceMappingURL=parse-path.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/router/utils/add-path-prefix.js
 
       /**
        * Adds the provided prefix to the given path. It first ensures that the path
@@ -388,7 +388,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
         }
         const { pathname, query, hash } = parsePath(path);
         return "" + prefix + pathname + query + hash;
-      } //# sourceMappingURL=add-path-prefix.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/router/utils/add-path-suffix.js
+      } //# sourceMappingURL=add-path-prefix.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/router/utils/add-path-suffix.js
 
       /**
        * Similarly to `addPathPrefix`, this function adds a suffix at the end on the
@@ -400,7 +400,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
         }
         const { pathname, query, hash } = parsePath(path);
         return "" + pathname + suffix + query + hash;
-      } //# sourceMappingURL=add-path-suffix.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/router/utils/path-has-prefix.js
+      } //# sourceMappingURL=add-path-suffix.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/router/utils/path-has-prefix.js
 
       /**
        * Checks if a given path starts with a given prefix. It ensures it matches
@@ -414,7 +414,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
         }
         const { pathname } = parsePath(path);
         return pathname === prefix || pathname.startsWith(prefix + "/");
-      } //# sourceMappingURL=path-has-prefix.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/router/utils/add-locale.js
+      } //# sourceMappingURL=path-has-prefix.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/router/utils/add-locale.js
 
       /**
        * For a given path and a locale, if the locale is given, it will prefix the
@@ -433,7 +433,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
         }
         // Add the locale prefix to the path.
         return addPathPrefix(path, "/" + locale);
-      } //# sourceMappingURL=add-locale.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/router/utils/format-next-pathname-info.js
+      } //# sourceMappingURL=add-locale.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/router/utils/format-next-pathname-info.js
 
       function formatNextPathnameInfo(info) {
         let pathname = addLocale(
@@ -457,7 +457,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
             ? addPathSuffix(pathname, "/")
             : pathname
           : removeTrailingSlash(pathname);
-      } //# sourceMappingURL=format-next-pathname-info.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/get-hostname.js
+      } //# sourceMappingURL=format-next-pathname-info.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/get-hostname.js
 
       /**
        * Takes an object with a hostname property (like a parsed URL) and some
@@ -477,7 +477,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
           hostname = parsed.hostname;
         } else return;
         return hostname.toLowerCase();
-      } //# sourceMappingURL=get-hostname.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/i18n/normalize-locale-path.js
+      } //# sourceMappingURL=get-hostname.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/i18n/normalize-locale-path.js
 
       /**
        * For a pathname that may include a locale from a list of locales, it
@@ -507,7 +507,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
           pathname,
           detectedLocale,
         };
-      } //# sourceMappingURL=normalize-locale-path.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/router/utils/remove-path-prefix.js
+      } //# sourceMappingURL=normalize-locale-path.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/router/utils/remove-path-prefix.js
 
       /**
        * Given a path and a prefix it will remove the prefix when it exists in the
@@ -541,7 +541,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
         // If the path without the prefix doesn't start with a `/` we need to add it
         // back to the path to make sure it's a valid path.
         return "/" + withoutPrefix;
-      } //# sourceMappingURL=remove-path-prefix.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/router/utils/get-next-pathname-info.js
+      } //# sourceMappingURL=remove-path-prefix.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/router/utils/get-next-pathname-info.js
 
       function getNextPathnameInfo(pathname, options) {
         var _options_nextConfig;
@@ -599,7 +599,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
           }
         }
         return info;
-      } //# sourceMappingURL=get-next-pathname-info.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/next-url.js
+      } //# sourceMappingURL=get-next-pathname-info.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/next-url.js
 
       const REGEX_LOCALHOST_HOSTNAME =
         /(?!^https?:\/\/)(127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}|\[::1\]|localhost)/;
@@ -826,8 +826,8 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
         }
       } //# sourceMappingURL=next-url.js.map
 
-      // EXTERNAL MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/compiled/@edge-runtime/cookies/index.js
-      var _edge_runtime_cookies = __webpack_require__(7220); // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/spec-extension/cookies.js // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/spec-extension/request.js
+      // EXTERNAL MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/compiled/@edge-runtime/cookies/index.js
+      var _edge_runtime_cookies = __webpack_require__(2738); // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/spec-extension/cookies.js // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/spec-extension/request.js
       //# sourceMappingURL=cookies.js.map
 
       const INTERNALS = Symbol("internal request");
@@ -904,7 +904,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
         get url() {
           return this[INTERNALS].url;
         }
-      } //# sourceMappingURL=request.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/spec-extension/response.js
+      } //# sourceMappingURL=request.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/spec-extension/response.js
 
       const response_INTERNALS = Symbol("internal response");
       const REDIRECTS = new Set([301, 302, 303, 307, 308]);
@@ -1002,7 +1002,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
             headers,
           });
         }
-      } //# sourceMappingURL=response.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/router/utils/relativize-url.js
+      } //# sourceMappingURL=response.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/router/utils/relativize-url.js
 
       /**
        * Given a URL as a string and a base URL it will make the URL relative
@@ -1015,7 +1015,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
         return relative.protocol + "//" + relative.host === origin
           ? relative.toString().replace(origin, "")
           : relative.toString();
-      } //# sourceMappingURL=relativize-url.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/client/components/app-router-headers.js
+      } //# sourceMappingURL=relativize-url.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/client/components/app-router-headers.js
 
       const RSC_HEADER = "RSC";
       const ACTION = "Next-Action";
@@ -1039,8 +1039,8 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
       const NEXT_RSC_UNION_QUERY = "_rsc";
       const NEXT_DID_POSTPONE_HEADER = "x-nextjs-postponed"; //# sourceMappingURL=app-router-headers.js.map
 
-      // EXTERNAL MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/modern-browserslist-target.js
-      var modern_browserslist_target = __webpack_require__(8739); // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/constants.js
+      // EXTERNAL MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/modern-browserslist-target.js
+      var modern_browserslist_target = __webpack_require__(3297); // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/constants.js
       const COMPILER_NAMES = {
         client: "client",
         server: "server",
@@ -1193,7 +1193,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
         CLIENT_STATIC_FILES_RUNTIME_REACT_REFRESH,
         CLIENT_STATIC_FILES_RUNTIME_AMP,
         CLIENT_STATIC_FILES_RUNTIME_MAIN_APP,
-      ]); //# sourceMappingURL=constants.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/internal-utils.js
+      ]); //# sourceMappingURL=constants.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/internal-utils.js
 
       const INTERNAL_QUERY_NAMES = [
         "__nextFallback",
@@ -1230,7 +1230,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
         for (const key of INTERNAL_HEADERS) {
           delete headers[key];
         }
-      } //# sourceMappingURL=internal-utils.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/router/utils/app-paths.js
+      } //# sourceMappingURL=internal-utils.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/shared/lib/router/utils/app-paths.js
 
       /**
        * Normalizes an app route so it represents the actual request path. Essentially
@@ -1281,7 +1281,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
        * Since this function is used on full urls it checks `?` for searchParams handling.
        */ function normalizeRscURL(url) {
         return url.replace(/\.rsc($|\?)/, "$1");
-      } //# sourceMappingURL=app-paths.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/lib/constants.js
+      } //# sourceMappingURL=app-paths.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/lib/constants.js
 
       const NEXT_QUERY_PARAM_PREFIX = "nxtP";
       const PRERENDER_REVALIDATE_HEADER = "x-prerender-revalidate";
@@ -1453,7 +1453,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
         metadata: "__next_metadata__",
         metadataRoute: "__next_metadata_route__",
         metadataImageMeta: "__next_metadata_image_meta__",
-      }; // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/spec-extension/adapters/reflect.js
+      }; // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/spec-extension/adapters/reflect.js
       //# sourceMappingURL=constants.js.map
 
       class ReflectAdapter {
@@ -1473,7 +1473,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
         static deleteProperty(target, prop) {
           return Reflect.deleteProperty(target, prop);
         }
-      } //# sourceMappingURL=reflect.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/spec-extension/adapters/headers.js
+      } //# sourceMappingURL=reflect.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/spec-extension/adapters/headers.js
 
       /**
        * @internal
@@ -1654,7 +1654,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
         [Symbol.iterator]() {
           return this.entries();
         }
-      } //# sourceMappingURL=headers.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/spec-extension/adapters/request-cookies.js
+      } //# sourceMappingURL=headers.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/spec-extension/adapters/request-cookies.js
 
       /**
        * @internal
@@ -1787,7 +1787,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
             },
           });
         }
-      } //# sourceMappingURL=request-cookies.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/api-utils/index.js
+      } //# sourceMappingURL=request-cookies.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/api-utils/index.js
 
       /**
        *
@@ -1842,7 +1842,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
         if (SYMBOL_CLEARED_COOKIES in res) {
           return res;
         }
-        const { serialize } = __webpack_require__(2792);
+        const { serialize } = __webpack_require__(6664);
         const previous = res.getHeader("Set-Cookie");
         res.setHeader(`Set-Cookie`, [
           ...(typeof previous === "string"
@@ -1939,7 +1939,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
             });
           },
         });
-      } //# sourceMappingURL=index.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/async-storage/draft-mode-provider.js
+      } //# sourceMappingURL=index.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/async-storage/draft-mode-provider.js
 
       class DraftModeProvider {
         constructor(previewProps, req, cookies, mutableCookies) {
@@ -1992,7 +1992,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
             expires: new Date(0),
           });
         }
-      } //# sourceMappingURL=draft-mode-provider.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/async-storage/request-async-storage-wrapper.js
+      } //# sourceMappingURL=draft-mode-provider.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/async-storage/request-async-storage-wrapper.js
 
       function getHeaders(headers) {
         const cleaned = HeadersAdapter.from(headers);
@@ -2077,10 +2077,21 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
         },
       }; //# sourceMappingURL=request-async-storage-wrapper.js.map
 
-      // EXTERNAL MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/client/components/async-local-storage.js
-      var async_local_storage = __webpack_require__(7987); // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/client/components/request-async-storage.external.js
+      // EXTERNAL MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/client/components/async-local-storage.js
+      var async_local_storage = __webpack_require__(7564); // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/client/components/request-async-storage.external.js
       const requestAsyncStorage = (0,
-      async_local_storage /* createAsyncLocalStorage */.P)(); //# sourceMappingURL=request-async-storage.external.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/lib/trace/constants.js
+      async_local_storage /* createAsyncLocalStorage */.P)();
+      function getExpectedRequestStore(callingExpression) {
+        const store = requestAsyncStorage.getStore();
+        if (!store) {
+          throw new Error(
+            "Invariant: `" +
+              callingExpression +
+              "` expects to have requestAsyncStorage, none available."
+          );
+        }
+        return store;
+      } //# sourceMappingURL=request-async-storage.external.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/lib/trace/constants.js
 
       /**
        * Contains predefined constants for the trace span name in next/server.
@@ -2218,7 +2229,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
         "NextNodeServer.createComponentTree",
         "NextNodeServer.findPageComponents",
         "NextNodeServer.getLayoutOrPageModule",
-      ]; // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/lib/trace/tracer.js
+      ]; // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/lib/trace/tracer.js
       //# sourceMappingURL=constants.js.map
 
       let api;
@@ -2230,7 +2241,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
       // the version that is bundled with Next.js.
       // the API is ~stable, so this should be fine
       if (true) {
-        api = __webpack_require__(7932);
+        api = __webpack_require__(3084);
       } else {
       }
       const {
@@ -2442,7 +2453,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
       const getTracer = (() => {
         const tracer = new NextTracerImpl();
         return () => tracer;
-      })(); // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/adapter.js
+      })(); // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/adapter.js
       //# sourceMappingURL=tracer.js.map
 
       class NextRequestHint extends NextRequest {
@@ -2480,7 +2491,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
           testApisIntercepted = true;
           if (process.env.NEXT_PRIVATE_TEST_PROXY === "true") {
             const { interceptTestApis, wrapRequestHandler } =
-              __webpack_require__(1146);
+              __webpack_require__(7089);
             interceptTestApis();
             propagator = wrapRequestHandler(propagator);
           }
@@ -2724,14 +2735,14 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
           waitUntil: Promise.all(event[waitUntilSymbol]),
           fetchMetrics: request.fetchMetrics,
         };
-      } //# sourceMappingURL=adapter.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/exports/next-response.js // CONCATENATED MODULE: ./middleware.js
+      } //# sourceMappingURL=adapter.js.map // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/esm/server/web/exports/next-response.js // CONCATENATED MODULE: ./middleware.js
 
       // This file is for modularized imports for next/server to get fully-treeshaking.
       //# sourceMappingURL=next-response.js.map
 
       async function middleware() {
         return NextResponse.next();
-      } // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+main-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/build/webpack/loaders/next-middleware-loader.js?absolutePagePath=private-next-root-dir%2Fmiddleware.js&page=%2Fmiddleware&rootDir=%2Ftmp%2Fnext-statsix5S3p%2Fstats-app&matchers=&preferredRegion=&middlewareConfig=e30%3D!
+      } // CONCATENATED MODULE: ./node_modules/.pnpm/file+..+diff-repo+packages+next+next-packed.tgz_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/build/webpack/loaders/next-middleware-loader.js?absolutePagePath=private-next-root-dir%2Fmiddleware.js&page=%2Fmiddleware&rootDir=%2Ftmp%2Fnext-statsix5S3p%2Fstats-app&matchers=&preferredRegion=&middlewareConfig=e30%3D!
 
       // Import the userland code.
 
@@ -2758,7 +2769,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
       /***/
     },
 
-    /***/ 7220: /***/ (module) => {
+    /***/ 2738: /***/ (module) => {
       "use strict";
 
       var __defProp = Object.defineProperty;
@@ -3179,7 +3190,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
       /***/
     },
 
-    /***/ 7932: /***/ (
+    /***/ 3084: /***/ (
       module,
       __unused_webpack_exports,
       __webpack_require__
@@ -4818,7 +4829,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
       /***/
     },
 
-    /***/ 2792: /***/ (module) => {
+    /***/ 6664: /***/ (module) => {
       "use strict";
       var __dirname = "/";
 
@@ -4948,7 +4959,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
       /***/
     },
 
-    /***/ 8739: /***/ (module) => {
+    /***/ 3297: /***/ (module) => {
       "use strict";
       // Note: This file is JS because it's used by the taskfile-swc.js file, which is JS.
       // Keep file changes in sync with the corresponding `.d.ts` files.
@@ -4970,7 +4981,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
       /***/
     },
 
-    /***/ 3896: /***/ (
+    /***/ 592: /***/ (
       __unused_webpack_module,
       exports,
       __webpack_require__
@@ -5033,7 +5044,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
       /***/
     },
 
-    /***/ 1254: /***/ (
+    /***/ 8689: /***/ (
       __unused_webpack_module,
       exports,
       __webpack_require__
@@ -5064,7 +5075,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
           return interceptFetch;
         },
       });
-      const _context = __webpack_require__(3896);
+      const _context = __webpack_require__(592);
       const reader = {
         url(req) {
           return req.url;
@@ -5193,7 +5204,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
       /***/
     },
 
-    /***/ 1146: /***/ (
+    /***/ 7089: /***/ (
       __unused_webpack_module,
       exports,
       __webpack_require__
@@ -5219,8 +5230,8 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
           return wrapRequestHandler;
         },
       });
-      const _context = __webpack_require__(3896);
-      const _fetch = __webpack_require__(1254);
+      const _context = __webpack_require__(592);
+      const _fetch = __webpack_require__(8689);
       function interceptTestApis() {
         return (0, _fetch.interceptFetch)(__webpack_require__.g.fetch);
       }
@@ -5232,7 +5243,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
       /***/
     },
 
-    /***/ 7987: /***/ (
+    /***/ 7564: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -5278,7 +5289,7 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`;
     // webpackRuntimeModules
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
-    /******/ var __webpack_exports__ = __webpack_exec__(1356);
+    /******/ var __webpack_exports__ = __webpack_exec__(7591);
     /******/ (_ENTRIES =
       typeof _ENTRIES === "undefined" ? {} : _ENTRIES).middleware_middleware =
       __webpack_exports__;
Diff for edge-ssr.js

Diff too large to display

Diff for 433-HASH.js

Diff too large to display

Diff for app-page-exp..ntime.dev.js

Diff too large to display

Diff for app-page-exp..time.prod.js

Diff too large to display

Diff for app-page-tur..time.prod.js

Diff too large to display

Diff for app-page-tur..time.prod.js

Diff too large to display

Diff for app-page.runtime.dev.js

Diff too large to display

Diff for app-page.runtime.prod.js

Diff too large to display

Diff for app-route-ex..ntime.dev.js

Diff too large to display

Diff for app-route-ex..time.prod.js

Diff too large to display

Diff for app-route-tu..time.prod.js

Diff too large to display

Diff for app-route-tu..time.prod.js

Diff too large to display

Diff for app-route.runtime.dev.js

Diff too large to display

Diff for app-route.ru..time.prod.js

Diff too large to display

Commit: 2324e67

@gnoff gnoff force-pushed the dynamic-apis branch 11 times, most recently from 94b2abf to bc0ce4f Compare January 18, 2024 01:48
* rendering during the React render phase. This should not be invoked outside
* of the React render phase as it'll throw an error.
*/
readonly postpone: ((reason: string) => never) | undefined
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Generally we want to avoid these methods of passing code around. Even our ComponentMod technique for exposing RSC scoped functions is really not ideal. In the rewrite to dynamic APIs references to React's postpone API are referenced directly from the modules that need them (transitively through dynamic-rendering.ts). Crucially this allows the postpone to be the "right" one for RSC vs SSR whereas in the previous implementaiton we were using the RSC postpone to postpone in SSR in some cases (this happens to work by accident of the implementation but by no means guaranteed)

Comment on lines -737 to -741
const providedSearchParams = isStaticGeneration
? createSearchParamsBailoutProxy()
: query

const searchParamsProps = { searchParams: providedSearchParams }
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We move this as close to where it is used as possible. see createDynamicallyTrackedSearchParams for how this is done now

// if called within a next/cache call, we want to cache the result
// and defer to the next/cache call to handle how to cache the result.
const callingExpression = 'unstable_noStore()'
const store = getExpectedStaticGenerationStore(callingExpression)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is maybe wrong b/c calling this inside a route handler is maybe ok? (a noop) cc @wyattjoh

@gnoff gnoff marked this pull request as ready for review January 18, 2024 02:00
@gnoff gnoff changed the title Dynamic apis Dynamic APIs Jan 18, 2024
@gnoff gnoff force-pushed the dynamic-apis branch 2 times, most recently from bc3ed54 to fabf4ea Compare January 18, 2024 16:11
@gnoff gnoff requested review from a team as code owners January 18, 2024 16:14
@gnoff gnoff requested review from jh3y and lydiahallie and removed request for a team January 18, 2024 16:14
@@ -58,9 +58,6 @@ export const staticGenerationBailout: StaticGenerationBailout = (
link: 'https://nextjs.org/docs/messages/dynamic-server-error',
})

// If postpone is available, we should postpone the render.
staticGenerationStore.postpone?.(reason)
Copy link
Member

Choose a reason for hiding this comment

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

PPR depends on this being available and firing, is this called elsewhere?

Copy link
Member

@ztanner ztanner Jan 22, 2024

Choose a reason for hiding this comment

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

I think this is now more explicitly invoked in the new dynamic helpers like trackDynamicDataAccessed

packages/next/src/lib/metadata/resolve-metadata.ts Outdated Show resolved Hide resolved
packages/next/src/server/app-render/rsc/postpone.ts Outdated Show resolved Hide resolved
packages/next/src/server/lib/patch-fetch.ts Show resolved Hide resolved
test/e2e/app-dir/dynamic-data/dynamic-data.test.ts Outdated Show resolved Hide resolved
Copy link
Member

@ztanner ztanner left a comment

Choose a reason for hiding this comment

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

👏 👏

Most of my comments are just copyediting. I found the new store flags quite a bit easier to reason about behaviors.

packages/next/src/client/components/headers.ts Outdated Show resolved Hide resolved
packages/next/src/client/components/headers.ts Outdated Show resolved Hide resolved
packages/next/src/client/components/search-params.ts Outdated Show resolved Hide resolved
if (typeof prop === 'string') {
trackDynamicDataAccessed(store, `searchParams.${prop}`)
}
return ReflectAdapter.get(target, prop, receiver)
Copy link
Member

Choose a reason for hiding this comment

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

Is there a reason we use ReflectAdapter here but Reflect in has and ownKeys?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm it's a style choice. ReflectAdapter requires me to understand what ReflectAdapter is and why it is being used etc.... If I added ReflectAdapter for all the Reflect methods it adds some cognative overhead to later understanding of this code. The fact that only get has special handling in the Adapter to me is a sign that we should probably make a lint rule for binding function types in get traps and just drop the namespaced class.

If I implemented all of Reflect in ReflectAdapter for completeness sake then we'd be shipping more code and in some cases an extra function call that isn't optimized away for the appearence of abstraction (the ReflectAdapter is going to take care of things). If our goal is to make sure you don't forget something critical I'd prefer linting since there is no runtime overhead and the code will just real plainly showing what it does

packages/next/src/server/app-render/app-render.tsx Outdated Show resolved Hide resolved
test/e2e/app-dir/dynamic-data/dynamic-data.test.ts Outdated Show resolved Hide resolved
test/e2e/app-dir/dynamic-data/dynamic-data.test.ts Outdated Show resolved Hide resolved
test/e2e/app-dir/dynamic-data/dynamic-data.test.ts Outdated Show resolved Hide resolved
test/e2e/app-dir/dynamic-data/dynamic-data.test.ts Outdated Show resolved Hide resolved
test/e2e/app-dir/dynamic-data/dynamic-data.test.ts Outdated Show resolved Hide resolved
…Previously this was talked about externally in Docs but implemented as a staticGenerationBailout. There are however different semantics we want to have for dynamic using htings like `unstable_noStore` vs `headers()` for instance and having APIs oriented around these semantics will make future planned changes easier to implement correctly.

The two main semantics are "the currently executing scope should be dynamic" and "some dynamic data source is being read"

The former will eventually be a noop if we make dynamic the default. In accordance with this the dynamic intent is ignored inside a cache scope from `unstable_cache`. This is a very weak form of dynamic scoping and makes sense because it does not entail a request specific data read.

The latter semantic is a stronger form. when doing any kind of static generation we disallow reading dynamic data sources such as headers, cookies, and searchParams. If these are read during a static render the render will bailout or postpone (depending on whether we are using PPR or not)

force-static should still forcibly prevent dynamic data reads. This is now implementation outside of the triggering of a dynamic data read.

This PR does not actually change yet how we define whether the result of a render was fully, partially, or not static. This will come in a follow up change where we can more faithfully track whether dynamic APIs were used separately from whether the render postpones.
@gnoff gnoff force-pushed the dynamic-apis branch 4 times, most recently from d61b0d6 to a3f8df2 Compare January 23, 2024 16:55
… to other dynamic apis and bailout techniques
@gnoff gnoff merged commit b5772b8 into vercel:canary Jan 24, 2024
68 checks passed
@gnoff gnoff deleted the dynamic-apis branch January 24, 2024 00:06
@github-actions github-actions bot added the locked label Feb 7, 2024
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 7, 2024
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.

None yet

4 participants