@vercel/next 3.2.5 → 3.2.7

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.
@@ -69,7 +69,7 @@ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs
69
69
  const lstatResults = {};
70
70
  const nonLambdaSsgPages = new Set();
71
71
  Object.keys(prerenderManifest.staticRoutes).forEach(route => {
72
- const result = (0, utils_1.onPrerenderRouteInitial)(prerenderManifest, canUsePreviewMode, entryDirectory, nonLambdaSsgPages, route, routesManifest.pages404, routesManifest);
72
+ const result = (0, utils_1.onPrerenderRouteInitial)(prerenderManifest, canUsePreviewMode, entryDirectory, nonLambdaSsgPages, route, routesManifest.pages404, routesManifest, appDir);
73
73
  if (result && result.static404Page) {
74
74
  static404Page = result.static404Page;
75
75
  }
@@ -143,6 +143,7 @@ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs
143
143
  console.time(lambdaCreationLabel);
144
144
  const apiPages = [];
145
145
  const nonApiPages = [];
146
+ const streamingPages = [];
146
147
  lambdaPageKeys.forEach(page => {
147
148
  if (internalPages.includes(page) &&
148
149
  page !== '404.js' &&
@@ -159,6 +160,9 @@ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs
159
160
  if (pageMatchesApi(page)) {
160
161
  apiPages.push(page);
161
162
  }
163
+ else if (appDir && lambdaAppPaths[page]) {
164
+ streamingPages.push(page);
165
+ }
162
166
  else {
163
167
  nonApiPages.push(page);
164
168
  }
@@ -269,7 +273,12 @@ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs
269
273
  };
270
274
  const pageTraces = {};
271
275
  const compressedPages = {};
272
- const mergedPageKeys = [...nonApiPages, ...apiPages, ...internalPages];
276
+ const mergedPageKeys = [
277
+ ...nonApiPages,
278
+ ...streamingPages,
279
+ ...apiPages,
280
+ ...internalPages,
281
+ ];
273
282
  const traceCache = {};
274
283
  const getOriginalPagePath = (page) => {
275
284
  let originalPagePath = page;
@@ -371,6 +380,25 @@ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs
371
380
  internalPages,
372
381
  pageExtensions,
373
382
  });
383
+ const streamingPageLambdaGroups = await (0, utils_1.getPageLambdaGroups)({
384
+ entryPath: requiredServerFilesManifest.appDir || entryPath,
385
+ config,
386
+ pages: streamingPages,
387
+ prerenderRoutes,
388
+ pageTraces,
389
+ compressedPages,
390
+ tracedPseudoLayer: tracedPseudoLayer.pseudoLayer,
391
+ initialPseudoLayer,
392
+ lambdaCompressedByteLimit,
393
+ initialPseudoLayerUncompressed: uncompressedInitialSize,
394
+ internalPages,
395
+ pageExtensions,
396
+ });
397
+ for (const group of streamingPageLambdaGroups) {
398
+ if (!group.isPrerenders) {
399
+ group.isStreaming = true;
400
+ }
401
+ }
374
402
  const apiLambdaGroups = await (0, utils_1.getPageLambdaGroups)({
375
403
  entryPath: requiredServerFilesManifest.appDir || entryPath,
376
404
  config,
@@ -397,9 +425,19 @@ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs
397
425
  pseudoLayerBytes: group.pseudoLayerBytes,
398
426
  uncompressedLayerBytes: group.pseudoLayerUncompressedBytes,
399
427
  })),
428
+ streamingPageLambdaGroups: streamingPageLambdaGroups.map(group => ({
429
+ pages: group.pages,
430
+ isPrerender: group.isPrerenders,
431
+ pseudoLayerBytes: group.pseudoLayerBytes,
432
+ uncompressedLayerBytes: group.pseudoLayerUncompressedBytes,
433
+ })),
400
434
  nextServerLayerSize: initialPseudoLayer.pseudoLayerBytes,
401
435
  }, null, 2));
402
- const combinedGroups = [...pageLambdaGroups, ...apiLambdaGroups];
436
+ const combinedGroups = [
437
+ ...pageLambdaGroups,
438
+ ...streamingPageLambdaGroups,
439
+ ...apiLambdaGroups,
440
+ ];
403
441
  await (0, utils_1.detectLambdaLimitExceeding)(combinedGroups, lambdaCompressedByteLimit, compressedPages);
404
442
  for (const group of combinedGroups) {
405
443
  const groupPageFiles = {};
@@ -467,6 +505,7 @@ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs
467
505
  memory: group.memory,
468
506
  runtime: nodeVersion.runtime,
469
507
  maxDuration: group.maxDuration,
508
+ isStreaming: group.isStreaming,
470
509
  });
471
510
  for (const page of group.pages) {
472
511
  const pageNoExt = page.replace(/\.js$/, '');
@@ -537,48 +576,6 @@ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs
537
576
  semver_1.default.gte(nextVersion, NEXT_DATA_MIDDLEWARE_RESOLVING_VERSION);
538
577
  const dynamicRoutes = await (0, utils_1.getDynamicRoutes)(entryPath, entryDirectory, dynamicPages, false, routesManifest, omittedPrerenderRoutes, canUsePreviewMode, prerenderManifest.bypassToken || '', true, middleware.dynamicRouteMap).then(arr => (0, utils_1.localizeDynamicRoutes)(arr, dynamicPrefix, entryDirectory, staticPages, prerenderManifest, routesManifest, true, isCorrectLocaleAPIRoutes));
539
578
  const { staticFiles, publicDirectoryFiles, staticDirectoryFiles } = await (0, utils_1.getStaticFiles)(entryPath, entryDirectory, outputDirectory);
540
- const notFoundPreviewRoutes = [];
541
- if (prerenderManifest.notFoundRoutes?.length > 0 && canUsePreviewMode) {
542
- // we combine routes into one src here to reduce the number of needed
543
- // routes since only the status is being modified and we don't want
544
- // to exceed the routes limit
545
- const starterRouteSrc = `^${entryDirectory !== '.'
546
- ? `${path_1.default.posix.join('/', entryDirectory)}()`
547
- : '()'}`;
548
- let currentRouteSrc = starterRouteSrc;
549
- const pushRoute = (src) => {
550
- notFoundPreviewRoutes.push({
551
- src,
552
- missing: [
553
- {
554
- type: 'cookie',
555
- key: '__prerender_bypass',
556
- value: prerenderManifest.bypassToken || undefined,
557
- },
558
- {
559
- type: 'cookie',
560
- key: '__next_preview_data',
561
- },
562
- ],
563
- status: 404,
564
- });
565
- };
566
- for (let i = 0; i < prerenderManifest.notFoundRoutes.length; i++) {
567
- const route = prerenderManifest.notFoundRoutes[i];
568
- const isLastRoute = i === prerenderManifest.notFoundRoutes.length - 1;
569
- if (prerenderManifest.staticRoutes[route]?.initialRevalidate === false) {
570
- if (currentRouteSrc.length + route.length + 1 >= 4000) {
571
- pushRoute(currentRouteSrc);
572
- currentRouteSrc = starterRouteSrc;
573
- }
574
- // add to existing route src if src length limit isn't reached
575
- currentRouteSrc = `${currentRouteSrc.substring(0, currentRouteSrc.length - 1)}${currentRouteSrc[currentRouteSrc.length - 2] === '(' ? '' : '|'}${route}/?)`;
576
- if (isLastRoute) {
577
- pushRoute(currentRouteSrc);
578
- }
579
- }
580
- }
581
- }
582
579
  const normalizeNextDataRoute = (isOverride = false) => {
583
580
  return isNextDataServerResolving
584
581
  ? [
@@ -799,9 +796,6 @@ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs
799
796
  // beforeFiles rewrites as middleware is not a "file" route
800
797
  ...(isCorrectMiddlewareOrder ? middleware.staticRoutes : []),
801
798
  ...beforeFilesRewrites,
802
- // ensure prerender's for notFound: true static routes
803
- // have 404 status code when not in preview mode
804
- ...notFoundPreviewRoutes,
805
799
  // Make sure to 404 for the /404 path itself
806
800
  ...(i18n
807
801
  ? [
@@ -1039,18 +1033,6 @@ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs
1039
1033
  continue: true,
1040
1034
  important: true,
1041
1035
  },
1042
- ...(appDir
1043
- ? [
1044
- {
1045
- src: path_1.default.posix.join('/', entryDirectory, '/(.*).rsc$'),
1046
- headers: {
1047
- 'content-type': 'application/octet-stream',
1048
- },
1049
- continue: true,
1050
- important: true,
1051
- },
1052
- ]
1053
- : []),
1054
1036
  // TODO: remove below workaround when `/` is allowed to be output
1055
1037
  // different than `/index`
1056
1038
  {
package/dist/utils.js CHANGED
@@ -460,7 +460,7 @@ exports.createPseudoLayer = createPseudoLayer;
460
460
  // measured with 1, 2, 5, 10, and `os.cpus().length || 5`
461
461
  // and sema(1) produced the best results
462
462
  const createLambdaSema = new async_sema_1.Sema(1);
463
- async function createLambdaFromPseudoLayers({ files: baseFiles, layers, ...lambdaOptions }) {
463
+ async function createLambdaFromPseudoLayers({ files: baseFiles, layers, isStreaming, ...lambdaOptions }) {
464
464
  await createLambdaSema.acquire();
465
465
  const files = {};
466
466
  const addedFiles = new Set();
@@ -488,6 +488,11 @@ async function createLambdaFromPseudoLayers({ files: baseFiles, layers, ...lambd
488
488
  createLambdaSema.release();
489
489
  return new build_utils_1.NodejsLambda({
490
490
  ...lambdaOptions,
491
+ ...(isStreaming
492
+ ? {
493
+ experimentalResponseStreaming: true,
494
+ }
495
+ : {}),
491
496
  files,
492
497
  shouldAddHelpers: false,
493
498
  shouldAddSourcemapSupport: false,
@@ -982,13 +987,14 @@ const detectLambdaLimitExceeding = async (lambdaGroups, compressedSizeLimit, com
982
987
  };
983
988
  exports.detectLambdaLimitExceeding = detectLambdaLimitExceeding;
984
989
  // checks if prerender files are all static or not before creating lambdas
985
- const onPrerenderRouteInitial = (prerenderManifest, canUsePreviewMode, entryDirectory, nonLambdaSsgPages, routeKey, hasPages404, routesManifest) => {
990
+ const onPrerenderRouteInitial = (prerenderManifest, canUsePreviewMode, entryDirectory, nonLambdaSsgPages, routeKey, hasPages404, routesManifest, appDir) => {
986
991
  let static404Page;
987
992
  let static500Page;
988
993
  // Get the route file as it'd be mounted in the builder output
989
994
  const pr = prerenderManifest.staticRoutes[routeKey];
990
- const { initialRevalidate, srcRoute } = pr;
995
+ const { initialRevalidate, srcRoute, dataRoute } = pr;
991
996
  const route = srcRoute || routeKey;
997
+ const isAppPathRoute = appDir && dataRoute?.endsWith('.rsc');
992
998
  const routeNoLocale = routesManifest?.i18n
993
999
  ? normalizeLocalePath(routeKey, routesManifest.i18n.locales).pathname
994
1000
  : routeKey;
@@ -1000,7 +1006,11 @@ const onPrerenderRouteInitial = (prerenderManifest, canUsePreviewMode, entryDire
1000
1006
  if (routeNoLocale === '/500') {
1001
1007
  static500Page = path_1.default.posix.join(entryDirectory, routeKey);
1002
1008
  }
1003
- if (initialRevalidate === false &&
1009
+ if (
1010
+ // App paths must be Prerenders to ensure Vary header is
1011
+ // correctly added
1012
+ !isAppPathRoute &&
1013
+ initialRevalidate === false &&
1004
1014
  (!canUsePreviewMode || (hasPages404 && routeNoLocale === '/404')) &&
1005
1015
  !prerenderManifest.fallbackRoutes[route] &&
1006
1016
  !prerenderManifest.blockingFallbackRoutes[route]) {
@@ -1120,7 +1130,19 @@ const onPrerenderRoute = (prerenderRouteArgs) => (routeKey, { isBlocking, isFall
1120
1130
  ? dataRoute
1121
1131
  : routeFileNoExt + '.json'}`),
1122
1132
  });
1123
- const outputPathPage = normalizeIndexOutput(path_1.default.posix.join(entryDirectory, routeFileNoExt), isServerMode);
1133
+ if (isAppPathRoute) {
1134
+ // for literal index routes we need to append an additional /index
1135
+ // due to the proxy's normalizing for /index routes
1136
+ if (routeKey !== '/index' && routeKey.endsWith('/index')) {
1137
+ routeKey = `${routeKey}/index`;
1138
+ routeFileNoExt = routeKey;
1139
+ origRouteFileNoExt = routeKey;
1140
+ }
1141
+ }
1142
+ let outputPathPage = path_1.default.posix.join(entryDirectory, routeFileNoExt);
1143
+ if (!isAppPathRoute) {
1144
+ outputPathPage = normalizeIndexOutput(outputPathPage, isServerMode);
1145
+ }
1124
1146
  const outputPathPageOrig = path_1.default.posix.join(entryDirectory, origRouteFileNoExt);
1125
1147
  let lambda;
1126
1148
  let outputPathData = path_1.default.posix.join(entryDirectory, dataRoute);
@@ -1144,7 +1166,7 @@ const onPrerenderRoute = (prerenderRouteArgs) => (routeKey, { isBlocking, isFall
1144
1166
  : path_1.default.posix.join(entryDirectory, srcRoute === '/' ? '/index' : srcRoute), isServerMode);
1145
1167
  lambda = lambdas[outputSrcPathPage];
1146
1168
  }
1147
- if (!isNotFound && initialRevalidate === false) {
1169
+ if (!isAppPathRoute && !isNotFound && initialRevalidate === false) {
1148
1170
  if (htmlFsRef == null || jsonFsRef == null) {
1149
1171
  throw new build_utils_1.NowBuildError({
1150
1172
  code: 'NEXT_HTMLFSREF_JSONFSREF',
@@ -1218,6 +1240,18 @@ const onPrerenderRoute = (prerenderRouteArgs) => (routeKey, { isBlocking, isFall
1218
1240
  fallback: htmlFsRef,
1219
1241
  group: prerenderGroup,
1220
1242
  bypassToken: prerenderManifest.bypassToken,
1243
+ ...(isNotFound
1244
+ ? {
1245
+ initialStatus: 404,
1246
+ }
1247
+ : {}),
1248
+ ...(isAppPathRoute
1249
+ ? {
1250
+ initialHeaders: {
1251
+ vary: '__rsc__, __next_router_state_tree__, __next_router_prefetch__',
1252
+ },
1253
+ }
1254
+ : {}),
1221
1255
  });
1222
1256
  prerenders[outputPathData] = new build_utils_1.Prerender({
1223
1257
  expiration: initialRevalidate,
@@ -1226,6 +1260,19 @@ const onPrerenderRoute = (prerenderRouteArgs) => (routeKey, { isBlocking, isFall
1226
1260
  fallback: jsonFsRef,
1227
1261
  group: prerenderGroup,
1228
1262
  bypassToken: prerenderManifest.bypassToken,
1263
+ ...(isNotFound
1264
+ ? {
1265
+ initialStatus: 404,
1266
+ }
1267
+ : {}),
1268
+ ...(isAppPathRoute
1269
+ ? {
1270
+ initialHeaders: {
1271
+ 'content-type': 'application/octet-stream',
1272
+ vary: '__rsc__, __next_router_state_tree__, __next_router_prefetch__',
1273
+ },
1274
+ }
1275
+ : {}),
1229
1276
  });
1230
1277
  ++prerenderGroup;
1231
1278
  if (routesManifest?.i18n && isBlocking) {
@@ -1477,6 +1524,11 @@ async function getMiddlewareBundle({ entryPath, outputDirectory, routesManifest,
1477
1524
  shortPath =
1478
1525
  shortPath.replace(/^app\//, '').replace(/(^|\/)page$/, '') || 'index';
1479
1526
  }
1527
+ if (routesManifest?.basePath) {
1528
+ shortPath = path_1.default.posix
1529
+ .join(routesManifest.basePath, shortPath)
1530
+ .replace(/^\//, '');
1531
+ }
1480
1532
  worker.edgeFunction.name = shortPath;
1481
1533
  source.edgeFunctions[shortPath] = worker.edgeFunction;
1482
1534
  // we don't add the route for edge functions as these
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/next",
3
- "version": "3.2.5",
3
+ "version": "3.2.7",
4
4
  "license": "MIT",
5
5
  "main": "./dist/index",
6
6
  "homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",
@@ -44,9 +44,9 @@
44
44
  "@types/semver": "6.0.0",
45
45
  "@types/text-table": "0.2.1",
46
46
  "@types/webpack-sources": "3.2.0",
47
- "@vercel/build-utils": "5.5.5",
47
+ "@vercel/build-utils": "5.5.6",
48
48
  "@vercel/nft": "0.22.1",
49
- "@vercel/routing-utils": "2.0.2",
49
+ "@vercel/routing-utils": "2.1.0",
50
50
  "async-sema": "3.0.1",
51
51
  "buffer-crc32": "0.2.13",
52
52
  "cheerio": "1.0.0-rc.10",
@@ -69,5 +69,5 @@
69
69
  "typescript": "4.5.2",
70
70
  "webpack-sources": "3.2.3"
71
71
  },
72
- "gitHead": "40f38948a04d83a9e260ddd455685d74e3eb9209"
72
+ "gitHead": "a630e1989613052f64411fd7e5468de58c5999ba"
73
73
  }