@vercel/next 4.5.0 → 4.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +201 -19
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -820,17 +820,29 @@ var require_superstatic = __commonJS({
820
820
  convertRewrites: () => convertRewrites2,
821
821
  convertTrailingSlash: () => convertTrailingSlash,
822
822
  getCleanUrls: () => getCleanUrls,
823
+ pathToRegexp: () => pathToRegexp,
823
824
  sourceToRegex: () => sourceToRegex
824
825
  });
825
826
  module2.exports = __toCommonJS2(superstatic_exports);
826
827
  var import_url4 = require("url");
827
828
  var import_path_to_regexp = require_dist();
828
829
  var import_path_to_regexp_updated = require_dist2();
830
+ function cloneKeys(keys) {
831
+ if (typeof keys === "undefined") {
832
+ return void 0;
833
+ }
834
+ return keys.slice(0);
835
+ }
836
+ function compareKeys(left, right) {
837
+ const leftSerialized = typeof left === "undefined" ? "undefined" : left.toString();
838
+ const rightSerialized = typeof right === "undefined" ? "undefined" : right.toString();
839
+ return leftSerialized === rightSerialized;
840
+ }
829
841
  function pathToRegexp(callerId, path5, keys, options) {
842
+ const newKeys = cloneKeys(keys);
830
843
  const currentRegExp = (0, import_path_to_regexp.pathToRegexp)(path5, keys, options);
831
844
  try {
832
845
  const currentKeys = keys;
833
- const newKeys = [];
834
846
  const newRegExp = (0, import_path_to_regexp_updated.pathToRegexp)(path5, newKeys, options);
835
847
  const isDiffRegExp = currentRegExp.toString() !== newRegExp.toString();
836
848
  if (process.env.FORCE_PATH_TO_REGEXP_LOG || isDiffRegExp) {
@@ -841,7 +853,7 @@ var require_superstatic = __commonJS({
841
853
  });
842
854
  console.error(`[vc] PATH TO REGEXP PATH DIFF @ #${callerId}: ${message}`);
843
855
  }
844
- const isDiffKeys = keys?.toString() !== newKeys?.toString();
856
+ const isDiffKeys = !compareKeys(keys, newKeys);
845
857
  if (process.env.FORCE_PATH_TO_REGEXP_LOG || isDiffKeys) {
846
858
  const message = JSON.stringify({
847
859
  isDiffKeys,
@@ -852,7 +864,11 @@ var require_superstatic = __commonJS({
852
864
  }
853
865
  } catch (err) {
854
866
  const error = err;
855
- console.error(`[vc] PATH TO REGEXP ERROR @ #${callerId}: ${error.message}`);
867
+ const message = JSON.stringify({
868
+ path: path5,
869
+ error: error.message
870
+ });
871
+ console.error(`[vc] PATH TO REGEXP ERROR @ #${callerId}: ${message}`);
856
872
  }
857
873
  return currentRegExp;
858
874
  }
@@ -11107,7 +11123,8 @@ async function getDynamicRoutes({
11107
11123
  bypassToken,
11108
11124
  isServerMode,
11109
11125
  dynamicMiddlewareRouteMap,
11110
- isAppPPREnabled
11126
+ isAppPPREnabled,
11127
+ isAppClientSegmentCacheEnabled
11111
11128
  }) {
11112
11129
  if (routesManifest) {
11113
11130
  switch (routesManifest.version) {
@@ -11140,7 +11157,13 @@ async function getDynamicRoutes({
11140
11157
  routes2.push(route2);
11141
11158
  continue;
11142
11159
  }
11143
- const { page, namedRegex, regex, routeKeys } = params;
11160
+ const {
11161
+ page,
11162
+ namedRegex,
11163
+ regex,
11164
+ routeKeys,
11165
+ prefetchSegmentDataRoutes
11166
+ } = params;
11144
11167
  const route = {
11145
11168
  src: namedRegex || regex,
11146
11169
  dest: `${!isDev ? import_path2.default.posix.join("/", entryDirectory, page) : page}${routeKeys ? `?${Object.keys(routeKeys).map((key) => `${routeKeys[key]}=$${key}`).join("&")}` : ""}`
@@ -11161,6 +11184,20 @@ async function getDynamicRoutes({
11161
11184
  }
11162
11185
  ];
11163
11186
  }
11187
+ if (isAppClientSegmentCacheEnabled && prefetchSegmentDataRoutes && prefetchSegmentDataRoutes.length > 0) {
11188
+ for (const prefetchSegmentDataRoute of prefetchSegmentDataRoutes) {
11189
+ routes2.push({
11190
+ ...route,
11191
+ src: prefetchSegmentDataRoute.source,
11192
+ dest: `${!isDev ? import_path2.default.posix.join(
11193
+ "/",
11194
+ entryDirectory,
11195
+ prefetchSegmentDataRoute.destination
11196
+ ) : prefetchSegmentDataRoute.destination}${routeKeys ? `?${Object.entries(routeKeys).map(([key, value]) => `${value}=$${key}`).join("&")}` : ""}`,
11197
+ check: true
11198
+ });
11199
+ }
11200
+ }
11164
11201
  if (isAppPPREnabled) {
11165
11202
  let dest = route.dest?.replace(/($|\?)/, ".prefetch.rsc$1");
11166
11203
  if (page === "/" || page === "/index") {
@@ -11248,6 +11285,7 @@ async function getDynamicRoutes({
11248
11285
  }
11249
11286
  function localizeDynamicRoutes(dynamicRoutes, dynamicPrefix, entryDirectory, staticPages, prerenderManifest, routesManifest, isServerMode, isCorrectLocaleAPIRoutes, inversedAppPathRoutesManifest) {
11250
11287
  const finalDynamicRoutes = [];
11288
+ const nonLocalePrefixedRoutes = [];
11251
11289
  for (const route of dynamicRoutes) {
11252
11290
  if (route.middleware !== void 0 || route.middlewarePath !== void 0) {
11253
11291
  finalDynamicRoutes.push(route);
@@ -11269,11 +11307,13 @@ function localizeDynamicRoutes(dynamicRoutes, dynamicPrefix, entryDirectory, sta
11269
11307
  "^",
11270
11308
  `^${dynamicPrefix || ""}[/]?`
11271
11309
  );
11272
- finalDynamicRoutes.push(nonLocalePrefixedRoute);
11310
+ nonLocalePrefixedRoutes.push(nonLocalePrefixedRoute);
11273
11311
  }
11274
11312
  route.src = route.src.replace(
11275
11313
  "^",
11276
- `^${dynamicPrefix ? `${dynamicPrefix}[/]?` : "[/]?"}(?${isLocalePrefixed ? "<nextLocale>" : ":"}${i18n.locales.map((locale) => (0, import_escape_string_regexp.default)(locale)).join("|")})?`
11314
+ `^${dynamicPrefix ? `${dynamicPrefix}[/]?` : "[/]?"}(?${isLocalePrefixed ? "<nextLocale>" : ":"}${i18n.locales.map((locale) => (0, import_escape_string_regexp.default)(locale)).join("|")})${// the locale is not optional on this path with the skip default
11315
+ // locale rewrite flag otherwise can cause double slash in dest
11316
+ skipDefaultLocaleRewrite ? "" : "?"}`
11277
11317
  );
11278
11318
  if (isLocalePrefixed && !(isCorrectLocaleAPIRoutes && isApiRoute) && !isAppRoute) {
11279
11319
  route.dest = route.dest.replace(
@@ -11286,6 +11326,9 @@ function localizeDynamicRoutes(dynamicRoutes, dynamicPrefix, entryDirectory, sta
11286
11326
  }
11287
11327
  finalDynamicRoutes.push(route);
11288
11328
  }
11329
+ if (nonLocalePrefixedRoutes.length > 0) {
11330
+ finalDynamicRoutes.push(...nonLocalePrefixedRoutes);
11331
+ }
11289
11332
  return finalDynamicRoutes;
11290
11333
  }
11291
11334
  async function getImagesManifest(entryPath, outputDirectory) {
@@ -12094,7 +12137,8 @@ var onPrerenderRoute = (prerenderRouteArgs) => async (routeKey, {
12094
12137
  routesManifest,
12095
12138
  isCorrectNotFoundRoutes,
12096
12139
  isEmptyAllowQueryForPrendered,
12097
- isAppPPREnabled
12140
+ isAppPPREnabled,
12141
+ isAppClientSegmentCacheEnabled
12098
12142
  } = prerenderRouteArgs;
12099
12143
  if (isBlocking && isFallback) {
12100
12144
  throw new import_build_utils.NowBuildError({
@@ -12211,7 +12255,7 @@ var onPrerenderRoute = (prerenderRouteArgs) => async (routeKey, {
12211
12255
  const metaPath = import_path2.default.join(appDir, `${routeFileNoExt}.meta`);
12212
12256
  if (import_fs_extra3.default.existsSync(htmlPath) && import_fs_extra3.default.existsSync(metaPath)) {
12213
12257
  const meta = JSON.parse(await import_fs_extra3.default.readFile(metaPath, "utf8"));
12214
- if ("postponed" in meta && typeof meta.postponed === "string") {
12258
+ if (typeof meta === "object" && meta !== null && "postponed" in meta && typeof meta.postponed === "string") {
12215
12259
  didPostpone = true;
12216
12260
  postponedPrerender = meta.postponed;
12217
12261
  initialHeaders ??= {};
@@ -12512,6 +12556,53 @@ var onPrerenderRoute = (prerenderRouteArgs) => async (routeKey, {
12512
12556
  prerenders[normalizePathData(outputPathData)] = prerender;
12513
12557
  }
12514
12558
  }
12559
+ const prefetchSegmentSuffix = routesManifest?.rsc?.prefetchSegmentSuffix;
12560
+ const prefetchSegmentDirSuffix = routesManifest?.rsc?.prefetchSegmentDirSuffix;
12561
+ if (isAppClientSegmentCacheEnabled && prefetchSegmentSuffix && prefetchSegmentDirSuffix && rscDidPostponeHeader && appDir) {
12562
+ const metaPath = import_path2.default.join(appDir, `${routeFileNoExt}.meta`);
12563
+ if (import_fs_extra3.default.existsSync(metaPath)) {
12564
+ const meta = JSON.parse(await import_fs_extra3.default.readFile(metaPath, "utf8"));
12565
+ if (typeof meta === "object" && meta !== null && "segmentPaths" in meta && typeof meta.segmentPaths === "object" && meta.segmentPaths !== null && Array.isArray(meta.segmentPaths)) {
12566
+ const segmentsDir = import_path2.default.join(
12567
+ appDir,
12568
+ routeFileNoExt + prefetchSegmentDirSuffix
12569
+ );
12570
+ for (const segmentPath of meta.segmentPaths) {
12571
+ const outputSegmentPath = import_path2.default.join(
12572
+ outputPathPage + prefetchSegmentDirSuffix,
12573
+ segmentPath
12574
+ ) + prefetchSegmentSuffix;
12575
+ let fallback = null;
12576
+ if (!isFallback) {
12577
+ const fsPath = import_path2.default.join(
12578
+ segmentsDir,
12579
+ segmentPath + prefetchSegmentSuffix
12580
+ );
12581
+ fallback = new import_build_utils.FileFsRef({ fsPath });
12582
+ }
12583
+ prerenders[outputSegmentPath] = new import_build_utils.Prerender({
12584
+ expiration: initialRevalidate,
12585
+ lambda,
12586
+ allowQuery,
12587
+ fallback,
12588
+ // Use the same prerender group as the JSON/data prerender.
12589
+ group: prerenderGroup,
12590
+ allowHeader,
12591
+ // These routes are always only static, so they should not
12592
+ // permit any bypass unless it's for preview
12593
+ bypassToken: prerenderManifest.bypassToken,
12594
+ experimentalBypassFor: void 0,
12595
+ initialHeaders: {
12596
+ ...initialHeaders,
12597
+ vary: rscVaryHeader,
12598
+ "content-type": rscContentTypeHeader,
12599
+ [rscDidPostponeHeader]: "2"
12600
+ }
12601
+ });
12602
+ }
12603
+ }
12604
+ }
12605
+ }
12515
12606
  if (outputPathData?.endsWith(".json") && appDir) {
12516
12607
  const dummyOutput = new import_build_utils.FileBlob({
12517
12608
  data: "{}",
@@ -13611,7 +13702,8 @@ async function serverBuild({
13611
13702
  requiredServerFilesManifest,
13612
13703
  variantsManifest,
13613
13704
  experimentalPPRRoutes,
13614
- isAppPPREnabled
13705
+ isAppPPREnabled,
13706
+ isAppClientSegmentCacheEnabled
13615
13707
  }) {
13616
13708
  if (isAppPPREnabled) {
13617
13709
  (0, import_build_utils2.debug)(
@@ -13664,10 +13756,17 @@ async function serverBuild({
13664
13756
  continue;
13665
13757
  const { protocol, pathname, query } = import_url2.default.parse(rewrite.dest);
13666
13758
  if (isAfterFilesRewrite) {
13667
- const rscSuffix = isAppPPREnabled ? `(\\.prefetch)?\\.rsc` : "\\.rsc";
13759
+ const parts = ["\\.rsc"];
13760
+ if (isAppPPREnabled) {
13761
+ parts.push("\\.prefetch\\.rsc");
13762
+ }
13763
+ if (isAppClientSegmentCacheEnabled) {
13764
+ parts.push("\\.segments/.+\\.segment\\.rsc");
13765
+ }
13766
+ const rscSuffix = parts.join("|");
13668
13767
  rewrite.src = rewrite.src.replace(
13669
13768
  /\/?\(\?:\/\)\?/,
13670
- `(?<rscsuff>${rscSuffix})?(?:/)?`
13769
+ `(?:/)?(?<rscsuff>${rscSuffix})?`
13671
13770
  );
13672
13771
  let destQueryIndex = rewrite.dest.indexOf("?");
13673
13772
  if (destQueryIndex === -1) {
@@ -14562,7 +14661,8 @@ ${JSON.stringify(
14562
14661
  hasPages404: routesManifest.pages404,
14563
14662
  isCorrectNotFoundRoutes,
14564
14663
  isEmptyAllowQueryForPrendered,
14565
- isAppPPREnabled
14664
+ isAppPPREnabled,
14665
+ isAppClientSegmentCacheEnabled
14566
14666
  });
14567
14667
  await Promise.all(
14568
14668
  Object.keys(prerenderManifest.staticRoutes).map(
@@ -14627,7 +14727,8 @@ ${JSON.stringify(
14627
14727
  bypassToken: prerenderManifest.bypassToken || "",
14628
14728
  isServerMode: true,
14629
14729
  dynamicMiddlewareRouteMap: middleware.dynamicRouteMap,
14630
- isAppPPREnabled
14730
+ isAppPPREnabled,
14731
+ isAppClientSegmentCacheEnabled
14631
14732
  }).then(
14632
14733
  (arr) => localizeDynamicRoutes(
14633
14734
  arr,
@@ -14787,6 +14888,9 @@ ${JSON.stringify(
14787
14888
  }
14788
14889
  }
14789
14890
  }
14891
+ const prefetchSegmentHeader = routesManifest?.rsc?.prefetchSegmentHeader;
14892
+ const prefetchSegmentDirSuffix = routesManifest?.rsc?.prefetchSegmentDirSuffix;
14893
+ const prefetchSegmentSuffix = routesManifest?.rsc?.prefetchSegmentSuffix;
14790
14894
  const rscPrefetchHeader = routesManifest.rsc?.prefetchHeader?.toLowerCase();
14791
14895
  const rscVaryHeader = routesManifest?.rsc?.varyHeader || "RSC, Next-Router-State-Tree, Next-Router-Prefetch";
14792
14896
  const appNotFoundPath = import_path4.default.posix.join(".", entryDirectory, "_not-found");
@@ -15020,9 +15124,65 @@ ${JSON.stringify(
15020
15124
  // to prevent a local/deploy mismatch
15021
15125
  ...!isCorrectMiddlewareOrder ? middleware.staticRoutes : [],
15022
15126
  ...appDir ? [
15127
+ ...isAppClientSegmentCacheEnabled && rscPrefetchHeader && prefetchSegmentHeader && prefetchSegmentDirSuffix && prefetchSegmentSuffix ? [
15128
+ {
15129
+ src: import_path4.default.posix.join("/", entryDirectory, "/(?<path>.+)$"),
15130
+ dest: import_path4.default.posix.join(
15131
+ "/",
15132
+ entryDirectory,
15133
+ `/$path${prefetchSegmentDirSuffix}/$segmentPath${prefetchSegmentSuffix}`
15134
+ ),
15135
+ has: [
15136
+ {
15137
+ type: "header",
15138
+ key: rscHeader,
15139
+ value: "1"
15140
+ },
15141
+ {
15142
+ type: "header",
15143
+ key: rscPrefetchHeader,
15144
+ value: "1"
15145
+ },
15146
+ {
15147
+ type: "header",
15148
+ key: prefetchSegmentHeader,
15149
+ value: "/(?<segmentPath>.+)"
15150
+ }
15151
+ ],
15152
+ continue: true,
15153
+ override: true
15154
+ },
15155
+ {
15156
+ src: import_path4.default.posix.join("^/", entryDirectory, "$"),
15157
+ dest: import_path4.default.posix.join(
15158
+ "/",
15159
+ entryDirectory,
15160
+ `/index${prefetchSegmentDirSuffix}/$segmentPath${prefetchSegmentSuffix}`
15161
+ ),
15162
+ has: [
15163
+ {
15164
+ type: "header",
15165
+ key: rscHeader,
15166
+ value: "1"
15167
+ },
15168
+ {
15169
+ type: "header",
15170
+ key: rscPrefetchHeader,
15171
+ value: "1"
15172
+ },
15173
+ {
15174
+ type: "header",
15175
+ key: prefetchSegmentHeader,
15176
+ value: "/(?<segmentPath>.+)"
15177
+ }
15178
+ ],
15179
+ continue: true,
15180
+ override: true
15181
+ }
15182
+ ] : [],
15023
15183
  ...rscPrefetchHeader && isAppPPREnabled ? [
15024
15184
  {
15025
- src: `^${import_path4.default.posix.join("/", entryDirectory, "/")}`,
15185
+ src: `^${import_path4.default.posix.join("/", entryDirectory, "/")}$`,
15026
15186
  has: [
15027
15187
  {
15028
15188
  type: "header",
@@ -15334,6 +15494,23 @@ ${JSON.stringify(
15334
15494
  dest: "__next_data_catchall"
15335
15495
  }
15336
15496
  ] : [],
15497
+ // If it didn't match any of the static routes or dynamic ones, then we
15498
+ // should fallback to the regular RSC request.
15499
+ ...isAppClientSegmentCacheEnabled && rscPrefetchHeader && prefetchSegmentHeader && prefetchSegmentDirSuffix && prefetchSegmentSuffix ? [
15500
+ {
15501
+ src: import_path4.default.posix.join(
15502
+ "/",
15503
+ entryDirectory,
15504
+ `/(?<path>.+)${(0, import_escape_string_regexp2.default)(prefetchSegmentDirSuffix)}/.+${(0, import_escape_string_regexp2.default)(prefetchSegmentSuffix)}$`
15505
+ ),
15506
+ dest: import_path4.default.posix.join(
15507
+ "/",
15508
+ entryDirectory,
15509
+ isAppPPREnabled ? "/$path.prefetch.rsc" : "/$path.rsc"
15510
+ ),
15511
+ check: true
15512
+ }
15513
+ ] : [],
15337
15514
  // routes to call after a file has been matched
15338
15515
  { handle: "hit" },
15339
15516
  // Before we handle static files we need to set proper caching headers
@@ -16384,6 +16561,7 @@ More info: http://err.sh/vercel/vercel/next-functions-config-optimized-lambdas`
16384
16561
  experimentalPPRRoutes.add(route);
16385
16562
  }
16386
16563
  const isAppPPREnabled = requiredServerFilesManifest ? requiredServerFilesManifest.config.experimental?.ppr === true || requiredServerFilesManifest.config.experimental?.ppr === "incremental" : false;
16564
+ const isAppClientSegmentCacheEnabled = requiredServerFilesManifest ? requiredServerFilesManifest.config.experimental?.clientSegmentCache === true : false;
16387
16565
  if (requiredServerFilesManifest) {
16388
16566
  if (!routesManifest) {
16389
16567
  throw new Error(
@@ -16432,7 +16610,8 @@ More info: http://err.sh/vercel/vercel/next-functions-config-optimized-lambdas`
16432
16610
  hasIsr500Page,
16433
16611
  variantsManifest,
16434
16612
  experimentalPPRRoutes,
16435
- isAppPPREnabled
16613
+ isAppPPREnabled,
16614
+ isAppClientSegmentCacheEnabled
16436
16615
  });
16437
16616
  }
16438
16617
  const pageKeys = Object.keys(pages);
@@ -16828,7 +17007,8 @@ More info: http://err.sh/vercel/vercel/next-functions-config-optimized-lambdas`
16828
17007
  canUsePreviewMode,
16829
17008
  bypassToken: prerenderManifest.bypassToken || "",
16830
17009
  isServerMode,
16831
- isAppPPREnabled: false
17010
+ isAppPPREnabled: false,
17011
+ isAppClientSegmentCacheEnabled: false
16832
17012
  }).then(
16833
17013
  (arr) => localizeDynamicRoutes(
16834
17014
  arr,
@@ -16854,7 +17034,8 @@ More info: http://err.sh/vercel/vercel/next-functions-config-optimized-lambdas`
16854
17034
  canUsePreviewMode,
16855
17035
  bypassToken: prerenderManifest.bypassToken || "",
16856
17036
  isServerMode,
16857
- isAppPPREnabled: false
17037
+ isAppPPREnabled: false,
17038
+ isAppClientSegmentCacheEnabled: false
16858
17039
  }).then(
16859
17040
  (arr) => arr.map((route) => {
16860
17041
  route.src = route.src.replace("^", `^${dynamicPrefix}`);
@@ -17033,7 +17214,8 @@ More info: http://err.sh/vercel/vercel/next-functions-config-optimized-lambdas`
17033
17214
  appPathRoutesManifest,
17034
17215
  isSharedLambdas,
17035
17216
  canUsePreviewMode,
17036
- isAppPPREnabled: false
17217
+ isAppPPREnabled: false,
17218
+ isAppClientSegmentCacheEnabled: false
17037
17219
  });
17038
17220
  await Promise.all(
17039
17221
  Object.keys(prerenderManifest.staticRoutes).map(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/next",
3
- "version": "4.5.0",
3
+ "version": "4.5.2",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./dist/index",
6
6
  "homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",
@@ -30,8 +30,8 @@
30
30
  "@types/semver": "6.0.0",
31
31
  "@types/text-table": "0.2.1",
32
32
  "@types/webpack-sources": "3.2.0",
33
- "@vercel/build-utils": "9.2.0",
34
- "@vercel/routing-utils": "5.0.2",
33
+ "@vercel/build-utils": "9.2.1",
34
+ "@vercel/routing-utils": "5.0.4",
35
35
  "async-sema": "3.0.1",
36
36
  "buffer-crc32": "0.2.13",
37
37
  "bytes": "3.1.2",