@vercel/next 4.19.1 → 4.20.1

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.
@@ -9914,7 +9914,7 @@ async function handleNodeOutputs(nodeOutputs, {
9914
9914
  if (filesHashes) {
9915
9915
  filesHashes["___next_launcher.cjs"] = sha256(handlerSource);
9916
9916
  }
9917
- const operationType = output.type === import_constants.AdapterOutputType.APP_PAGE || output.type === import_constants.AdapterOutputType.PAGES ? "PAGE" : "API";
9917
+ const operationType = output.type === import_constants.AdapterOutputType.APP_PAGE || import_constants.AdapterOutputType.PAGES ? "PAGE" : "API";
9918
9918
  const sourceFile = await getSourceFilePathFromPage({
9919
9919
  workPath: projectDir,
9920
9920
  page: output.sourcePage,
@@ -10231,7 +10231,7 @@ async function handleMiddleware(output, ctx) {
10231
10231
  }
10232
10232
  var _usesSrcCache;
10233
10233
  async function usesSrcDirectory(workPath) {
10234
- if (_usesSrcCache === void 0) {
10234
+ if (!_usesSrcCache) {
10235
10235
  const sourcePages = import_node_path.default.join(workPath, "src", "pages");
10236
10236
  try {
10237
10237
  if ((await import_promises.default.stat(sourcePages)).isDirectory()) {
@@ -10241,7 +10241,7 @@ async function usesSrcDirectory(workPath) {
10241
10241
  _usesSrcCache = false;
10242
10242
  }
10243
10243
  }
10244
- if (_usesSrcCache === void 0) {
10244
+ if (!_usesSrcCache) {
10245
10245
  const sourceAppdir = import_node_path.default.join(workPath, "src", "app");
10246
10246
  try {
10247
10247
  if ((await import_promises.default.stat(sourceAppdir)).isDirectory()) {
@@ -10251,10 +10251,7 @@ async function usesSrcDirectory(workPath) {
10251
10251
  _usesSrcCache = false;
10252
10252
  }
10253
10253
  }
10254
- if (_usesSrcCache === void 0) {
10255
- _usesSrcCache = false;
10256
- }
10257
- return _usesSrcCache;
10254
+ return Boolean(_usesSrcCache);
10258
10255
  }
10259
10256
  function isDirectory(path3) {
10260
10257
  return import_fs_extra3.default.existsSync(path3) && import_fs_extra3.default.lstatSync(path3).isDirectory();
@@ -10627,10 +10624,8 @@ if(${cookieCheck}){
10627
10624
  var myAdapter = {
10628
10625
  name: "Vercel",
10629
10626
  async modifyConfig(config, ctx) {
10630
- if (ctx.phase === import_constants2.PHASE_PRODUCTION_BUILD) {
10631
- config.experimental.supportsImmutableAssets = // Default to true, allow users to opt-out
10632
- (config.experimental.supportsImmutableAssets ?? true) && // AND with infra support to allow disabling via feature flag if necessary.
10633
- process.env.VERCEL_IMMUTABLE_STATIC_FILES_ENABLED === "1";
10627
+ if (ctx.phase === import_constants2.PHASE_PRODUCTION_BUILD && process.env.VERCEL_IMMUTABLE_STATIC_FILES_ENABLED === "1") {
10628
+ config.experimental.supportsImmutableAssets = true;
10634
10629
  }
10635
10630
  if (process.env.VERCEL_HASH_SALT != null) {
10636
10631
  config.experimental.outputHashSalt = (config.experimental.outputHashSalt ?? "") + process.env.VERCEL_HASH_SALT;
package/dist/index.js CHANGED
@@ -814,6 +814,7 @@ var require_superstatic = __commonJS({
814
814
  var superstatic_exports = {};
815
815
  __export2(superstatic_exports, {
816
816
  collectHasSegments: () => collectHasSegments,
817
+ compilePathToRegexpTemplate: () => compilePathToRegexpTemplate,
817
818
  convertCleanUrls: () => convertCleanUrls,
818
819
  convertHeaders: () => convertHeaders2,
819
820
  convertRedirects: () => convertRedirects2,
@@ -957,6 +958,22 @@ var require_superstatic = __commonJS({
957
958
  }
958
959
  route = { src, destination };
959
960
  }
961
+ if (r.transforms) {
962
+ route.transforms = r.transforms.map((transform) => {
963
+ if (transform.type !== "request.path") {
964
+ return { ...transform };
965
+ }
966
+ return {
967
+ ...transform,
968
+ args: compilePathToRegexpTemplateFromSegments(
969
+ transform.args,
970
+ segments,
971
+ hasSegments,
972
+ transform.env
973
+ )
974
+ };
975
+ });
976
+ }
960
977
  if (typeof r.env !== "undefined") {
961
978
  route.env = r.env;
962
979
  }
@@ -1097,6 +1114,81 @@ var require_superstatic = __commonJS({
1097
1114
  }
1098
1115
  var escapeSegment = (str, segmentName) => str.replace(new RegExp(`:${segmentName}`, "g"), `__ESC_COLON_${segmentName}`);
1099
1116
  var unescapeSegments = (str) => str.replace(/__ESC_COLON_/gi, ":");
1117
+ var pathTemplateSegmentNameRegex = /^([a-zA-Z_][a-zA-Z0-9_]*)/;
1118
+ function isEscaped(value, index) {
1119
+ let backslashCount = 0;
1120
+ for (let i = index - 1; i >= 0 && value[i] === "\\"; i--) {
1121
+ backslashCount++;
1122
+ }
1123
+ return backslashCount % 2 === 1;
1124
+ }
1125
+ function collectPathTemplateSegments(template2) {
1126
+ const segments = [];
1127
+ for (let i = 0; i < template2.length; i++) {
1128
+ if (template2[i] !== ":" || isEscaped(template2, i)) {
1129
+ continue;
1130
+ }
1131
+ const match = template2.slice(i + 1).match(pathTemplateSegmentNameRegex);
1132
+ if (match) {
1133
+ segments.push(match[1]);
1134
+ i += match[1].length;
1135
+ }
1136
+ }
1137
+ return segments;
1138
+ }
1139
+ function collectNamedDollarReferences(template2) {
1140
+ const references = [];
1141
+ for (let i = 0; i < template2.length; i++) {
1142
+ if (template2[i] !== "$" || isEscaped(template2, i)) {
1143
+ continue;
1144
+ }
1145
+ const remainder = template2.slice(i + 1);
1146
+ const bracedMatch = remainder.match(/^\{([a-zA-Z_][a-zA-Z0-9_]*)\}/);
1147
+ const unbracedMatch = remainder.match(pathTemplateSegmentNameRegex);
1148
+ const name = bracedMatch?.[1] || unbracedMatch?.[1];
1149
+ if (name) {
1150
+ references.push(name);
1151
+ }
1152
+ }
1153
+ return references;
1154
+ }
1155
+ function compilePathToRegexpTemplateFromSegments(template2, segments, hasItemSegments, env = []) {
1156
+ const indexes = {};
1157
+ segments.forEach((name, index) => {
1158
+ indexes[name] = toSegmentDest(index);
1159
+ });
1160
+ hasItemSegments.forEach((name) => {
1161
+ indexes[name] = `$${name}`;
1162
+ });
1163
+ for (const name of collectPathTemplateSegments(template2)) {
1164
+ if (!(name in indexes)) {
1165
+ throw new Error(
1166
+ `Path template references parameter ":${name}" that is not present in the source or has conditions.`
1167
+ );
1168
+ }
1169
+ }
1170
+ const routeParameters = /* @__PURE__ */ new Set([
1171
+ ...segments.filter((name) => name !== UN_NAMED_SEGMENT),
1172
+ ...hasItemSegments
1173
+ ]);
1174
+ for (const name of collectNamedDollarReferences(template2)) {
1175
+ if (routeParameters.has(name) && !env.includes(name)) {
1176
+ throw new Error(
1177
+ `Path template references route parameter "${name}" as \`$${name}\`. Use \`:${name}\` path-to-regexp syntax in high-level rewrites, or list "${name}" in the transform env allowlist if it is an environment variable.`
1178
+ );
1179
+ }
1180
+ }
1181
+ return safelyCompile(template2, indexes, true);
1182
+ }
1183
+ function compilePathToRegexpTemplate(source, template2, has, env) {
1184
+ const { segments } = sourceToRegex(source);
1185
+ return compilePathToRegexpTemplateFromSegments(
1186
+ template2,
1187
+ segments,
1188
+ collectHasSegments(has),
1189
+ env
1190
+ );
1191
+ }
1100
1192
  function replaceSegments(segments, hasItemSegments, destination, isRedirect, internalParamNames) {
1101
1193
  const namedSegments = segments.filter((name) => name !== UN_NAMED_SEGMENT);
1102
1194
  const canNeedReplacing = destination.includes(":") && namedSegments.length > 0 || hasItemSegments.length > 0 || !isRedirect;
@@ -10942,6 +11034,7 @@ var MIB = 1024 * KIB;
10942
11034
  var EDGE_FUNCTION_SIZE_LIMIT = 4 * MIB;
10943
11035
  var DEFAULT_MAX_UNCOMPRESSED_LAMBDA_SIZE = 250 * MIB;
10944
11036
  var DEFAULT_MAX_UNCOMPRESSED_LAMBDA_SIZE_BUN = 150 * MIB;
11037
+ var DEFAULT_MAX_UNCOMPRESSED_LARGE_LAMBDA_SIZE = 5 * 1024 * MIB;
10945
11038
  var LAMBDA_RESERVED_UNCOMPRESSED_SIZE = 25 * MIB;
10946
11039
  var INTERNAL_PAGES = ["_app.js", "_error.js", "_document.js"];
10947
11040
 
@@ -11240,6 +11333,13 @@ function getMaxUncompressedLambdaSize(runtime) {
11240
11333
  }
11241
11334
  return runtime.startsWith("bun") ? DEFAULT_MAX_UNCOMPRESSED_LAMBDA_SIZE_BUN : DEFAULT_MAX_UNCOMPRESSED_LAMBDA_SIZE;
11242
11335
  }
11336
+ var LARGE_FUNCTIONS_ENV = "NEXT_EXPERIMENTAL_LARGE_FUNCTIONS";
11337
+ function isLargeFunctionsEnabled() {
11338
+ return Boolean(process.env[LARGE_FUNCTIONS_ENV]);
11339
+ }
11340
+ function getGroupMaxUncompressedLambdaSize(runtime, isLargeFunctions) {
11341
+ return isLargeFunctions ? DEFAULT_MAX_UNCOMPRESSED_LARGE_LAMBDA_SIZE : getMaxUncompressedLambdaSize(runtime);
11342
+ }
11243
11343
  var skipDefaultLocaleRewrite = Boolean(
11244
11344
  process.env.NEXT_EXPERIMENTAL_DEFER_DEFAULT_LOCALE_REWRITE
11245
11345
  );
@@ -12209,6 +12309,7 @@ async function getPageLambdaGroups({
12209
12309
  nodeVersion
12210
12310
  }) {
12211
12311
  const groups = [];
12312
+ const largeFunctionsEnabled = isLargeFunctionsEnabled();
12212
12313
  for (const page of pages) {
12213
12314
  const newPages = [...internalPages, page];
12214
12315
  const routeName = normalizePage(page.replace(/\.js$/, ""));
@@ -12261,11 +12362,34 @@ async function getPageLambdaGroups({
12261
12362
  Object.assign(opts, config2.workflows);
12262
12363
  }
12263
12364
  }
12264
- let matchingGroup = experimentalAllowBundling ? void 0 : groups.find((group) => {
12265
- const matches = group.maxDuration === opts.maxDuration && group.memory === opts.memory && compareRegions(group.regions, opts.regions) && compareRegions(
12266
- group.functionFailoverRegions,
12267
- opts.functionFailoverRegions
12268
- ) && group.isPrerenders === isPrerenderRoute && group.isExperimentalPPR === isExperimentalPPR && JSON.stringify(group.experimentalTriggers) === JSON.stringify(opts.experimentalTriggers) && group.supportsCancellation === opts.supportsCancellation;
12365
+ let isLargeFunction = false;
12366
+ if (largeFunctionsEnabled && !experimentalAllowBundling) {
12367
+ let standaloneUncompressedSize = initialPseudoLayerUncompressed;
12368
+ const countedFiles = new Set(
12369
+ Object.keys(initialPseudoLayer.pseudoLayer)
12370
+ );
12371
+ for (const newPage of newPages) {
12372
+ for (const file of Object.keys(pageTraces[newPage] || {})) {
12373
+ if (!countedFiles.has(file)) {
12374
+ countedFiles.add(file);
12375
+ const item = tracedPseudoLayer[file];
12376
+ standaloneUncompressedSize += item?.uncompressedSize || 0;
12377
+ }
12378
+ }
12379
+ standaloneUncompressedSize += compressedPages[newPage].uncompressedSize;
12380
+ }
12381
+ const normalBudget = getMaxUncompressedLambdaSize(nodeVersion.runtime) - LAMBDA_RESERVED_UNCOMPRESSED_SIZE;
12382
+ isLargeFunction = standaloneUncompressedSize >= normalBudget;
12383
+ }
12384
+ const skipGroupBundling = experimentalAllowBundling || isLargeFunction;
12385
+ let matchingGroup = skipGroupBundling ? void 0 : groups.find((group) => {
12386
+ const matches = (
12387
+ // Never merge a normal route into a large (single-route) group.
12388
+ (group.isLargeFunctions ?? false) === isLargeFunction && group.maxDuration === opts.maxDuration && group.memory === opts.memory && compareRegions(group.regions, opts.regions) && compareRegions(
12389
+ group.functionFailoverRegions,
12390
+ opts.functionFailoverRegions
12391
+ ) && group.isPrerenders === isPrerenderRoute && group.isExperimentalPPR === isExperimentalPPR && JSON.stringify(group.experimentalTriggers) === JSON.stringify(opts.experimentalTriggers) && group.supportsCancellation === opts.supportsCancellation
12392
+ );
12269
12393
  if (matches) {
12270
12394
  let newTracedFilesUncompressedSize = group.pseudoLayerUncompressedBytes;
12271
12395
  for (const newPage of newPages) {
@@ -12277,8 +12401,9 @@ async function getPageLambdaGroups({
12277
12401
  });
12278
12402
  newTracedFilesUncompressedSize += compressedPages[newPage].uncompressedSize;
12279
12403
  }
12280
- const maxLambdaSize = getMaxUncompressedLambdaSize(
12281
- nodeVersion.runtime
12404
+ const maxLambdaSize = getGroupMaxUncompressedLambdaSize(
12405
+ nodeVersion.runtime,
12406
+ isLargeFunction
12282
12407
  );
12283
12408
  const underUncompressedLimit = newTracedFilesUncompressedSize < maxLambdaSize - LAMBDA_RESERVED_UNCOMPRESSED_SIZE;
12284
12409
  return underUncompressedLimit;
@@ -12293,6 +12418,7 @@ async function getPageLambdaGroups({
12293
12418
  ...opts,
12294
12419
  isPrerenders: isPrerenderRoute,
12295
12420
  isExperimentalPPR,
12421
+ isLargeFunctions: isLargeFunction,
12296
12422
  isApiLambda: !!isApiPage(page) || !!isRouteHandlers,
12297
12423
  pseudoLayerBytes: initialPseudoLayer.pseudoLayerBytes,
12298
12424
  pseudoLayerUncompressedBytes: initialPseudoLayerUncompressed,
@@ -12401,13 +12527,17 @@ var outputFunctionFileSizeInfo = (pages, pseudoLayer, pseudoLayerUncompressedByt
12401
12527
  };
12402
12528
  var detectLambdaLimitExceeding = async (lambdaGroups, compressedPages, runtime) => {
12403
12529
  const maxLambdaSize = getMaxUncompressedLambdaSize(runtime);
12404
- const UNCOMPRESSED_SIZE_LIMIT_CLOSE = maxLambdaSize - 5 * MIB;
12405
12530
  let numExceededLimit = 0;
12406
12531
  let numCloseToLimit = 0;
12407
12532
  let loggedHeadInfo = false;
12408
12533
  const filteredGroups = lambdaGroups.filter((group) => {
12409
- const exceededLimit = group.pseudoLayerUncompressedBytes > maxLambdaSize;
12410
- const closeToLimit = group.pseudoLayerUncompressedBytes > UNCOMPRESSED_SIZE_LIMIT_CLOSE;
12534
+ const groupMaxLambdaSize = getGroupMaxUncompressedLambdaSize(
12535
+ runtime,
12536
+ group.isLargeFunctions
12537
+ );
12538
+ const groupCloseLimit = groupMaxLambdaSize - 5 * MIB;
12539
+ const exceededLimit = group.pseudoLayerUncompressedBytes > groupMaxLambdaSize;
12540
+ const closeToLimit = group.pseudoLayerUncompressedBytes > groupCloseLimit;
12411
12541
  if (closeToLimit || exceededLimit || (0, import_build_utils.getPlatformEnv)("BUILDER_DEBUG") || process.env.NEXT_DEBUG_FUNCTION_SIZE) {
12412
12542
  if (exceededLimit) {
12413
12543
  numExceededLimit += 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/next",
3
- "version": "4.19.1",
3
+ "version": "4.20.1",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./dist/index",
6
6
  "homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",
@@ -16,7 +16,7 @@
16
16
  "@vercel/nft": "1.10.0"
17
17
  },
18
18
  "devDependencies": {
19
- "@next-community/adapter-vercel": "0.0.1-beta.23",
19
+ "@next-community/adapter-vercel": "0.0.1-beta.22",
20
20
  "@types/aws-lambda": "8.10.19",
21
21
  "@types/buffer-crc32": "0.2.0",
22
22
  "@types/bytes": "3.1.1",
@@ -53,8 +53,8 @@
53
53
  "text-table": "0.2.0",
54
54
  "vitest": "2.0.3",
55
55
  "webpack-sources": "3.2.3",
56
- "@vercel/build-utils": "13.30.0",
57
- "@vercel/routing-utils": "6.3.0"
56
+ "@vercel/routing-utils": "6.3.1",
57
+ "@vercel/build-utils": "13.32.1"
58
58
  },
59
59
  "scripts": {
60
60
  "build": "node build.mjs",