@vercel/next 4.0.12 → 4.0.14

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,9 @@ var onPrerenderRoute = (prerenderRouteArgs) => (routeKey, {
10837
10951
  ...rscEnabled ? {
10838
10952
  initialHeaders: {
10839
10953
  "content-type": rscContentTypeHeader,
10840
- vary: rscVaryHeader
10954
+ vary: rscVaryHeader,
10955
+ // If it contains a pre-render, then it was postponed.
10956
+ ...prerender && rscDidPostponeHeader ? { [rscDidPostponeHeader]: "1" } : {}
10841
10957
  }
10842
10958
  } : {}
10843
10959
  });
@@ -11877,13 +11993,16 @@ async function serverBuild({
11877
11993
  inversedAppPathManifest[appPathRoutesManifest[ogRoute]] = ogRoute;
11878
11994
  }
11879
11995
  }
11996
+ const experimental = {
11997
+ ppr: requiredServerFilesManifest.config.experimental?.ppr === true
11998
+ };
11880
11999
  let appRscPrefetches = {};
11881
12000
  let appBuildTraces = {};
11882
12001
  let appDir = null;
11883
12002
  if (appPathRoutesManifest) {
11884
12003
  appDir = import_path4.default.join(pagesDir, "../app");
11885
12004
  appBuildTraces = await (0, import_build_utils2.glob)("**/*.js.nft.json", appDir);
11886
- appRscPrefetches = await (0, import_build_utils2.glob)(`**/*${RSC_PREFETCH_SUFFIX}`, appDir);
12005
+ appRscPrefetches = experimental.ppr ? {} : await (0, import_build_utils2.glob)(`**/*${RSC_PREFETCH_SUFFIX}`, appDir);
11887
12006
  const rscContentTypeHeader = routesManifest?.rsc?.contentTypeHeader || RSC_CONTENT_TYPE;
11888
12007
  appRscPrefetches = normalizePrefetches(appRscPrefetches);
11889
12008
  for (const value of Object.values(appRscPrefetches)) {
@@ -11952,6 +12071,16 @@ async function serverBuild({
11952
12071
  if (lambdaPages["404.js"]) {
11953
12072
  internalPages.push("404.js");
11954
12073
  }
12074
+ const experimentalPPRRoutes = /* @__PURE__ */ new Set();
12075
+ for (const [route, { experimentalPPR }] of [
12076
+ ...Object.entries(prerenderManifest.staticRoutes),
12077
+ ...Object.entries(prerenderManifest.blockingFallbackRoutes),
12078
+ ...Object.entries(prerenderManifest.fallbackRoutes)
12079
+ ]) {
12080
+ if (!experimentalPPR)
12081
+ continue;
12082
+ experimentalPPRRoutes.add(route);
12083
+ }
11955
12084
  const prerenderRoutes = /* @__PURE__ */ new Set([
11956
12085
  ...canUsePreviewMode ? omittedPrerenderRoutes : [],
11957
12086
  ...Object.keys(prerenderManifest.blockingFallbackRoutes),
@@ -11961,6 +12090,7 @@ async function serverBuild({
11961
12090
  return staticRoute.srcRoute || route;
11962
12091
  })
11963
12092
  ]);
12093
+ const experimentalStreamingLambdaPaths = /* @__PURE__ */ new Map();
11964
12094
  if (hasLambdas) {
11965
12095
  const initialTracingLabel = "Traced Next.js server files in";
11966
12096
  console.time(initialTracingLabel);
@@ -12206,8 +12336,8 @@ async function serverBuild({
12206
12336
  "utf8"
12207
12337
  );
12208
12338
  let launcher = launcherData.replace(
12209
- "conf: __NEXT_CONFIG__",
12210
- `conf: ${JSON.stringify({
12339
+ "const conf = __NEXT_CONFIG__",
12340
+ `const conf = ${JSON.stringify({
12211
12341
  ...requiredServerFilesManifest.config,
12212
12342
  distDir: import_path4.default.relative(
12213
12343
  projectDir,
@@ -12354,6 +12484,7 @@ async function serverBuild({
12354
12484
  prerenderRoutes,
12355
12485
  pageTraces,
12356
12486
  compressedPages,
12487
+ experimentalPPRRoutes: void 0,
12357
12488
  tracedPseudoLayer: tracedPseudoLayer.pseudoLayer,
12358
12489
  initialPseudoLayer,
12359
12490
  lambdaCompressedByteLimit,
@@ -12372,6 +12503,7 @@ async function serverBuild({
12372
12503
  prerenderRoutes,
12373
12504
  pageTraces,
12374
12505
  compressedPages,
12506
+ experimentalPPRRoutes,
12375
12507
  tracedPseudoLayer: tracedPseudoLayer.pseudoLayer,
12376
12508
  initialPseudoLayer,
12377
12509
  lambdaCompressedByteLimit,
@@ -12387,6 +12519,7 @@ async function serverBuild({
12387
12519
  prerenderRoutes,
12388
12520
  pageTraces,
12389
12521
  compressedPages,
12522
+ experimentalPPRRoutes: void 0,
12390
12523
  tracedPseudoLayer: tracedPseudoLayer.pseudoLayer,
12391
12524
  initialPseudoLayer,
12392
12525
  lambdaCompressedByteLimit,
@@ -12395,7 +12528,7 @@ async function serverBuild({
12395
12528
  pageExtensions
12396
12529
  });
12397
12530
  for (const group of appRouterLambdaGroups) {
12398
- if (!group.isPrerenders) {
12531
+ if (!group.isPrerenders || group.isExperimentalPPR) {
12399
12532
  group.isStreaming = true;
12400
12533
  }
12401
12534
  group.isAppRouter = true;
@@ -12415,6 +12548,7 @@ async function serverBuild({
12415
12548
  prerenderRoutes,
12416
12549
  pageTraces,
12417
12550
  compressedPages,
12551
+ experimentalPPRRoutes: void 0,
12418
12552
  tracedPseudoLayer: tracedPseudoLayer.pseudoLayer,
12419
12553
  initialPseudoLayer,
12420
12554
  initialPseudoLayerUncompressed: uncompressedInitialSize,
@@ -12529,7 +12663,7 @@ async function serverBuild({
12529
12663
  [import_path4.default.join(import_path4.default.relative(baseDir, projectDir), "___next_launcher.cjs")]: new import_build_utils2.FileBlob({ data: group.isAppRouter ? appLauncher : launcher })
12530
12664
  };
12531
12665
  const operationType = getOperationType({ group, prerenderManifest });
12532
- const lambda = await createLambdaFromPseudoLayers({
12666
+ const options = {
12533
12667
  files: {
12534
12668
  ...launcherFiles,
12535
12669
  ...updatedManifestFiles
@@ -12545,7 +12679,19 @@ async function serverBuild({
12545
12679
  maxDuration: group.maxDuration,
12546
12680
  isStreaming: group.isStreaming,
12547
12681
  nextVersion
12548
- });
12682
+ };
12683
+ const lambda = await createLambdaFromPseudoLayers(options);
12684
+ const isPPR = experimental.ppr && group.isAppRouter && !group.isAppRouteHandler;
12685
+ let revalidate;
12686
+ if (isPPR) {
12687
+ if (isPPR && !options.isStreaming) {
12688
+ throw new Error("Invariant: PPR lambda isn't streaming");
12689
+ }
12690
+ revalidate = await createLambdaFromPseudoLayers({
12691
+ ...options,
12692
+ isStreaming: false
12693
+ });
12694
+ }
12549
12695
  for (const page of group.pages) {
12550
12696
  const pageNoExt = page.replace(/\.js$/, "");
12551
12697
  let isPrerender = prerenderRoutes.has(
@@ -12558,10 +12704,25 @@ async function serverBuild({
12558
12704
  );
12559
12705
  });
12560
12706
  }
12561
- const outputName = normalizeIndexOutput(
12707
+ let outputName = normalizeIndexOutput(
12562
12708
  import_path4.default.posix.join(entryDirectory, pageNoExt),
12563
12709
  true
12564
12710
  );
12711
+ if (isPPR) {
12712
+ if (!revalidate) {
12713
+ throw new Error("Invariant: PPR lambda isn't set");
12714
+ }
12715
+ outputName = import_path4.default.posix.join(entryDirectory, pageNoExt);
12716
+ lambdas[outputName] = revalidate;
12717
+ const pprOutputName = import_path4.default.posix.join(
12718
+ entryDirectory,
12719
+ "/_next/postponed/resume",
12720
+ pageNoExt
12721
+ );
12722
+ lambdas[pprOutputName] = lambda;
12723
+ experimentalStreamingLambdaPaths.set(outputName, pprOutputName);
12724
+ continue;
12725
+ }
12565
12726
  if (i18n && !isPrerender && !group.isAppRouter && (!isCorrectLocaleAPIRoutes || !(pageNoExt === "api" || pageNoExt.startsWith("api/")))) {
12566
12727
  for (const locale of i18n.locales) {
12567
12728
  lambdas[normalizeIndexOutput(
@@ -12585,6 +12746,7 @@ async function serverBuild({
12585
12746
  pagesDir,
12586
12747
  pageLambdaMap: {},
12587
12748
  lambdas,
12749
+ experimentalStreamingLambdaPaths,
12588
12750
  prerenders,
12589
12751
  entryDirectory,
12590
12752
  routesManifest,
@@ -12599,21 +12761,31 @@ async function serverBuild({
12599
12761
  isCorrectNotFoundRoutes,
12600
12762
  isEmptyAllowQueryForPrendered
12601
12763
  });
12602
- Object.keys(prerenderManifest.staticRoutes).forEach(
12603
- (route) => prerenderRoute(route, {})
12764
+ await Promise.all(
12765
+ Object.keys(prerenderManifest.staticRoutes).map(
12766
+ (route) => prerenderRoute(route, {})
12767
+ )
12604
12768
  );
12605
- Object.keys(prerenderManifest.fallbackRoutes).forEach(
12606
- (route) => prerenderRoute(route, { isFallback: true })
12769
+ await Promise.all(
12770
+ Object.keys(prerenderManifest.fallbackRoutes).map(
12771
+ (route) => prerenderRoute(route, { isFallback: true })
12772
+ )
12607
12773
  );
12608
- Object.keys(prerenderManifest.blockingFallbackRoutes).forEach(
12609
- (route) => prerenderRoute(route, { isBlocking: true })
12774
+ await Promise.all(
12775
+ Object.keys(prerenderManifest.blockingFallbackRoutes).map(
12776
+ (route) => prerenderRoute(route, { isBlocking: true })
12777
+ )
12610
12778
  );
12611
12779
  if (static404Page && canUsePreviewMode) {
12612
- omittedPrerenderRoutes.forEach((route) => {
12613
- prerenderRoute(route, { isOmitted: true });
12614
- });
12780
+ await Promise.all(
12781
+ [...omittedPrerenderRoutes].map((route) => {
12782
+ return prerenderRoute(route, { isOmitted: true });
12783
+ })
12784
+ );
12615
12785
  }
12616
12786
  prerenderRoutes.forEach((route) => {
12787
+ if (experimentalPPRRoutes.has(route))
12788
+ return;
12617
12789
  if (routesManifest?.i18n) {
12618
12790
  route = normalizeLocalePath(route, routesManifest.i18n.locales).pathname;
12619
12791
  }
@@ -12643,7 +12815,8 @@ async function serverBuild({
12643
12815
  canUsePreviewMode,
12644
12816
  prerenderManifest.bypassToken || "",
12645
12817
  true,
12646
- middleware.dynamicRouteMap
12818
+ middleware.dynamicRouteMap,
12819
+ experimental.ppr
12647
12820
  ).then(
12648
12821
  (arr) => localizeDynamicRoutes(
12649
12822
  arr,
@@ -12783,20 +12956,20 @@ async function serverBuild({
12783
12956
  }
12784
12957
  if (appPathRoutesManifest) {
12785
12958
  const edgeFunctions = middleware.edgeFunctions;
12786
- for (let route of Object.values(appPathRoutesManifest)) {
12959
+ for (const route of Object.values(appPathRoutesManifest)) {
12787
12960
  const ogRoute = inversedAppPathManifest[route];
12788
12961
  if (ogRoute.endsWith("/route")) {
12789
12962
  continue;
12790
12963
  }
12791
- route = normalizeIndexOutput(
12964
+ const pathname = normalizeIndexOutput(
12792
12965
  import_path4.default.posix.join("./", entryDirectory, route === "/" ? "/index" : route),
12793
12966
  true
12794
12967
  );
12795
- if (lambdas[route]) {
12796
- lambdas[`${route}.rsc`] = lambdas[route];
12968
+ if (lambdas[pathname]) {
12969
+ lambdas[`${pathname}.rsc`] = lambdas[pathname];
12797
12970
  }
12798
- if (edgeFunctions[route]) {
12799
- edgeFunctions[`${route}.rsc`] = edgeFunctions[route];
12971
+ if (edgeFunctions[pathname]) {
12972
+ edgeFunctions[`${pathname}.rsc`] = edgeFunctions[pathname];
12800
12973
  }
12801
12974
  }
12802
12975
  }
@@ -12809,6 +12982,9 @@ async function serverBuild({
12809
12982
  ...value,
12810
12983
  metadata: value.metadata ?? {}
12811
12984
  })) : [];
12985
+ if (experimental.ppr && !rscPrefetchHeader) {
12986
+ throw new Error("Invariant: cannot use PPR without 'rsc.prefetchHeader'");
12987
+ }
12812
12988
  return {
12813
12989
  wildcard: wildcardConfig,
12814
12990
  images: getImagesConfig(imagesManifest),
@@ -13091,7 +13267,7 @@ async function serverBuild({
13091
13267
  check: true
13092
13268
  }
13093
13269
  ] : [],
13094
- ...rscPrefetchHeader ? [
13270
+ ...rscPrefetchHeader && !experimental.ppr ? [
13095
13271
  {
13096
13272
  src: import_path4.default.posix.join(
13097
13273
  "/",
@@ -13114,7 +13290,11 @@ async function serverBuild({
13114
13290
  entryDirectory,
13115
13291
  `/(.+?)${RSC_PREFETCH_SUFFIX}(?:/)?$`
13116
13292
  )}`,
13117
- dest: import_path4.default.posix.join("/", entryDirectory, "/$1.rsc"),
13293
+ dest: import_path4.default.posix.join(
13294
+ "/",
13295
+ entryDirectory,
13296
+ `/$1${experimental.ppr ? RSC_PREFETCH_SUFFIX : ".rsc"}`
13297
+ ),
13118
13298
  has: [
13119
13299
  {
13120
13300
  type: "header",
@@ -13285,8 +13465,6 @@ async function serverBuild({
13285
13465
  continue: true,
13286
13466
  important: true
13287
13467
  },
13288
- // TODO: remove below workaround when `/` is allowed to be output
13289
- // different than `/index`
13290
13468
  {
13291
13469
  src: import_path4.default.posix.join("/", entryDirectory, "/index"),
13292
13470
  headers: {
@@ -14472,7 +14650,8 @@ More info: http://err.sh/vercel/vercel/next-functions-config-optimized-lambdas`
14472
14650
  lambdaCompressedByteLimit,
14473
14651
  // internal pages are already referenced in traces for serverless
14474
14652
  // like builds
14475
- internalPages: []
14653
+ internalPages: [],
14654
+ experimentalPPRRoutes: void 0
14476
14655
  });
14477
14656
  const initialApiLambdaGroups = await getPageLambdaGroups({
14478
14657
  entryPath,
@@ -14486,7 +14665,8 @@ More info: http://err.sh/vercel/vercel/next-functions-config-optimized-lambdas`
14486
14665
  initialPseudoLayer: { pseudoLayer: {}, pseudoLayerBytes: 0 },
14487
14666
  initialPseudoLayerUncompressed: 0,
14488
14667
  lambdaCompressedByteLimit,
14489
- internalPages: []
14668
+ internalPages: [],
14669
+ experimentalPPRRoutes: void 0
14490
14670
  });
14491
14671
  for (const group of initialApiLambdaGroups) {
14492
14672
  group.isApiLambda = true;
@@ -14894,6 +15074,7 @@ More info: http://err.sh/vercel/vercel/next-functions-config-optimized-lambdas`
14894
15074
  static404Page,
14895
15075
  pageLambdaMap,
14896
15076
  lambdas,
15077
+ experimentalStreamingLambdaPaths: void 0,
14897
15078
  isServerMode,
14898
15079
  prerenders,
14899
15080
  entryDirectory,
@@ -14921,20 +15102,40 @@ More info: http://err.sh/vercel/vercel/next-functions-config-optimized-lambdas`
14921
15102
  [
14922
15103
  ...Object.entries(prerenderManifest.fallbackRoutes),
14923
15104
  ...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
- });
15105
+ ].forEach(
15106
+ ([
15107
+ ,
15108
+ {
15109
+ dataRouteRegex,
15110
+ dataRoute,
15111
+ prefetchDataRouteRegex,
15112
+ prefetchDataRoute
15113
+ }
15114
+ ]) => {
15115
+ if (!dataRoute || !dataRouteRegex)
15116
+ return;
15117
+ dataRoutes.push({
15118
+ // Next.js provided data route regex
15119
+ src: dataRouteRegex.replace(
15120
+ /^\^/,
15121
+ `^${appMountPrefixNoTrailingSlash}`
15122
+ ),
15123
+ // Location of lambda in builder output
15124
+ dest: import_path5.default.posix.join(entryDirectory, dataRoute),
15125
+ check: true
15126
+ });
15127
+ if (!prefetchDataRoute || !prefetchDataRouteRegex)
15128
+ return;
15129
+ dataRoutes.push({
15130
+ src: prefetchDataRouteRegex.replace(
15131
+ /^\^/,
15132
+ `^${appMountPrefixNoTrailingSlash}`
15133
+ ),
15134
+ dest: import_path5.default.posix.join(entryDirectory, prefetchDataRoute),
15135
+ check: true
15136
+ });
15137
+ }
15138
+ );
14938
15139
  }
14939
15140
  }
14940
15141
  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.14",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./dist/index",
6
6
  "homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",