@vercel/next 4.0.12 → 4.0.13

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.
package/dist/index.js CHANGED
@@ -9677,7 +9677,7 @@ async function getRoutesManifest(entryPath, outputDirectory, nextVersion) {
9677
9677
  }
9678
9678
  return routesManifest;
9679
9679
  }
9680
- async function getDynamicRoutes(entryPath, entryDirectory, dynamicPages, isDev, routesManifest, omittedRoutes, canUsePreviewMode, bypassToken, isServerMode, dynamicMiddlewareRouteMap) {
9680
+ async function getDynamicRoutes(entryPath, entryDirectory, dynamicPages, isDev, routesManifest, omittedRoutes, canUsePreviewMode, bypassToken, isServerMode, dynamicMiddlewareRouteMap, experimentalPPR) {
9681
9681
  if (routesManifest) {
9682
9682
  switch (routesManifest.version) {
9683
9683
  case 1:
@@ -9730,6 +9730,20 @@ async function getDynamicRoutes(entryPath, entryDirectory, dynamicPages, isDev,
9730
9730
  }
9731
9731
  ];
9732
9732
  }
9733
+ if (experimentalPPR) {
9734
+ let dest = route.dest?.replace(/($|\?)/, ".prefetch.rsc$1");
9735
+ if (page === "/" || page === "/index") {
9736
+ dest = dest?.replace(/([^/]+\.prefetch\.rsc(\?.*|$))/, "__$1");
9737
+ }
9738
+ routes2.push({
9739
+ ...route,
9740
+ src: route.src.replace(
9741
+ new RegExp((0, import_escape_string_regexp.default)("(?:/)?$")),
9742
+ "(?:\\.prefetch\\.rsc)(?:/)?$"
9743
+ ),
9744
+ dest
9745
+ });
9746
+ }
9733
9747
  routes2.push({
9734
9748
  ...route,
9735
9749
  src: route.src.replace(
@@ -9739,7 +9753,6 @@ async function getDynamicRoutes(entryPath, entryDirectory, dynamicPages, isDev,
9739
9753
  dest: route.dest?.replace(/($|\?)/, ".rsc$1")
9740
9754
  });
9741
9755
  routes2.push(route);
9742
- continue;
9743
9756
  }
9744
9757
  return routes2;
9745
9758
  }
@@ -10152,47 +10165,68 @@ async function getPrerenderManifest(entryPath, outputDirectory) {
10152
10165
  let initialStatus;
10153
10166
  let initialHeaders;
10154
10167
  let experimentalBypassFor;
10168
+ let experimentalPPR;
10169
+ let prefetchDataRoute;
10155
10170
  if (manifest.version === 4) {
10156
10171
  initialStatus = manifest.routes[route].initialStatus;
10157
10172
  initialHeaders = manifest.routes[route].initialHeaders;
10158
10173
  experimentalBypassFor = manifest.routes[route].experimentalBypassFor;
10174
+ experimentalPPR = manifest.routes[route].experimentalPPR;
10175
+ prefetchDataRoute = manifest.routes[route].prefetchDataRoute;
10159
10176
  }
10160
10177
  ret.staticRoutes[route] = {
10161
10178
  initialRevalidate: initialRevalidateSeconds === false ? false : Math.max(1, initialRevalidateSeconds),
10162
10179
  dataRoute,
10180
+ prefetchDataRoute,
10163
10181
  srcRoute,
10164
10182
  initialStatus,
10165
10183
  initialHeaders,
10166
- experimentalBypassFor
10184
+ experimentalBypassFor,
10185
+ experimentalPPR
10167
10186
  };
10168
10187
  });
10169
10188
  lazyRoutes.forEach((lazyRoute) => {
10170
10189
  const { routeRegex, fallback, dataRoute, dataRouteRegex } = manifest.dynamicRoutes[lazyRoute];
10171
10190
  let experimentalBypassFor;
10191
+ let experimentalPPR;
10192
+ let prefetchDataRoute;
10193
+ let prefetchDataRouteRegex;
10172
10194
  if (manifest.version === 4) {
10173
10195
  experimentalBypassFor = manifest.dynamicRoutes[lazyRoute].experimentalBypassFor;
10196
+ experimentalPPR = manifest.dynamicRoutes[lazyRoute].experimentalPPR;
10197
+ prefetchDataRoute = manifest.dynamicRoutes[lazyRoute].prefetchDataRoute;
10198
+ prefetchDataRouteRegex = manifest.dynamicRoutes[lazyRoute].prefetchDataRouteRegex;
10174
10199
  }
10175
10200
  if (typeof fallback === "string") {
10176
10201
  ret.fallbackRoutes[lazyRoute] = {
10177
10202
  experimentalBypassFor,
10203
+ experimentalPPR,
10178
10204
  routeRegex,
10179
10205
  fallback,
10180
10206
  dataRoute,
10181
- dataRouteRegex
10207
+ dataRouteRegex,
10208
+ prefetchDataRoute,
10209
+ prefetchDataRouteRegex
10182
10210
  };
10183
10211
  } else if (fallback === null) {
10184
10212
  ret.blockingFallbackRoutes[lazyRoute] = {
10185
10213
  experimentalBypassFor,
10214
+ experimentalPPR,
10186
10215
  routeRegex,
10187
10216
  dataRoute,
10188
- dataRouteRegex
10217
+ dataRouteRegex,
10218
+ prefetchDataRoute,
10219
+ prefetchDataRouteRegex
10189
10220
  };
10190
10221
  } else {
10191
10222
  ret.omittedRoutes[lazyRoute] = {
10192
10223
  experimentalBypassFor,
10224
+ experimentalPPR,
10193
10225
  routeRegex,
10194
10226
  dataRoute,
10195
- dataRouteRegex
10227
+ dataRouteRegex,
10228
+ prefetchDataRoute,
10229
+ prefetchDataRouteRegex
10196
10230
  };
10197
10231
  }
10198
10232
  });
@@ -10322,6 +10356,7 @@ async function getPageLambdaGroups({
10322
10356
  functionsConfigManifest,
10323
10357
  pages,
10324
10358
  prerenderRoutes,
10359
+ experimentalPPRRoutes,
10325
10360
  pageTraces,
10326
10361
  compressedPages,
10327
10362
  tracedPseudoLayer,
@@ -10336,6 +10371,7 @@ async function getPageLambdaGroups({
10336
10371
  const newPages = [...internalPages, page];
10337
10372
  const routeName = normalizePage(page.replace(/\.js$/, ""));
10338
10373
  const isPrerenderRoute = prerenderRoutes.has(routeName);
10374
+ const isExperimentalPPR = experimentalPPRRoutes?.has(routeName) ?? false;
10339
10375
  let opts = {};
10340
10376
  if (functionsConfigManifest && functionsConfigManifest.functions[routeName]) {
10341
10377
  opts = functionsConfigManifest.functions[routeName];
@@ -10353,7 +10389,7 @@ async function getPageLambdaGroups({
10353
10389
  opts = { ...vercelConfigOpts, ...opts };
10354
10390
  }
10355
10391
  let matchingGroup = groups.find((group) => {
10356
- const matches = group.maxDuration === opts.maxDuration && group.memory === opts.memory && group.isPrerenders === isPrerenderRoute;
10392
+ const matches = group.maxDuration === opts.maxDuration && group.memory === opts.memory && group.isPrerenders === isPrerenderRoute && group.isExperimentalPPR === isExperimentalPPR;
10357
10393
  if (matches) {
10358
10394
  let newTracedFilesSize = group.pseudoLayerBytes;
10359
10395
  let newTracedFilesUncompressedSize = group.pseudoLayerUncompressedBytes;
@@ -10381,6 +10417,7 @@ async function getPageLambdaGroups({
10381
10417
  pages: [page],
10382
10418
  ...opts,
10383
10419
  isPrerenders: isPrerenderRoute,
10420
+ isExperimentalPPR,
10384
10421
  isApiLambda: !!isApiPage(page),
10385
10422
  pseudoLayerBytes: initialPseudoLayer.pseudoLayerBytes,
10386
10423
  pseudoLayerUncompressedBytes: initialPseudoLayerUncompressed,
@@ -10562,7 +10599,7 @@ var onPrerenderRouteInitial = (prerenderManifest, canUsePreviewMode, entryDirect
10562
10599
  };
10563
10600
  };
10564
10601
  var prerenderGroup = 1;
10565
- var onPrerenderRoute = (prerenderRouteArgs) => (routeKey, {
10602
+ var onPrerenderRoute = (prerenderRouteArgs) => async (routeKey, {
10566
10603
  isBlocking,
10567
10604
  isFallback,
10568
10605
  isOmitted,
@@ -10579,6 +10616,7 @@ var onPrerenderRoute = (prerenderRouteArgs) => (routeKey, {
10579
10616
  isServerMode,
10580
10617
  canUsePreviewMode,
10581
10618
  lambdas,
10619
+ experimentalStreamingLambdaPaths,
10582
10620
  prerenders,
10583
10621
  pageLambdaMap,
10584
10622
  routesManifest,
@@ -10621,9 +10659,11 @@ var onPrerenderRoute = (prerenderRouteArgs) => (routeKey, {
10621
10659
  let initialRevalidate;
10622
10660
  let srcRoute;
10623
10661
  let dataRoute;
10662
+ let prefetchDataRoute;
10624
10663
  let initialStatus;
10625
10664
  let initialHeaders;
10626
10665
  let experimentalBypassFor;
10666
+ let experimentalPPR;
10627
10667
  if (isFallback || isBlocking) {
10628
10668
  const pr = isFallback ? prerenderManifest.fallbackRoutes[routeKey] : prerenderManifest.blockingFallbackRoutes[routeKey];
10629
10669
  initialRevalidate = 1;
@@ -10636,11 +10676,15 @@ var onPrerenderRoute = (prerenderRouteArgs) => (routeKey, {
10636
10676
  srcRoute = null;
10637
10677
  dataRoute = pr.dataRoute;
10638
10678
  experimentalBypassFor = pr.experimentalBypassFor;
10679
+ experimentalPPR = pr.experimentalPPR;
10680
+ prefetchDataRoute = pr.prefetchDataRoute;
10639
10681
  } else if (isOmitted) {
10640
10682
  initialRevalidate = false;
10641
10683
  srcRoute = routeKey;
10642
10684
  dataRoute = prerenderManifest.omittedRoutes[routeKey].dataRoute;
10643
10685
  experimentalBypassFor = prerenderManifest.omittedRoutes[routeKey].experimentalBypassFor;
10686
+ experimentalPPR = prerenderManifest.omittedRoutes[routeKey].experimentalPPR;
10687
+ prefetchDataRoute = prerenderManifest.omittedRoutes[routeKey].prefetchDataRoute;
10644
10688
  } else {
10645
10689
  const pr = prerenderManifest.staticRoutes[routeKey];
10646
10690
  ({
@@ -10649,7 +10693,9 @@ var onPrerenderRoute = (prerenderRouteArgs) => (routeKey, {
10649
10693
  dataRoute,
10650
10694
  initialHeaders,
10651
10695
  initialStatus,
10652
- experimentalBypassFor
10696
+ experimentalBypassFor,
10697
+ experimentalPPR,
10698
+ prefetchDataRoute
10653
10699
  } = pr);
10654
10700
  }
10655
10701
  let isAppPathRoute = false;
@@ -10658,7 +10704,38 @@ var onPrerenderRoute = (prerenderRouteArgs) => (routeKey, {
10658
10704
  }
10659
10705
  const isOmittedOrNotFound = isOmitted || isNotFound;
10660
10706
  let htmlFsRef;
10661
- if (appDir && !dataRoute && isAppPathRoute && !(isBlocking || isFallback)) {
10707
+ let prerender;
10708
+ if (experimentalPPR && appDir) {
10709
+ const htmlPath = import_path2.default.join(appDir, `${routeFileNoExt}.html`);
10710
+ const metaPath = import_path2.default.join(appDir, `${routeFileNoExt}.meta`);
10711
+ if (import_fs_extra3.default.existsSync(htmlPath) && import_fs_extra3.default.existsSync(metaPath)) {
10712
+ const meta = JSON.parse(await import_fs_extra3.default.readFile(metaPath, "utf8"));
10713
+ if ("postponed" in meta && typeof meta.postponed === "string") {
10714
+ prerender = meta.postponed;
10715
+ initialHeaders ??= {};
10716
+ initialHeaders["content-type"] = `application/x-nextjs-pre-render; state-length=${meta.postponed.length}`;
10717
+ const html = await import_fs_extra3.default.readFileSync(htmlPath, "utf8");
10718
+ prerender += html;
10719
+ }
10720
+ }
10721
+ if (!dataRoute?.endsWith(".rsc")) {
10722
+ throw new Error(
10723
+ `Invariant: unexpected output path for ${dataRoute} and PPR`
10724
+ );
10725
+ }
10726
+ if (!prefetchDataRoute?.endsWith(".prefetch.rsc")) {
10727
+ throw new Error(
10728
+ `Invariant: unexpected output path for ${prefetchDataRoute} and PPR`
10729
+ );
10730
+ }
10731
+ }
10732
+ if (prerender) {
10733
+ const contentType = initialHeaders?.["content-type"];
10734
+ if (!contentType) {
10735
+ throw new Error("Invariant: contentType can't be undefined");
10736
+ }
10737
+ htmlFsRef = new import_build_utils.FileBlob({ contentType, data: prerender });
10738
+ } else if (appDir && !dataRoute && isAppPathRoute && !(isBlocking || isFallback)) {
10662
10739
  const contentType = initialHeaders?.["content-type"];
10663
10740
  htmlFsRef = new import_build_utils.FileFsRef({
10664
10741
  fsPath: import_path2.default.join(appDir, `${routeFileNoExt}.body`),
@@ -10691,7 +10768,7 @@ var onPrerenderRoute = (prerenderRouteArgs) => (routeKey, {
10691
10768
  isFallback || isBlocking || isNotFound && !static404Page || !dataRoute ? null : new import_build_utils.FileFsRef({
10692
10769
  fsPath: import_path2.default.join(
10693
10770
  isAppPathRoute && !isOmittedOrNotFound && appDir ? appDir : pagesDir,
10694
- `${isOmittedOrNotFound ? localePrefixed404 ? addLocaleOrDefault("/404.html", routesManifest, locale) : "/404.html" : isAppPathRoute ? dataRoute : routeFileNoExt + ".json"}`
10771
+ `${isOmittedOrNotFound ? localePrefixed404 ? addLocaleOrDefault("/404.html", routesManifest, locale) : "/404.html" : isAppPathRoute ? prefetchDataRoute || dataRoute : routeFileNoExt + ".json"}`
10695
10772
  )
10696
10773
  })
10697
10774
  );
@@ -10714,11 +10791,10 @@ var onPrerenderRoute = (prerenderRouteArgs) => (routeKey, {
10714
10791
  origRouteFileNoExt
10715
10792
  );
10716
10793
  let lambda;
10717
- let outputPathData = null;
10718
- if (dataRoute) {
10719
- outputPathData = import_path2.default.posix.join(entryDirectory, dataRoute);
10794
+ function normalizeDataRoute(route) {
10795
+ let normalized = import_path2.default.posix.join(entryDirectory, route);
10720
10796
  if (nonDynamicSsg || isFallback || isOmitted) {
10721
- outputPathData = outputPathData.replace(
10797
+ normalized = normalized.replace(
10722
10798
  new RegExp(`${(0, import_escape_string_regexp.default)(origRouteFileNoExt)}.json$`),
10723
10799
  // ensure we escape "$" correctly while replacing as "$" is a special
10724
10800
  // character, we need to do double escaping as first is for the initial
@@ -10726,7 +10802,24 @@ var onPrerenderRoute = (prerenderRouteArgs) => (routeKey, {
10726
10802
  `${routeFileNoExt.replace(/\$/g, "$$$$")}.json`
10727
10803
  );
10728
10804
  }
10805
+ return normalized;
10729
10806
  }
10807
+ let outputPathData = null;
10808
+ if (dataRoute) {
10809
+ outputPathData = normalizeDataRoute(dataRoute);
10810
+ }
10811
+ let outputPathPrefetchData = null;
10812
+ if (prefetchDataRoute) {
10813
+ if (!experimentalPPR) {
10814
+ throw new Error(
10815
+ "Invariant: prefetchDataRoute can't be set without PPR"
10816
+ );
10817
+ }
10818
+ outputPathPrefetchData = normalizeDataRoute(prefetchDataRoute);
10819
+ } else if (experimentalPPR) {
10820
+ throw new Error("Invariant: expected to find prefetch data route PPR");
10821
+ }
10822
+ const outputPrerenderPathData = outputPathPrefetchData || outputPathData;
10730
10823
  if (isSharedLambdas) {
10731
10824
  const outputSrcPathPage = normalizeIndexOutput(
10732
10825
  import_path2.default.join(
@@ -10760,8 +10853,8 @@ var onPrerenderRoute = (prerenderRouteArgs) => (routeKey, {
10760
10853
  if (!canUsePreviewMode || routeKey === "/404" && !lambdas[outputPathPage]) {
10761
10854
  htmlFsRef.contentType = htmlContentType;
10762
10855
  prerenders[outputPathPage] = htmlFsRef;
10763
- if (outputPathData) {
10764
- prerenders[outputPathData] = jsonFsRef;
10856
+ if (outputPrerenderPathData) {
10857
+ prerenders[outputPrerenderPathData] = jsonFsRef;
10765
10858
  }
10766
10859
  }
10767
10860
  }
@@ -10797,10 +10890,22 @@ var onPrerenderRoute = (prerenderRouteArgs) => (routeKey, {
10797
10890
  const rscEnabled = !!routesManifest?.rsc;
10798
10891
  const rscVaryHeader = routesManifest?.rsc?.varyHeader || "RSC, Next-Router-State-Tree, Next-Router-Prefetch";
10799
10892
  const rscContentTypeHeader = routesManifest?.rsc?.contentTypeHeader || RSC_CONTENT_TYPE;
10893
+ const rscDidPostponeHeader = routesManifest?.rsc?.didPostponeHeader;
10800
10894
  let sourcePath;
10801
10895
  if (`/${outputPathPage}` !== srcRoute && srcRoute) {
10802
10896
  sourcePath = srcRoute;
10803
10897
  }
10898
+ let key = srcRoute || routeKey;
10899
+ if (key === "/") {
10900
+ key = "index";
10901
+ } else {
10902
+ if (!key.startsWith("/")) {
10903
+ throw new Error("Invariant: key doesn't start with /");
10904
+ }
10905
+ key = key.substring(1);
10906
+ }
10907
+ key = import_path2.default.posix.join(entryDirectory, key);
10908
+ const experimentalStreamingLambdaPath = experimentalStreamingLambdaPaths?.get(key);
10804
10909
  prerenders[outputPathPage] = new import_build_utils.Prerender({
10805
10910
  expiration: initialRevalidate,
10806
10911
  lambda,
@@ -10812,6 +10917,7 @@ var onPrerenderRoute = (prerenderRouteArgs) => (routeKey, {
10812
10917
  initialStatus,
10813
10918
  initialHeaders,
10814
10919
  sourcePath,
10920
+ experimentalStreamingLambdaPath,
10815
10921
  ...isNotFound ? {
10816
10922
  initialStatus: 404
10817
10923
  } : {},
@@ -10822,8 +10928,16 @@ var onPrerenderRoute = (prerenderRouteArgs) => (routeKey, {
10822
10928
  }
10823
10929
  } : {}
10824
10930
  });
10825
- if (outputPathData) {
10826
- prerenders[outputPathData] = new import_build_utils.Prerender({
10931
+ if (outputPrerenderPathData) {
10932
+ let normalizedPathData = outputPrerenderPathData;
10933
+ if ((srcRoute === "/" || srcRoute == "/index") && outputPrerenderPathData.endsWith(RSC_PREFETCH_SUFFIX)) {
10934
+ delete lambdas[normalizedPathData];
10935
+ normalizedPathData = normalizedPathData.replace(
10936
+ /([^/]+\.prefetch\.rsc)$/,
10937
+ "__$1"
10938
+ );
10939
+ }
10940
+ prerenders[normalizedPathData] = new import_build_utils.Prerender({
10827
10941
  expiration: initialRevalidate,
10828
10942
  lambda,
10829
10943
  allowQuery,
@@ -10837,7 +10951,8 @@ var onPrerenderRoute = (prerenderRouteArgs) => (routeKey, {
10837
10951
  ...rscEnabled ? {
10838
10952
  initialHeaders: {
10839
10953
  "content-type": rscContentTypeHeader,
10840
- vary: rscVaryHeader
10954
+ vary: rscVaryHeader,
10955
+ ...experimentalPPR && rscDidPostponeHeader ? { [rscDidPostponeHeader]: "1" } : {}
10841
10956
  }
10842
10957
  } : {}
10843
10958
  });
@@ -11877,13 +11992,16 @@ async function serverBuild({
11877
11992
  inversedAppPathManifest[appPathRoutesManifest[ogRoute]] = ogRoute;
11878
11993
  }
11879
11994
  }
11995
+ const experimental = {
11996
+ ppr: requiredServerFilesManifest.config.experimental?.ppr === true
11997
+ };
11880
11998
  let appRscPrefetches = {};
11881
11999
  let appBuildTraces = {};
11882
12000
  let appDir = null;
11883
12001
  if (appPathRoutesManifest) {
11884
12002
  appDir = import_path4.default.join(pagesDir, "../app");
11885
12003
  appBuildTraces = await (0, import_build_utils2.glob)("**/*.js.nft.json", appDir);
11886
- appRscPrefetches = await (0, import_build_utils2.glob)(`**/*${RSC_PREFETCH_SUFFIX}`, appDir);
12004
+ appRscPrefetches = experimental.ppr ? {} : await (0, import_build_utils2.glob)(`**/*${RSC_PREFETCH_SUFFIX}`, appDir);
11887
12005
  const rscContentTypeHeader = routesManifest?.rsc?.contentTypeHeader || RSC_CONTENT_TYPE;
11888
12006
  appRscPrefetches = normalizePrefetches(appRscPrefetches);
11889
12007
  for (const value of Object.values(appRscPrefetches)) {
@@ -11952,6 +12070,16 @@ async function serverBuild({
11952
12070
  if (lambdaPages["404.js"]) {
11953
12071
  internalPages.push("404.js");
11954
12072
  }
12073
+ const experimentalPPRRoutes = /* @__PURE__ */ new Set();
12074
+ for (const [route, { experimentalPPR }] of [
12075
+ ...Object.entries(prerenderManifest.staticRoutes),
12076
+ ...Object.entries(prerenderManifest.blockingFallbackRoutes),
12077
+ ...Object.entries(prerenderManifest.fallbackRoutes)
12078
+ ]) {
12079
+ if (!experimentalPPR)
12080
+ continue;
12081
+ experimentalPPRRoutes.add(route);
12082
+ }
11955
12083
  const prerenderRoutes = /* @__PURE__ */ new Set([
11956
12084
  ...canUsePreviewMode ? omittedPrerenderRoutes : [],
11957
12085
  ...Object.keys(prerenderManifest.blockingFallbackRoutes),
@@ -11961,6 +12089,7 @@ async function serverBuild({
11961
12089
  return staticRoute.srcRoute || route;
11962
12090
  })
11963
12091
  ]);
12092
+ const experimentalStreamingLambdaPaths = /* @__PURE__ */ new Map();
11964
12093
  if (hasLambdas) {
11965
12094
  const initialTracingLabel = "Traced Next.js server files in";
11966
12095
  console.time(initialTracingLabel);
@@ -12206,8 +12335,8 @@ async function serverBuild({
12206
12335
  "utf8"
12207
12336
  );
12208
12337
  let launcher = launcherData.replace(
12209
- "conf: __NEXT_CONFIG__",
12210
- `conf: ${JSON.stringify({
12338
+ "const conf = __NEXT_CONFIG__",
12339
+ `const conf = ${JSON.stringify({
12211
12340
  ...requiredServerFilesManifest.config,
12212
12341
  distDir: import_path4.default.relative(
12213
12342
  projectDir,
@@ -12354,6 +12483,7 @@ async function serverBuild({
12354
12483
  prerenderRoutes,
12355
12484
  pageTraces,
12356
12485
  compressedPages,
12486
+ experimentalPPRRoutes: void 0,
12357
12487
  tracedPseudoLayer: tracedPseudoLayer.pseudoLayer,
12358
12488
  initialPseudoLayer,
12359
12489
  lambdaCompressedByteLimit,
@@ -12372,6 +12502,7 @@ async function serverBuild({
12372
12502
  prerenderRoutes,
12373
12503
  pageTraces,
12374
12504
  compressedPages,
12505
+ experimentalPPRRoutes,
12375
12506
  tracedPseudoLayer: tracedPseudoLayer.pseudoLayer,
12376
12507
  initialPseudoLayer,
12377
12508
  lambdaCompressedByteLimit,
@@ -12387,6 +12518,7 @@ async function serverBuild({
12387
12518
  prerenderRoutes,
12388
12519
  pageTraces,
12389
12520
  compressedPages,
12521
+ experimentalPPRRoutes: void 0,
12390
12522
  tracedPseudoLayer: tracedPseudoLayer.pseudoLayer,
12391
12523
  initialPseudoLayer,
12392
12524
  lambdaCompressedByteLimit,
@@ -12395,7 +12527,7 @@ async function serverBuild({
12395
12527
  pageExtensions
12396
12528
  });
12397
12529
  for (const group of appRouterLambdaGroups) {
12398
- if (!group.isPrerenders) {
12530
+ if (!group.isPrerenders || group.isExperimentalPPR) {
12399
12531
  group.isStreaming = true;
12400
12532
  }
12401
12533
  group.isAppRouter = true;
@@ -12415,6 +12547,7 @@ async function serverBuild({
12415
12547
  prerenderRoutes,
12416
12548
  pageTraces,
12417
12549
  compressedPages,
12550
+ experimentalPPRRoutes: void 0,
12418
12551
  tracedPseudoLayer: tracedPseudoLayer.pseudoLayer,
12419
12552
  initialPseudoLayer,
12420
12553
  initialPseudoLayerUncompressed: uncompressedInitialSize,
@@ -12529,7 +12662,7 @@ async function serverBuild({
12529
12662
  [import_path4.default.join(import_path4.default.relative(baseDir, projectDir), "___next_launcher.cjs")]: new import_build_utils2.FileBlob({ data: group.isAppRouter ? appLauncher : launcher })
12530
12663
  };
12531
12664
  const operationType = getOperationType({ group, prerenderManifest });
12532
- const lambda = await createLambdaFromPseudoLayers({
12665
+ const options = {
12533
12666
  files: {
12534
12667
  ...launcherFiles,
12535
12668
  ...updatedManifestFiles
@@ -12545,7 +12678,19 @@ async function serverBuild({
12545
12678
  maxDuration: group.maxDuration,
12546
12679
  isStreaming: group.isStreaming,
12547
12680
  nextVersion
12548
- });
12681
+ };
12682
+ const lambda = await createLambdaFromPseudoLayers(options);
12683
+ const isPPR = experimental.ppr && group.isAppRouter && !group.isAppRouteHandler;
12684
+ let revalidate;
12685
+ if (isPPR) {
12686
+ if (isPPR && !options.isStreaming) {
12687
+ throw new Error("Invariant: PPR lambda isn't streaming");
12688
+ }
12689
+ revalidate = await createLambdaFromPseudoLayers({
12690
+ ...options,
12691
+ isStreaming: false
12692
+ });
12693
+ }
12549
12694
  for (const page of group.pages) {
12550
12695
  const pageNoExt = page.replace(/\.js$/, "");
12551
12696
  let isPrerender = prerenderRoutes.has(
@@ -12558,10 +12703,25 @@ async function serverBuild({
12558
12703
  );
12559
12704
  });
12560
12705
  }
12561
- const outputName = normalizeIndexOutput(
12706
+ let outputName = normalizeIndexOutput(
12562
12707
  import_path4.default.posix.join(entryDirectory, pageNoExt),
12563
12708
  true
12564
12709
  );
12710
+ if (isPPR) {
12711
+ if (!revalidate) {
12712
+ throw new Error("Invariant: PPR lambda isn't set");
12713
+ }
12714
+ outputName = import_path4.default.posix.join(entryDirectory, pageNoExt);
12715
+ lambdas[outputName] = revalidate;
12716
+ const pprOutputName = import_path4.default.posix.join(
12717
+ entryDirectory,
12718
+ "/_next/postponed/resume",
12719
+ pageNoExt
12720
+ );
12721
+ lambdas[pprOutputName] = lambda;
12722
+ experimentalStreamingLambdaPaths.set(outputName, pprOutputName);
12723
+ continue;
12724
+ }
12565
12725
  if (i18n && !isPrerender && !group.isAppRouter && (!isCorrectLocaleAPIRoutes || !(pageNoExt === "api" || pageNoExt.startsWith("api/")))) {
12566
12726
  for (const locale of i18n.locales) {
12567
12727
  lambdas[normalizeIndexOutput(
@@ -12585,6 +12745,7 @@ async function serverBuild({
12585
12745
  pagesDir,
12586
12746
  pageLambdaMap: {},
12587
12747
  lambdas,
12748
+ experimentalStreamingLambdaPaths,
12588
12749
  prerenders,
12589
12750
  entryDirectory,
12590
12751
  routesManifest,
@@ -12599,21 +12760,31 @@ async function serverBuild({
12599
12760
  isCorrectNotFoundRoutes,
12600
12761
  isEmptyAllowQueryForPrendered
12601
12762
  });
12602
- Object.keys(prerenderManifest.staticRoutes).forEach(
12603
- (route) => prerenderRoute(route, {})
12763
+ await Promise.all(
12764
+ Object.keys(prerenderManifest.staticRoutes).map(
12765
+ (route) => prerenderRoute(route, {})
12766
+ )
12604
12767
  );
12605
- Object.keys(prerenderManifest.fallbackRoutes).forEach(
12606
- (route) => prerenderRoute(route, { isFallback: true })
12768
+ await Promise.all(
12769
+ Object.keys(prerenderManifest.fallbackRoutes).map(
12770
+ (route) => prerenderRoute(route, { isFallback: true })
12771
+ )
12607
12772
  );
12608
- Object.keys(prerenderManifest.blockingFallbackRoutes).forEach(
12609
- (route) => prerenderRoute(route, { isBlocking: true })
12773
+ await Promise.all(
12774
+ Object.keys(prerenderManifest.blockingFallbackRoutes).map(
12775
+ (route) => prerenderRoute(route, { isBlocking: true })
12776
+ )
12610
12777
  );
12611
12778
  if (static404Page && canUsePreviewMode) {
12612
- omittedPrerenderRoutes.forEach((route) => {
12613
- prerenderRoute(route, { isOmitted: true });
12614
- });
12779
+ await Promise.all(
12780
+ [...omittedPrerenderRoutes].map((route) => {
12781
+ return prerenderRoute(route, { isOmitted: true });
12782
+ })
12783
+ );
12615
12784
  }
12616
12785
  prerenderRoutes.forEach((route) => {
12786
+ if (experimentalPPRRoutes.has(route))
12787
+ return;
12617
12788
  if (routesManifest?.i18n) {
12618
12789
  route = normalizeLocalePath(route, routesManifest.i18n.locales).pathname;
12619
12790
  }
@@ -12643,7 +12814,8 @@ async function serverBuild({
12643
12814
  canUsePreviewMode,
12644
12815
  prerenderManifest.bypassToken || "",
12645
12816
  true,
12646
- middleware.dynamicRouteMap
12817
+ middleware.dynamicRouteMap,
12818
+ experimental.ppr
12647
12819
  ).then(
12648
12820
  (arr) => localizeDynamicRoutes(
12649
12821
  arr,
@@ -12783,20 +12955,20 @@ async function serverBuild({
12783
12955
  }
12784
12956
  if (appPathRoutesManifest) {
12785
12957
  const edgeFunctions = middleware.edgeFunctions;
12786
- for (let route of Object.values(appPathRoutesManifest)) {
12958
+ for (const route of Object.values(appPathRoutesManifest)) {
12787
12959
  const ogRoute = inversedAppPathManifest[route];
12788
12960
  if (ogRoute.endsWith("/route")) {
12789
12961
  continue;
12790
12962
  }
12791
- route = normalizeIndexOutput(
12963
+ const pathname = normalizeIndexOutput(
12792
12964
  import_path4.default.posix.join("./", entryDirectory, route === "/" ? "/index" : route),
12793
12965
  true
12794
12966
  );
12795
- if (lambdas[route]) {
12796
- lambdas[`${route}.rsc`] = lambdas[route];
12967
+ if (lambdas[pathname]) {
12968
+ lambdas[`${pathname}.rsc`] = lambdas[pathname];
12797
12969
  }
12798
- if (edgeFunctions[route]) {
12799
- edgeFunctions[`${route}.rsc`] = edgeFunctions[route];
12970
+ if (edgeFunctions[pathname]) {
12971
+ edgeFunctions[`${pathname}.rsc`] = edgeFunctions[pathname];
12800
12972
  }
12801
12973
  }
12802
12974
  }
@@ -12809,6 +12981,9 @@ async function serverBuild({
12809
12981
  ...value,
12810
12982
  metadata: value.metadata ?? {}
12811
12983
  })) : [];
12984
+ if (experimental.ppr && !rscPrefetchHeader) {
12985
+ throw new Error("Invariant: cannot use PPR without 'rsc.prefetchHeader'");
12986
+ }
12812
12987
  return {
12813
12988
  wildcard: wildcardConfig,
12814
12989
  images: getImagesConfig(imagesManifest),
@@ -13091,7 +13266,7 @@ async function serverBuild({
13091
13266
  check: true
13092
13267
  }
13093
13268
  ] : [],
13094
- ...rscPrefetchHeader ? [
13269
+ ...rscPrefetchHeader && !experimental.ppr ? [
13095
13270
  {
13096
13271
  src: import_path4.default.posix.join(
13097
13272
  "/",
@@ -13114,7 +13289,11 @@ async function serverBuild({
13114
13289
  entryDirectory,
13115
13290
  `/(.+?)${RSC_PREFETCH_SUFFIX}(?:/)?$`
13116
13291
  )}`,
13117
- dest: import_path4.default.posix.join("/", entryDirectory, "/$1.rsc"),
13292
+ dest: import_path4.default.posix.join(
13293
+ "/",
13294
+ entryDirectory,
13295
+ `/$1${experimental.ppr ? RSC_PREFETCH_SUFFIX : ".rsc"}`
13296
+ ),
13118
13297
  has: [
13119
13298
  {
13120
13299
  type: "header",
@@ -13285,8 +13464,6 @@ async function serverBuild({
13285
13464
  continue: true,
13286
13465
  important: true
13287
13466
  },
13288
- // TODO: remove below workaround when `/` is allowed to be output
13289
- // different than `/index`
13290
13467
  {
13291
13468
  src: import_path4.default.posix.join("/", entryDirectory, "/index"),
13292
13469
  headers: {
@@ -14472,7 +14649,8 @@ More info: http://err.sh/vercel/vercel/next-functions-config-optimized-lambdas`
14472
14649
  lambdaCompressedByteLimit,
14473
14650
  // internal pages are already referenced in traces for serverless
14474
14651
  // like builds
14475
- internalPages: []
14652
+ internalPages: [],
14653
+ experimentalPPRRoutes: void 0
14476
14654
  });
14477
14655
  const initialApiLambdaGroups = await getPageLambdaGroups({
14478
14656
  entryPath,
@@ -14486,7 +14664,8 @@ More info: http://err.sh/vercel/vercel/next-functions-config-optimized-lambdas`
14486
14664
  initialPseudoLayer: { pseudoLayer: {}, pseudoLayerBytes: 0 },
14487
14665
  initialPseudoLayerUncompressed: 0,
14488
14666
  lambdaCompressedByteLimit,
14489
- internalPages: []
14667
+ internalPages: [],
14668
+ experimentalPPRRoutes: void 0
14490
14669
  });
14491
14670
  for (const group of initialApiLambdaGroups) {
14492
14671
  group.isApiLambda = true;
@@ -14894,6 +15073,7 @@ More info: http://err.sh/vercel/vercel/next-functions-config-optimized-lambdas`
14894
15073
  static404Page,
14895
15074
  pageLambdaMap,
14896
15075
  lambdas,
15076
+ experimentalStreamingLambdaPaths: void 0,
14897
15077
  isServerMode,
14898
15078
  prerenders,
14899
15079
  entryDirectory,
@@ -14921,20 +15101,40 @@ More info: http://err.sh/vercel/vercel/next-functions-config-optimized-lambdas`
14921
15101
  [
14922
15102
  ...Object.entries(prerenderManifest.fallbackRoutes),
14923
15103
  ...Object.entries(prerenderManifest.blockingFallbackRoutes)
14924
- ].forEach(([, { dataRouteRegex, dataRoute }]) => {
14925
- if (!dataRoute || !dataRouteRegex)
14926
- return;
14927
- dataRoutes.push({
14928
- // Next.js provided data route regex
14929
- src: dataRouteRegex.replace(
14930
- /^\^/,
14931
- `^${appMountPrefixNoTrailingSlash}`
14932
- ),
14933
- // Location of lambda in builder output
14934
- dest: import_path5.default.posix.join(entryDirectory, dataRoute),
14935
- check: true
14936
- });
14937
- });
15104
+ ].forEach(
15105
+ ([
15106
+ ,
15107
+ {
15108
+ dataRouteRegex,
15109
+ dataRoute,
15110
+ prefetchDataRouteRegex,
15111
+ prefetchDataRoute
15112
+ }
15113
+ ]) => {
15114
+ if (!dataRoute || !dataRouteRegex)
15115
+ return;
15116
+ dataRoutes.push({
15117
+ // Next.js provided data route regex
15118
+ src: dataRouteRegex.replace(
15119
+ /^\^/,
15120
+ `^${appMountPrefixNoTrailingSlash}`
15121
+ ),
15122
+ // Location of lambda in builder output
15123
+ dest: import_path5.default.posix.join(entryDirectory, dataRoute),
15124
+ check: true
15125
+ });
15126
+ if (!prefetchDataRoute || !prefetchDataRouteRegex)
15127
+ return;
15128
+ dataRoutes.push({
15129
+ src: prefetchDataRouteRegex.replace(
15130
+ /^\^/,
15131
+ `^${appMountPrefixNoTrailingSlash}`
15132
+ ),
15133
+ dest: import_path5.default.posix.join(entryDirectory, prefetchDataRoute),
15134
+ check: true
15135
+ });
15136
+ }
15137
+ );
14938
15138
  }
14939
15139
  }
14940
15140
  if (!isSharedLambdas) {
@@ -12,20 +12,23 @@ if (process.env.NODE_ENV !== "production" && region !== "dev1") {
12
12
  }
13
13
  // @preserve pre-next-server-target
14
14
  const NextServer = require("__NEXT_SERVER_PATH__").default;
15
+ const conf = __NEXT_CONFIG__;
15
16
  const nextServer = new NextServer({
16
- // @ts-ignore __NEXT_CONFIG__ value is injected
17
- conf: __NEXT_CONFIG__,
17
+ conf,
18
18
  dir: ".",
19
19
  minimalMode: true,
20
20
  customServer: false
21
21
  });
22
- const requestHandler = nextServer.getRequestHandler();
23
- module.exports = async (req, res) => {
22
+ const serve = (handler) => async (req, res) => {
24
23
  try {
25
24
  // @preserve entryDirectory handler
26
- await requestHandler(req, res);
25
+ await handler(req, res);
27
26
  } catch (err) {
28
27
  console.error(err);
29
28
  process.exit(1);
30
29
  }
31
30
  };
31
+ module.exports = serve(nextServer.getRequestHandler());
32
+ if (conf.experimental?.ppr && "getRequestHandlerWithMetadata" in nextServer && typeof nextServer.getRequestHandlerWithMetadata === "function") {
33
+ module.exports.getRequestHandlerWithMetadata = (metadata) => serve(nextServer.getRequestHandlerWithMetadata(metadata));
34
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/next",
3
- "version": "4.0.12",
3
+ "version": "4.0.13",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./dist/index",
6
6
  "homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",