@vercel/next 4.0.6 → 4.0.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.
- package/dist/index.js +14671 -46249
- package/dist/legacy-launcher.js +28 -10
- package/dist/server-launcher.js +18 -28
- package/dist/templated-launcher-shared.js +6 -14
- package/dist/templated-launcher.js +2 -11
- package/package.json +7 -5
- package/dist/create-serverless-config.js +0 -91
- package/dist/edge-function-source/constants.js +0 -8
- package/dist/edge-function-source/get-edge-function-source.js +0 -78
- package/dist/edge-function-source/get-edge-function.js +0 -138
- package/dist/edge-function-source/to-plain-headers.js +0 -87
- package/dist/legacy-versions.js +0 -338
- package/dist/server-build.js +0 -1330
- package/dist/sourcemapped.js +0 -121
- package/dist/utils.js +0 -1943
package/dist/utils.js
DELETED
@@ -1,1943 +0,0 @@
|
|
1
|
-
"use strict";
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
-
if (k2 === undefined) k2 = k;
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
7
|
-
}
|
8
|
-
Object.defineProperty(o, k2, desc);
|
9
|
-
}) : (function(o, m, k, k2) {
|
10
|
-
if (k2 === undefined) k2 = k;
|
11
|
-
o[k2] = m[k];
|
12
|
-
}));
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
15
|
-
}) : function(o, v) {
|
16
|
-
o["default"] = v;
|
17
|
-
});
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
19
|
-
if (mod && mod.__esModule) return mod;
|
20
|
-
var result = {};
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
22
|
-
__setModuleDefault(result, mod);
|
23
|
-
return result;
|
24
|
-
};
|
25
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
26
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
27
|
-
};
|
28
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
29
|
-
exports.isApiPage = exports.getOperationType = exports.upgradeMiddlewareManifest = exports.getMiddlewareManifest = exports.getFunctionsConfigManifest = exports.getMiddlewareBundle = exports.normalizeEdgeFunctionPath = exports.getSourceFilePathFromPage = exports.isDynamicRoute = exports.normalizePage = exports.getImagesConfig = exports.getNextConfig = exports.normalizePackageJson = exports.validateEntrypoint = exports.excludeFiles = exports.getPrivateOutputs = exports.updateRouteSrc = exports.getNextServerPath = exports.normalizeIndexOutput = exports.getStaticFiles = exports.onPrerenderRoute = exports.onPrerenderRouteInitial = exports.detectLambdaLimitExceeding = exports.outputFunctionFileSizeInfo = exports.getPageLambdaGroups = exports.MAX_UNCOMPRESSED_LAMBDA_SIZE = exports.addLocaleOrDefault = exports.normalizeLocalePath = exports.getPrerenderManifest = exports.getRequiredServerFilesManifest = exports.getExportStatus = exports.getExportIntent = exports.createLambdaFromPseudoLayers = exports.createPseudoLayer = exports.ExperimentalTraceVersion = exports.collectTracedFiles = exports.getFilesMapFromReasons = exports.filterStaticPages = exports.getImagesManifest = exports.localizeDynamicRoutes = exports.getDynamicRoutes = exports.getRoutesManifest = exports.RSC_PREFETCH_SUFFIX = exports.RSC_CONTENT_TYPE = exports.prettyBytes = exports.MIB = exports.KIB = void 0;
|
30
|
-
const build_utils_1 = require("@vercel/build-utils");
|
31
|
-
const async_sema_1 = require("async-sema");
|
32
|
-
const buffer_crc32_1 = __importDefault(require("buffer-crc32"));
|
33
|
-
const fs_extra_1 = __importStar(require("fs-extra"));
|
34
|
-
const path_1 = __importDefault(require("path"));
|
35
|
-
const resolve_from_1 = __importDefault(require("resolve-from"));
|
36
|
-
const semver_1 = __importDefault(require("semver"));
|
37
|
-
const zlib_1 = __importDefault(require("zlib"));
|
38
|
-
const url_1 = __importDefault(require("url"));
|
39
|
-
const escape_string_regexp_1 = __importDefault(require("escape-string-regexp"));
|
40
|
-
const _1 = require(".");
|
41
|
-
const text_table_1 = __importDefault(require("text-table"));
|
42
|
-
const get_edge_function_source_1 = require("./edge-function-source/get-edge-function-source");
|
43
|
-
const sourcemapped_1 = require("./sourcemapped");
|
44
|
-
const bytes_1 = __importDefault(require("bytes"));
|
45
|
-
exports.KIB = 1024;
|
46
|
-
exports.MIB = 1024 * exports.KIB;
|
47
|
-
const prettyBytes = (n) => (0, bytes_1.default)(n, { unitSeparator: ' ' });
|
48
|
-
exports.prettyBytes = prettyBytes;
|
49
|
-
exports.RSC_CONTENT_TYPE = 'x-component';
|
50
|
-
exports.RSC_PREFETCH_SUFFIX = '.prefetch.rsc';
|
51
|
-
// Identify /[param]/ in route string
|
52
|
-
// eslint-disable-next-line no-useless-escape
|
53
|
-
const TEST_DYNAMIC_ROUTE = /\/\[[^\/]+?\](?=\/|$)/;
|
54
|
-
function isDynamicRoute(route) {
|
55
|
-
route = route.startsWith('/') ? route : `/${route}`;
|
56
|
-
return TEST_DYNAMIC_ROUTE.test(route);
|
57
|
-
}
|
58
|
-
exports.isDynamicRoute = isDynamicRoute;
|
59
|
-
/**
|
60
|
-
* Validate if the entrypoint is allowed to be used
|
61
|
-
*/
|
62
|
-
function validateEntrypoint(entrypoint) {
|
63
|
-
if (!/package\.json$/.exec(entrypoint) &&
|
64
|
-
!/next\.config\.js$/.exec(entrypoint)) {
|
65
|
-
throw new build_utils_1.NowBuildError({
|
66
|
-
message: 'Specified "src" for "@vercel/next" has to be "package.json" or "next.config.js"',
|
67
|
-
code: 'NEXT_INCORRECT_SRC',
|
68
|
-
});
|
69
|
-
}
|
70
|
-
}
|
71
|
-
exports.validateEntrypoint = validateEntrypoint;
|
72
|
-
/**
|
73
|
-
* Exclude certain files from the files object
|
74
|
-
*/
|
75
|
-
function excludeFiles(files, matcher) {
|
76
|
-
return Object.keys(files).reduce((newFiles, filePath) => {
|
77
|
-
if (matcher(filePath)) {
|
78
|
-
return newFiles;
|
79
|
-
}
|
80
|
-
return {
|
81
|
-
...newFiles,
|
82
|
-
[filePath]: files[filePath],
|
83
|
-
};
|
84
|
-
}, {});
|
85
|
-
}
|
86
|
-
exports.excludeFiles = excludeFiles;
|
87
|
-
/**
|
88
|
-
* Enforce specific package.json configuration for smallest possible lambda
|
89
|
-
*/
|
90
|
-
function normalizePackageJson(defaultPackageJson = {}) {
|
91
|
-
const dependencies = {};
|
92
|
-
const devDependencies = {
|
93
|
-
...defaultPackageJson.dependencies,
|
94
|
-
...defaultPackageJson.devDependencies,
|
95
|
-
};
|
96
|
-
if (devDependencies.react) {
|
97
|
-
dependencies.react = devDependencies.react;
|
98
|
-
delete devDependencies.react;
|
99
|
-
}
|
100
|
-
if (devDependencies['react-dom']) {
|
101
|
-
dependencies['react-dom'] = devDependencies['react-dom'];
|
102
|
-
delete devDependencies['react-dom'];
|
103
|
-
}
|
104
|
-
delete devDependencies['next-server'];
|
105
|
-
return {
|
106
|
-
...defaultPackageJson,
|
107
|
-
dependencies: {
|
108
|
-
// react and react-dom can be overwritten
|
109
|
-
react: 'latest',
|
110
|
-
'react-dom': 'latest',
|
111
|
-
...dependencies,
|
112
|
-
// next-server is forced to canary
|
113
|
-
'next-server': 'v7.0.2-canary.49',
|
114
|
-
},
|
115
|
-
devDependencies: {
|
116
|
-
...devDependencies,
|
117
|
-
// next is forced to canary
|
118
|
-
next: 'v7.0.2-canary.49',
|
119
|
-
},
|
120
|
-
scripts: {
|
121
|
-
...defaultPackageJson.scripts,
|
122
|
-
'now-build': 'NODE_OPTIONS=--max_old_space_size=3000 next build --lambdas',
|
123
|
-
},
|
124
|
-
};
|
125
|
-
}
|
126
|
-
exports.normalizePackageJson = normalizePackageJson;
|
127
|
-
async function getNextConfig(workPath, entryPath) {
|
128
|
-
const entryConfig = path_1.default.join(entryPath, './next.config.js');
|
129
|
-
if (await fs_extra_1.default.pathExists(entryConfig)) {
|
130
|
-
return fs_extra_1.default.readFile(entryConfig, 'utf8');
|
131
|
-
}
|
132
|
-
const workConfig = path_1.default.join(workPath, './next.config.js');
|
133
|
-
if (await fs_extra_1.default.pathExists(workConfig)) {
|
134
|
-
return fs_extra_1.default.readFile(workConfig, 'utf8');
|
135
|
-
}
|
136
|
-
return null;
|
137
|
-
}
|
138
|
-
exports.getNextConfig = getNextConfig;
|
139
|
-
function getImagesConfig(imagesManifest) {
|
140
|
-
return imagesManifest?.images?.loader === 'default' &&
|
141
|
-
imagesManifest.images?.unoptimized !== true
|
142
|
-
? {
|
143
|
-
domains: imagesManifest.images.domains,
|
144
|
-
sizes: imagesManifest.images.sizes,
|
145
|
-
remotePatterns: imagesManifest.images.remotePatterns,
|
146
|
-
minimumCacheTTL: imagesManifest.images.minimumCacheTTL,
|
147
|
-
formats: imagesManifest.images.formats,
|
148
|
-
dangerouslyAllowSVG: imagesManifest.images.dangerouslyAllowSVG,
|
149
|
-
contentSecurityPolicy: imagesManifest.images.contentSecurityPolicy,
|
150
|
-
contentDispositionType: imagesManifest.images.contentDispositionType,
|
151
|
-
}
|
152
|
-
: undefined;
|
153
|
-
}
|
154
|
-
exports.getImagesConfig = getImagesConfig;
|
155
|
-
function normalizePage(page) {
|
156
|
-
// Resolve on anything that doesn't start with `/`
|
157
|
-
if (!page.startsWith('/')) {
|
158
|
-
page = `/${page}`;
|
159
|
-
}
|
160
|
-
// remove '/index' from the end
|
161
|
-
page = page.replace(/\/index$/, '/');
|
162
|
-
return page;
|
163
|
-
}
|
164
|
-
exports.normalizePage = normalizePage;
|
165
|
-
async function getRoutesManifest(entryPath, outputDirectory, nextVersion) {
|
166
|
-
const shouldHaveManifest = nextVersion && semver_1.default.gte(nextVersion, '9.1.4-canary.0');
|
167
|
-
if (!shouldHaveManifest)
|
168
|
-
return;
|
169
|
-
const pathRoutesManifest = path_1.default.join(entryPath, outputDirectory, 'routes-manifest.json');
|
170
|
-
const hasRoutesManifest = await fs_extra_1.default
|
171
|
-
.access(pathRoutesManifest)
|
172
|
-
.then(() => true)
|
173
|
-
.catch(() => false);
|
174
|
-
if (shouldHaveManifest && !hasRoutesManifest) {
|
175
|
-
throw new build_utils_1.NowBuildError({
|
176
|
-
message: `The file "${pathRoutesManifest}" couldn't be found. This is often caused by a misconfiguration in your project.`,
|
177
|
-
link: 'https://err.sh/vercel/vercel/now-next-routes-manifest',
|
178
|
-
code: 'NEXT_NO_ROUTES_MANIFEST',
|
179
|
-
});
|
180
|
-
}
|
181
|
-
const routesManifest = await fs_extra_1.default.readJSON(pathRoutesManifest);
|
182
|
-
// remove temporary array based routeKeys from v1/v2 of routes
|
183
|
-
// manifest since it can result in invalid routes
|
184
|
-
for (const route of routesManifest.dataRoutes || []) {
|
185
|
-
if (Array.isArray(route.routeKeys)) {
|
186
|
-
delete route.routeKeys;
|
187
|
-
delete route.namedDataRouteRegex;
|
188
|
-
}
|
189
|
-
}
|
190
|
-
for (const route of routesManifest.dynamicRoutes || []) {
|
191
|
-
if ('routeKeys' in route && Array.isArray(route.routeKeys)) {
|
192
|
-
delete route.routeKeys;
|
193
|
-
delete route.namedRegex;
|
194
|
-
}
|
195
|
-
}
|
196
|
-
return routesManifest;
|
197
|
-
}
|
198
|
-
exports.getRoutesManifest = getRoutesManifest;
|
199
|
-
async function getDynamicRoutes(entryPath, entryDirectory, dynamicPages, isDev, routesManifest, omittedRoutes, canUsePreviewMode, bypassToken, isServerMode, dynamicMiddlewareRouteMap) {
|
200
|
-
if (routesManifest) {
|
201
|
-
switch (routesManifest.version) {
|
202
|
-
case 1:
|
203
|
-
case 2: {
|
204
|
-
return routesManifest.dynamicRoutes
|
205
|
-
.filter(({ page }) => canUsePreviewMode || !omittedRoutes?.has(page))
|
206
|
-
.map(({ page, regex }) => {
|
207
|
-
return {
|
208
|
-
src: regex,
|
209
|
-
dest: !isDev ? path_1.default.posix.join('/', entryDirectory, page) : page,
|
210
|
-
check: true,
|
211
|
-
status: canUsePreviewMode && omittedRoutes?.has(page) ? 404 : undefined,
|
212
|
-
};
|
213
|
-
});
|
214
|
-
}
|
215
|
-
case 3:
|
216
|
-
case 4: {
|
217
|
-
const routes = [];
|
218
|
-
for (const dynamicRoute of routesManifest.dynamicRoutes) {
|
219
|
-
if (!canUsePreviewMode && omittedRoutes?.has(dynamicRoute.page)) {
|
220
|
-
continue;
|
221
|
-
}
|
222
|
-
const params = dynamicRoute;
|
223
|
-
if ('isMiddleware' in params) {
|
224
|
-
const route = dynamicMiddlewareRouteMap?.get(params.page);
|
225
|
-
if (!route) {
|
226
|
-
throw new Error(`Could not find dynamic middleware route for ${params.page}`);
|
227
|
-
}
|
228
|
-
routes.push(route);
|
229
|
-
continue;
|
230
|
-
}
|
231
|
-
const { page, namedRegex, regex, routeKeys } = params;
|
232
|
-
const route = {
|
233
|
-
src: namedRegex || regex,
|
234
|
-
dest: `${!isDev ? path_1.default.posix.join('/', entryDirectory, page) : page}${routeKeys
|
235
|
-
? `?${Object.keys(routeKeys)
|
236
|
-
.map(key => `${routeKeys[key]}=$${key}`)
|
237
|
-
.join('&')}`
|
238
|
-
: ''}`,
|
239
|
-
};
|
240
|
-
if (!isServerMode) {
|
241
|
-
route.check = true;
|
242
|
-
}
|
243
|
-
if (isServerMode && canUsePreviewMode && omittedRoutes?.has(page)) {
|
244
|
-
// only match this route when in preview mode so
|
245
|
-
// preview works for non-prerender fallback: false pages
|
246
|
-
route.has = [
|
247
|
-
{
|
248
|
-
type: 'cookie',
|
249
|
-
key: '__prerender_bypass',
|
250
|
-
value: bypassToken || undefined,
|
251
|
-
},
|
252
|
-
{
|
253
|
-
type: 'cookie',
|
254
|
-
key: '__next_preview_data',
|
255
|
-
},
|
256
|
-
];
|
257
|
-
}
|
258
|
-
routes.push({
|
259
|
-
...route,
|
260
|
-
src: route.src.replace(new RegExp((0, escape_string_regexp_1.default)('(?:/)?$')), '(?:\\.rsc)(?:/)?$'),
|
261
|
-
dest: route.dest?.replace(/($|\?)/, '.rsc$1'),
|
262
|
-
});
|
263
|
-
routes.push(route);
|
264
|
-
continue;
|
265
|
-
}
|
266
|
-
return routes;
|
267
|
-
}
|
268
|
-
default: {
|
269
|
-
// update MIN_ROUTES_MANIFEST_VERSION
|
270
|
-
throw new build_utils_1.NowBuildError({
|
271
|
-
message: 'This version of `@vercel/next` does not support the version of Next.js you are trying to deploy.\n' +
|
272
|
-
'Please upgrade your `@vercel/next` builder and try again. Contact support if this continues to happen.',
|
273
|
-
code: 'NEXT_VERSION_UPGRADE',
|
274
|
-
});
|
275
|
-
}
|
276
|
-
}
|
277
|
-
}
|
278
|
-
// FALLBACK:
|
279
|
-
// When `routes-manifest.json` does not exist (old Next.js versions), we'll try to
|
280
|
-
// require the methods we need from Next.js' internals.
|
281
|
-
if (!dynamicPages.length) {
|
282
|
-
return [];
|
283
|
-
}
|
284
|
-
let getRouteRegex = undefined;
|
285
|
-
let getSortedRoutes;
|
286
|
-
try {
|
287
|
-
// NOTE: `eval('require')` is necessary to avoid bad transpilation to `__webpack_require__`
|
288
|
-
({ getRouteRegex, getSortedRoutes } = eval('require')((0, resolve_from_1.default)(entryPath, 'next-server/dist/lib/router/utils')));
|
289
|
-
if (typeof getRouteRegex !== 'function') {
|
290
|
-
getRouteRegex = undefined;
|
291
|
-
}
|
292
|
-
}
|
293
|
-
catch (_) { } // eslint-disable-line no-empty
|
294
|
-
if (!getRouteRegex || !getSortedRoutes) {
|
295
|
-
try {
|
296
|
-
// NOTE: `eval('require')` is necessary to avoid bad transpilation to `__webpack_require__`
|
297
|
-
({ getRouteRegex, getSortedRoutes } = eval('require')((0, resolve_from_1.default)(entryPath, 'next/dist/next-server/lib/router/utils')));
|
298
|
-
if (typeof getRouteRegex !== 'function') {
|
299
|
-
getRouteRegex = undefined;
|
300
|
-
}
|
301
|
-
}
|
302
|
-
catch (_) { } // eslint-disable-line no-empty
|
303
|
-
}
|
304
|
-
if (!getRouteRegex || !getSortedRoutes) {
|
305
|
-
throw new build_utils_1.NowBuildError({
|
306
|
-
message: 'Found usage of dynamic routes but not on a new enough version of Next.js.',
|
307
|
-
code: 'NEXT_DYNAMIC_ROUTES_OUTDATED',
|
308
|
-
});
|
309
|
-
}
|
310
|
-
const pageMatchers = getSortedRoutes(dynamicPages).map(pageName => ({
|
311
|
-
pageName,
|
312
|
-
matcher: getRouteRegex && getRouteRegex(pageName).re,
|
313
|
-
}));
|
314
|
-
const routes = [];
|
315
|
-
pageMatchers.forEach(pageMatcher => {
|
316
|
-
// in `vercel dev` we don't need to prefix the destination
|
317
|
-
const dest = !isDev
|
318
|
-
? path_1.default.posix.join('/', entryDirectory, pageMatcher.pageName)
|
319
|
-
: pageMatcher.pageName;
|
320
|
-
if (pageMatcher && pageMatcher.matcher) {
|
321
|
-
routes.push({
|
322
|
-
src: pageMatcher.matcher.source,
|
323
|
-
dest,
|
324
|
-
check: !isDev,
|
325
|
-
});
|
326
|
-
}
|
327
|
-
});
|
328
|
-
return routes;
|
329
|
-
}
|
330
|
-
exports.getDynamicRoutes = getDynamicRoutes;
|
331
|
-
function localizeDynamicRoutes(dynamicRoutes, dynamicPrefix, entryDirectory, staticPages, prerenderManifest, routesManifest, isServerMode, isCorrectLocaleAPIRoutes, inversedAppPathRoutesManifest) {
|
332
|
-
return dynamicRoutes.map((route) => {
|
333
|
-
// i18n is already handled for middleware
|
334
|
-
if (route.middleware !== undefined || route.middlewarePath !== undefined)
|
335
|
-
return route;
|
336
|
-
const { i18n } = routesManifest || {};
|
337
|
-
if (i18n) {
|
338
|
-
const { pathname } = url_1.default.parse(route.dest);
|
339
|
-
const pathnameNoPrefix = pathname?.replace(dynamicPrefix, '');
|
340
|
-
const isFallback = prerenderManifest.fallbackRoutes[pathname];
|
341
|
-
const isBlocking = prerenderManifest.blockingFallbackRoutes[pathname];
|
342
|
-
const isApiRoute = pathnameNoPrefix === '/api' || pathnameNoPrefix?.startsWith('/api/');
|
343
|
-
const isAutoExport = staticPages[addLocaleOrDefault(pathname, routesManifest).substring(1)];
|
344
|
-
const isAppRoute = inversedAppPathRoutesManifest?.[pathnameNoPrefix || ''];
|
345
|
-
const isLocalePrefixed = isFallback || isBlocking || isAutoExport || isServerMode;
|
346
|
-
route.src = route.src.replace('^', `^${dynamicPrefix ? `${dynamicPrefix}[/]?` : '[/]?'}(?${isLocalePrefixed ? '<nextLocale>' : ':'}${i18n.locales.map(locale => (0, escape_string_regexp_1.default)(locale)).join('|')})?`);
|
347
|
-
if (isLocalePrefixed &&
|
348
|
-
!(isCorrectLocaleAPIRoutes && isApiRoute) &&
|
349
|
-
!isAppRoute) {
|
350
|
-
// ensure destination has locale prefix to match prerender output
|
351
|
-
// path so that the prerender object is used
|
352
|
-
route.dest = route.dest.replace(`${path_1.default.posix.join('/', entryDirectory, '/')}`, `${path_1.default.posix.join('/', entryDirectory, '$nextLocale', '/')}`);
|
353
|
-
}
|
354
|
-
}
|
355
|
-
else {
|
356
|
-
route.src = route.src.replace('^', `^${dynamicPrefix}`);
|
357
|
-
}
|
358
|
-
return route;
|
359
|
-
});
|
360
|
-
}
|
361
|
-
exports.localizeDynamicRoutes = localizeDynamicRoutes;
|
362
|
-
async function getImagesManifest(entryPath, outputDirectory) {
|
363
|
-
const pathImagesManifest = path_1.default.join(entryPath, outputDirectory, 'images-manifest.json');
|
364
|
-
const hasImagesManifest = await fs_extra_1.default
|
365
|
-
.access(pathImagesManifest)
|
366
|
-
.then(() => true)
|
367
|
-
.catch(() => false);
|
368
|
-
if (!hasImagesManifest) {
|
369
|
-
return undefined;
|
370
|
-
}
|
371
|
-
return fs_extra_1.default.readJson(pathImagesManifest);
|
372
|
-
}
|
373
|
-
exports.getImagesManifest = getImagesManifest;
|
374
|
-
function filterStaticPages(staticPageFiles, dynamicPages, entryDirectory, htmlContentType, prerenderManifest, routesManifest) {
|
375
|
-
const staticPages = {};
|
376
|
-
Object.keys(staticPageFiles).forEach((page) => {
|
377
|
-
const pathname = page.replace(/\.html$/, '');
|
378
|
-
const routeName = normalizeLocalePath(normalizePage(pathname), routesManifest?.i18n?.locales).pathname;
|
379
|
-
// Prerendered routes emit a `.html` file but should not be treated as a
|
380
|
-
// static page.
|
381
|
-
// Lazily prerendered routes have a fallback `.html` file on newer
|
382
|
-
// Next.js versions so we need to also not treat it as a static page here.
|
383
|
-
if (prerenderManifest.staticRoutes[routeName] ||
|
384
|
-
prerenderManifest.fallbackRoutes[routeName] ||
|
385
|
-
prerenderManifest.staticRoutes[normalizePage(pathname)] ||
|
386
|
-
prerenderManifest.fallbackRoutes[normalizePage(pathname)]) {
|
387
|
-
return;
|
388
|
-
}
|
389
|
-
const staticRoute = path_1.default.posix.join(entryDirectory, pathname);
|
390
|
-
staticPages[staticRoute] = staticPageFiles[page];
|
391
|
-
staticPages[staticRoute].contentType = htmlContentType;
|
392
|
-
if (isDynamicRoute(pathname)) {
|
393
|
-
dynamicPages.push(routeName);
|
394
|
-
return;
|
395
|
-
}
|
396
|
-
});
|
397
|
-
return staticPages;
|
398
|
-
}
|
399
|
-
exports.filterStaticPages = filterStaticPages;
|
400
|
-
function getFilesMapFromReasons(fileList, reasons, ignoreFn) {
|
401
|
-
// this uses the reasons tree to collect files specific to a
|
402
|
-
// certain parent allowing us to not have to trace each parent
|
403
|
-
// separately
|
404
|
-
const parentFilesMap = new Map();
|
405
|
-
function propagateToParents(parents, file, seen = new Set()) {
|
406
|
-
for (const parent of parents || []) {
|
407
|
-
if (!seen.has(parent)) {
|
408
|
-
seen.add(parent);
|
409
|
-
let parentFiles = parentFilesMap.get(parent);
|
410
|
-
if (!parentFiles) {
|
411
|
-
parentFiles = new Set();
|
412
|
-
parentFilesMap.set(parent, parentFiles);
|
413
|
-
}
|
414
|
-
if (!ignoreFn?.(file, parent)) {
|
415
|
-
parentFiles.add(file);
|
416
|
-
}
|
417
|
-
const parentReason = reasons.get(parent);
|
418
|
-
if (parentReason?.parents) {
|
419
|
-
propagateToParents(parentReason.parents, file, seen);
|
420
|
-
}
|
421
|
-
}
|
422
|
-
}
|
423
|
-
}
|
424
|
-
for (const file of fileList) {
|
425
|
-
const reason = reasons.get(file);
|
426
|
-
const isInitial = reason?.type.length === 1 && reason.type.includes('initial');
|
427
|
-
if (!reason ||
|
428
|
-
!reason.parents ||
|
429
|
-
(isInitial && reason.parents.size === 0)) {
|
430
|
-
continue;
|
431
|
-
}
|
432
|
-
propagateToParents(reason.parents, file);
|
433
|
-
}
|
434
|
-
return parentFilesMap;
|
435
|
-
}
|
436
|
-
exports.getFilesMapFromReasons = getFilesMapFromReasons;
|
437
|
-
const collectTracedFiles = (baseDir, lstatResults, lstatSema, reasons, files) => async (file) => {
|
438
|
-
const reason = reasons.get(file);
|
439
|
-
if (reason && reason.type.includes('initial')) {
|
440
|
-
// Initial files are manually added to the lambda later
|
441
|
-
return;
|
442
|
-
}
|
443
|
-
const filePath = path_1.default.join(baseDir, file);
|
444
|
-
if (!lstatResults[filePath]) {
|
445
|
-
lstatResults[filePath] = lstatSema
|
446
|
-
.acquire()
|
447
|
-
.then(() => (0, fs_extra_1.lstat)(filePath))
|
448
|
-
.finally(() => lstatSema.release());
|
449
|
-
}
|
450
|
-
const { mode } = await lstatResults[filePath];
|
451
|
-
files[file] = new build_utils_1.FileFsRef({
|
452
|
-
fsPath: path_1.default.join(baseDir, file),
|
453
|
-
mode,
|
454
|
-
});
|
455
|
-
};
|
456
|
-
exports.collectTracedFiles = collectTracedFiles;
|
457
|
-
exports.ExperimentalTraceVersion = `9.0.4-canary.1`;
|
458
|
-
const compressBuffer = (buf) => {
|
459
|
-
return new Promise((resolve, reject) => {
|
460
|
-
zlib_1.default.deflateRaw(buf, { level: zlib_1.default.constants.Z_BEST_COMPRESSION }, (err, compBuf) => {
|
461
|
-
if (err)
|
462
|
-
return reject(err);
|
463
|
-
resolve(compBuf);
|
464
|
-
});
|
465
|
-
});
|
466
|
-
};
|
467
|
-
async function createPseudoLayer(files) {
|
468
|
-
const pseudoLayer = {};
|
469
|
-
let pseudoLayerBytes = 0;
|
470
|
-
for (const fileName of Object.keys(files)) {
|
471
|
-
const file = files[fileName];
|
472
|
-
if ((0, build_utils_1.isSymbolicLink)(file.mode)) {
|
473
|
-
const symlinkTarget = await fs_extra_1.default.readlink(file.fsPath);
|
474
|
-
pseudoLayer[fileName] = {
|
475
|
-
file,
|
476
|
-
isSymlink: true,
|
477
|
-
symlinkTarget,
|
478
|
-
};
|
479
|
-
}
|
480
|
-
else {
|
481
|
-
const origBuffer = await (0, build_utils_1.streamToBuffer)(file.toStream());
|
482
|
-
const compBuffer = await compressBuffer(origBuffer);
|
483
|
-
pseudoLayerBytes += compBuffer.byteLength;
|
484
|
-
pseudoLayer[fileName] = {
|
485
|
-
file,
|
486
|
-
compBuffer,
|
487
|
-
isSymlink: false,
|
488
|
-
crc32: buffer_crc32_1.default.unsigned(origBuffer),
|
489
|
-
uncompressedSize: origBuffer.byteLength,
|
490
|
-
};
|
491
|
-
}
|
492
|
-
}
|
493
|
-
return { pseudoLayer, pseudoLayerBytes };
|
494
|
-
}
|
495
|
-
exports.createPseudoLayer = createPseudoLayer;
|
496
|
-
// measured with 1, 2, 5, 10, and `os.cpus().length || 5`
|
497
|
-
// and sema(1) produced the best results
|
498
|
-
const createLambdaSema = new async_sema_1.Sema(1);
|
499
|
-
async function createLambdaFromPseudoLayers({ files: baseFiles, layers, isStreaming, nextVersion, ...lambdaOptions }) {
|
500
|
-
await createLambdaSema.acquire();
|
501
|
-
const files = {};
|
502
|
-
const addedFiles = new Set();
|
503
|
-
// Add files from pseudo layers
|
504
|
-
for (const layer of layers) {
|
505
|
-
for (const seedKey of Object.keys(layer)) {
|
506
|
-
if (addedFiles.has(seedKey)) {
|
507
|
-
// File was already added in a previous pseudo layer
|
508
|
-
continue;
|
509
|
-
}
|
510
|
-
const item = layer[seedKey];
|
511
|
-
files[seedKey] = item.file;
|
512
|
-
addedFiles.add(seedKey);
|
513
|
-
}
|
514
|
-
}
|
515
|
-
for (const fileName of Object.keys(baseFiles)) {
|
516
|
-
if (addedFiles.has(fileName)) {
|
517
|
-
// File was already added in a previous pseudo layer
|
518
|
-
continue;
|
519
|
-
}
|
520
|
-
const file = baseFiles[fileName];
|
521
|
-
files[fileName] = file;
|
522
|
-
addedFiles.add(fileName);
|
523
|
-
}
|
524
|
-
createLambdaSema.release();
|
525
|
-
return new build_utils_1.NodejsLambda({
|
526
|
-
...lambdaOptions,
|
527
|
-
...(isStreaming
|
528
|
-
? {
|
529
|
-
supportsResponseStreaming: true,
|
530
|
-
}
|
531
|
-
: {}),
|
532
|
-
files,
|
533
|
-
shouldAddHelpers: false,
|
534
|
-
shouldAddSourcemapSupport: false,
|
535
|
-
supportsMultiPayloads: true,
|
536
|
-
framework: {
|
537
|
-
slug: 'nextjs',
|
538
|
-
version: nextVersion,
|
539
|
-
},
|
540
|
-
});
|
541
|
-
}
|
542
|
-
exports.createLambdaFromPseudoLayers = createLambdaFromPseudoLayers;
|
543
|
-
async function getExportIntent(entryPath) {
|
544
|
-
const pathExportMarker = path_1.default.join(entryPath, '.next', 'export-marker.json');
|
545
|
-
const hasExportMarker = await fs_extra_1.default
|
546
|
-
.access(pathExportMarker, fs_extra_1.default.constants.F_OK)
|
547
|
-
.then(() => true)
|
548
|
-
.catch(() => false);
|
549
|
-
if (!hasExportMarker) {
|
550
|
-
return false;
|
551
|
-
}
|
552
|
-
const manifest = JSON.parse(await fs_extra_1.default.readFile(pathExportMarker, 'utf8'));
|
553
|
-
switch (manifest.version) {
|
554
|
-
case 1: {
|
555
|
-
if (manifest.hasExportPathMap !== true) {
|
556
|
-
return false;
|
557
|
-
}
|
558
|
-
return { trailingSlash: manifest.exportTrailingSlash };
|
559
|
-
}
|
560
|
-
default: {
|
561
|
-
return false;
|
562
|
-
}
|
563
|
-
}
|
564
|
-
}
|
565
|
-
exports.getExportIntent = getExportIntent;
|
566
|
-
async function getExportStatus(entryPath) {
|
567
|
-
const pathExportDetail = path_1.default.join(entryPath, '.next', 'export-detail.json');
|
568
|
-
const hasExportDetail = await fs_extra_1.default
|
569
|
-
.access(pathExportDetail, fs_extra_1.default.constants.F_OK)
|
570
|
-
.then(() => true)
|
571
|
-
.catch(() => false);
|
572
|
-
if (!hasExportDetail) {
|
573
|
-
return false;
|
574
|
-
}
|
575
|
-
const manifest = JSON.parse(await fs_extra_1.default.readFile(pathExportDetail, 'utf8'));
|
576
|
-
switch (manifest.version) {
|
577
|
-
case 1: {
|
578
|
-
return {
|
579
|
-
success: !!manifest.success,
|
580
|
-
outDirectory: manifest.outDirectory,
|
581
|
-
};
|
582
|
-
}
|
583
|
-
default: {
|
584
|
-
return false;
|
585
|
-
}
|
586
|
-
}
|
587
|
-
}
|
588
|
-
exports.getExportStatus = getExportStatus;
|
589
|
-
async function getRequiredServerFilesManifest(entryPath, outputDirectory) {
|
590
|
-
const pathRequiredServerFilesManifest = path_1.default.join(entryPath, outputDirectory, 'required-server-files.json');
|
591
|
-
const hasManifest = await fs_extra_1.default
|
592
|
-
.access(pathRequiredServerFilesManifest, fs_extra_1.default.constants.F_OK)
|
593
|
-
.then(() => true)
|
594
|
-
.catch(() => false);
|
595
|
-
if (!hasManifest) {
|
596
|
-
return false;
|
597
|
-
}
|
598
|
-
const manifestData = JSON.parse(await fs_extra_1.default.readFile(pathRequiredServerFilesManifest, 'utf8'));
|
599
|
-
const requiredServerFiles = {
|
600
|
-
files: [],
|
601
|
-
ignore: [],
|
602
|
-
config: {},
|
603
|
-
appDir: manifestData.appDir,
|
604
|
-
relativeAppDir: manifestData.relativeAppDir,
|
605
|
-
};
|
606
|
-
switch (manifestData.version) {
|
607
|
-
case 1: {
|
608
|
-
requiredServerFiles.files = manifestData.files;
|
609
|
-
requiredServerFiles.ignore = manifestData.ignore;
|
610
|
-
requiredServerFiles.config = manifestData.config;
|
611
|
-
requiredServerFiles.appDir = manifestData.appDir;
|
612
|
-
break;
|
613
|
-
}
|
614
|
-
default: {
|
615
|
-
throw new Error(`Invalid required-server-files manifest version ${manifestData.version}, please contact support if this error persists`);
|
616
|
-
}
|
617
|
-
}
|
618
|
-
return requiredServerFiles;
|
619
|
-
}
|
620
|
-
exports.getRequiredServerFilesManifest = getRequiredServerFilesManifest;
|
621
|
-
async function getPrerenderManifest(entryPath, outputDirectory) {
|
622
|
-
const pathPrerenderManifest = path_1.default.join(entryPath, outputDirectory, 'prerender-manifest.json');
|
623
|
-
const hasManifest = await fs_extra_1.default
|
624
|
-
.access(pathPrerenderManifest, fs_extra_1.default.constants.F_OK)
|
625
|
-
.then(() => true)
|
626
|
-
.catch(() => false);
|
627
|
-
if (!hasManifest) {
|
628
|
-
return {
|
629
|
-
staticRoutes: {},
|
630
|
-
blockingFallbackRoutes: {},
|
631
|
-
fallbackRoutes: {},
|
632
|
-
bypassToken: null,
|
633
|
-
omittedRoutes: {},
|
634
|
-
notFoundRoutes: [],
|
635
|
-
isLocalePrefixed: false,
|
636
|
-
};
|
637
|
-
}
|
638
|
-
const manifest = JSON.parse(await fs_extra_1.default.readFile(pathPrerenderManifest, 'utf8'));
|
639
|
-
switch (manifest.version) {
|
640
|
-
case 1: {
|
641
|
-
const routes = Object.keys(manifest.routes);
|
642
|
-
const lazyRoutes = Object.keys(manifest.dynamicRoutes);
|
643
|
-
const ret = {
|
644
|
-
staticRoutes: {},
|
645
|
-
blockingFallbackRoutes: {},
|
646
|
-
fallbackRoutes: {},
|
647
|
-
bypassToken: (manifest.preview && manifest.preview.previewModeId) || null,
|
648
|
-
omittedRoutes: {},
|
649
|
-
notFoundRoutes: [],
|
650
|
-
isLocalePrefixed: false,
|
651
|
-
};
|
652
|
-
routes.forEach(route => {
|
653
|
-
const { initialRevalidateSeconds, dataRoute, srcRoute } = manifest.routes[route];
|
654
|
-
ret.staticRoutes[route] = {
|
655
|
-
initialRevalidate: initialRevalidateSeconds === false
|
656
|
-
? false
|
657
|
-
: Math.max(1, initialRevalidateSeconds),
|
658
|
-
dataRoute,
|
659
|
-
srcRoute,
|
660
|
-
};
|
661
|
-
});
|
662
|
-
lazyRoutes.forEach(lazyRoute => {
|
663
|
-
const { routeRegex, fallback, dataRoute, dataRouteRegex } = manifest.dynamicRoutes[lazyRoute];
|
664
|
-
if (fallback) {
|
665
|
-
ret.fallbackRoutes[lazyRoute] = {
|
666
|
-
routeRegex,
|
667
|
-
fallback,
|
668
|
-
dataRoute,
|
669
|
-
dataRouteRegex,
|
670
|
-
};
|
671
|
-
}
|
672
|
-
else {
|
673
|
-
ret.blockingFallbackRoutes[lazyRoute] = {
|
674
|
-
routeRegex,
|
675
|
-
dataRoute,
|
676
|
-
dataRouteRegex,
|
677
|
-
};
|
678
|
-
}
|
679
|
-
});
|
680
|
-
return ret;
|
681
|
-
}
|
682
|
-
case 2:
|
683
|
-
case 3:
|
684
|
-
case 4: {
|
685
|
-
const routes = Object.keys(manifest.routes);
|
686
|
-
const lazyRoutes = Object.keys(manifest.dynamicRoutes);
|
687
|
-
const ret = {
|
688
|
-
staticRoutes: {},
|
689
|
-
blockingFallbackRoutes: {},
|
690
|
-
fallbackRoutes: {},
|
691
|
-
bypassToken: manifest.preview.previewModeId,
|
692
|
-
omittedRoutes: {},
|
693
|
-
notFoundRoutes: [],
|
694
|
-
isLocalePrefixed: manifest.version > 2,
|
695
|
-
};
|
696
|
-
if (manifest.notFoundRoutes) {
|
697
|
-
ret.notFoundRoutes.push(...manifest.notFoundRoutes);
|
698
|
-
}
|
699
|
-
routes.forEach(route => {
|
700
|
-
const { initialRevalidateSeconds, dataRoute, srcRoute } = manifest.routes[route];
|
701
|
-
let initialStatus;
|
702
|
-
let initialHeaders;
|
703
|
-
let experimentalBypassFor;
|
704
|
-
if (manifest.version === 4) {
|
705
|
-
initialStatus = manifest.routes[route].initialStatus;
|
706
|
-
initialHeaders = manifest.routes[route].initialHeaders;
|
707
|
-
experimentalBypassFor = manifest.routes[route].experimentalBypassFor;
|
708
|
-
}
|
709
|
-
ret.staticRoutes[route] = {
|
710
|
-
initialRevalidate: initialRevalidateSeconds === false
|
711
|
-
? false
|
712
|
-
: Math.max(1, initialRevalidateSeconds),
|
713
|
-
dataRoute,
|
714
|
-
srcRoute,
|
715
|
-
initialStatus,
|
716
|
-
initialHeaders,
|
717
|
-
experimentalBypassFor,
|
718
|
-
};
|
719
|
-
});
|
720
|
-
lazyRoutes.forEach(lazyRoute => {
|
721
|
-
const { routeRegex, fallback, dataRoute, dataRouteRegex } = manifest.dynamicRoutes[lazyRoute];
|
722
|
-
let experimentalBypassFor;
|
723
|
-
if (manifest.version === 4) {
|
724
|
-
experimentalBypassFor =
|
725
|
-
manifest.dynamicRoutes[lazyRoute].experimentalBypassFor;
|
726
|
-
}
|
727
|
-
if (typeof fallback === 'string') {
|
728
|
-
ret.fallbackRoutes[lazyRoute] = {
|
729
|
-
experimentalBypassFor,
|
730
|
-
routeRegex,
|
731
|
-
fallback,
|
732
|
-
dataRoute,
|
733
|
-
dataRouteRegex,
|
734
|
-
};
|
735
|
-
}
|
736
|
-
else if (fallback === null) {
|
737
|
-
ret.blockingFallbackRoutes[lazyRoute] = {
|
738
|
-
experimentalBypassFor,
|
739
|
-
routeRegex,
|
740
|
-
dataRoute,
|
741
|
-
dataRouteRegex,
|
742
|
-
};
|
743
|
-
}
|
744
|
-
else {
|
745
|
-
// Fallback behavior is disabled, all routes would've been provided
|
746
|
-
// in the top-level `routes` key (`staticRoutes`).
|
747
|
-
ret.omittedRoutes[lazyRoute] = {
|
748
|
-
experimentalBypassFor,
|
749
|
-
routeRegex,
|
750
|
-
dataRoute,
|
751
|
-
dataRouteRegex,
|
752
|
-
};
|
753
|
-
}
|
754
|
-
});
|
755
|
-
return ret;
|
756
|
-
}
|
757
|
-
default: {
|
758
|
-
return {
|
759
|
-
staticRoutes: {},
|
760
|
-
blockingFallbackRoutes: {},
|
761
|
-
fallbackRoutes: {},
|
762
|
-
bypassToken: null,
|
763
|
-
omittedRoutes: {},
|
764
|
-
notFoundRoutes: [],
|
765
|
-
isLocalePrefixed: false,
|
766
|
-
};
|
767
|
-
}
|
768
|
-
}
|
769
|
-
}
|
770
|
-
exports.getPrerenderManifest = getPrerenderManifest;
|
771
|
-
// We only need this once per build
|
772
|
-
let _usesSrcCache;
|
773
|
-
async function usesSrcDirectory(workPath) {
|
774
|
-
if (!_usesSrcCache) {
|
775
|
-
const sourcePages = path_1.default.join(workPath, 'src', 'pages');
|
776
|
-
try {
|
777
|
-
if ((await fs_extra_1.default.stat(sourcePages)).isDirectory()) {
|
778
|
-
_usesSrcCache = true;
|
779
|
-
}
|
780
|
-
}
|
781
|
-
catch (_err) {
|
782
|
-
_usesSrcCache = false;
|
783
|
-
}
|
784
|
-
}
|
785
|
-
if (!_usesSrcCache) {
|
786
|
-
const sourceAppdir = path_1.default.join(workPath, 'src', 'app');
|
787
|
-
try {
|
788
|
-
if ((await fs_extra_1.default.stat(sourceAppdir)).isDirectory()) {
|
789
|
-
_usesSrcCache = true;
|
790
|
-
}
|
791
|
-
}
|
792
|
-
catch (_err) {
|
793
|
-
_usesSrcCache = false;
|
794
|
-
}
|
795
|
-
}
|
796
|
-
return Boolean(_usesSrcCache);
|
797
|
-
}
|
798
|
-
async function getSourceFilePathFromPage({ workPath, page, pageExtensions, }) {
|
799
|
-
const usesSrcDir = await usesSrcDirectory(workPath);
|
800
|
-
const extensionsToTry = pageExtensions || ['js', 'jsx', 'ts', 'tsx'];
|
801
|
-
for (const pageType of ['pages', 'app']) {
|
802
|
-
let fsPath = path_1.default.join(workPath, pageType, page);
|
803
|
-
if (usesSrcDir) {
|
804
|
-
fsPath = path_1.default.join(workPath, 'src', pageType, page);
|
805
|
-
}
|
806
|
-
if (fs_extra_1.default.existsSync(fsPath)) {
|
807
|
-
return path_1.default.relative(workPath, fsPath);
|
808
|
-
}
|
809
|
-
const extensionless = fsPath.replace(path_1.default.extname(fsPath), '');
|
810
|
-
for (const ext of extensionsToTry) {
|
811
|
-
fsPath = `${extensionless}.${ext}`;
|
812
|
-
// for appDir, we need to treat "index.js" as root-level "page.js"
|
813
|
-
if (pageType === 'app' &&
|
814
|
-
extensionless ===
|
815
|
-
path_1.default.join(workPath, `${usesSrcDir ? 'src/' : ''}app/index`)) {
|
816
|
-
fsPath = `${extensionless.replace(/index$/, 'page')}.${ext}`;
|
817
|
-
}
|
818
|
-
if (fs_extra_1.default.existsSync(fsPath)) {
|
819
|
-
return path_1.default.relative(workPath, fsPath);
|
820
|
-
}
|
821
|
-
}
|
822
|
-
if (isDirectory(extensionless)) {
|
823
|
-
if (pageType === 'pages') {
|
824
|
-
for (const ext of extensionsToTry) {
|
825
|
-
fsPath = path_1.default.join(extensionless, `index.${ext}`);
|
826
|
-
if (fs_extra_1.default.existsSync(fsPath)) {
|
827
|
-
return path_1.default.relative(workPath, fsPath);
|
828
|
-
}
|
829
|
-
}
|
830
|
-
// appDir
|
831
|
-
}
|
832
|
-
else {
|
833
|
-
for (const ext of extensionsToTry) {
|
834
|
-
// RSC
|
835
|
-
fsPath = path_1.default.join(extensionless, `page.${ext}`);
|
836
|
-
if (fs_extra_1.default.existsSync(fsPath)) {
|
837
|
-
return path_1.default.relative(workPath, fsPath);
|
838
|
-
}
|
839
|
-
// Route Handlers
|
840
|
-
fsPath = path_1.default.join(extensionless, `route.${ext}`);
|
841
|
-
if (fs_extra_1.default.existsSync(fsPath)) {
|
842
|
-
return path_1.default.relative(workPath, fsPath);
|
843
|
-
}
|
844
|
-
}
|
845
|
-
}
|
846
|
-
}
|
847
|
-
}
|
848
|
-
console.log(`WARNING: Unable to find source file for page ${page} with extensions: ${extensionsToTry.join(', ')}, this can cause functions config from \`vercel.json\` to not be applied`);
|
849
|
-
return '';
|
850
|
-
}
|
851
|
-
exports.getSourceFilePathFromPage = getSourceFilePathFromPage;
|
852
|
-
function isDirectory(path) {
|
853
|
-
return fs_extra_1.default.existsSync(path) && fs_extra_1.default.lstatSync(path).isDirectory();
|
854
|
-
}
|
855
|
-
function normalizeLocalePath(pathname, locales) {
|
856
|
-
let detectedLocale;
|
857
|
-
// first item will be empty string from splitting at first char
|
858
|
-
const pathnameParts = pathname.split('/');
|
859
|
-
(locales || []).some(locale => {
|
860
|
-
if (pathnameParts[1].toLowerCase() === locale.toLowerCase()) {
|
861
|
-
detectedLocale = locale;
|
862
|
-
pathnameParts.splice(1, 1);
|
863
|
-
pathname = pathnameParts.join('/') || '/';
|
864
|
-
return true;
|
865
|
-
}
|
866
|
-
return false;
|
867
|
-
});
|
868
|
-
return {
|
869
|
-
pathname,
|
870
|
-
detectedLocale,
|
871
|
-
};
|
872
|
-
}
|
873
|
-
exports.normalizeLocalePath = normalizeLocalePath;
|
874
|
-
function addLocaleOrDefault(pathname, routesManifest, locale) {
|
875
|
-
if (!routesManifest?.i18n)
|
876
|
-
return pathname;
|
877
|
-
if (!locale)
|
878
|
-
locale = routesManifest.i18n.defaultLocale;
|
879
|
-
return locale
|
880
|
-
? `/${locale}${pathname === '/index' ? '' : pathname}`
|
881
|
-
: pathname;
|
882
|
-
}
|
883
|
-
exports.addLocaleOrDefault = addLocaleOrDefault;
|
884
|
-
exports.MAX_UNCOMPRESSED_LAMBDA_SIZE = 250 * exports.MIB;
|
885
|
-
const LAMBDA_RESERVED_UNCOMPRESSED_SIZE = 2.5 * exports.MIB;
|
886
|
-
const LAMBDA_RESERVED_COMPRESSED_SIZE = 250 * exports.KIB;
|
887
|
-
async function getPageLambdaGroups({ entryPath, config, functionsConfigManifest, pages, prerenderRoutes, pageTraces, compressedPages, tracedPseudoLayer, initialPseudoLayer, initialPseudoLayerUncompressed, lambdaCompressedByteLimit, internalPages, pageExtensions, }) {
|
888
|
-
const groups = [];
|
889
|
-
for (const page of pages) {
|
890
|
-
const newPages = [...internalPages, page];
|
891
|
-
const routeName = normalizePage(page.replace(/\.js$/, ''));
|
892
|
-
const isPrerenderRoute = prerenderRoutes.has(routeName);
|
893
|
-
let opts = {};
|
894
|
-
if (functionsConfigManifest &&
|
895
|
-
functionsConfigManifest.functions[routeName]) {
|
896
|
-
opts = functionsConfigManifest.functions[routeName];
|
897
|
-
}
|
898
|
-
if (config && config.functions) {
|
899
|
-
const sourceFile = await getSourceFilePathFromPage({
|
900
|
-
workPath: entryPath,
|
901
|
-
page,
|
902
|
-
pageExtensions,
|
903
|
-
});
|
904
|
-
const vercelConfigOpts = await (0, build_utils_1.getLambdaOptionsFromFunction)({
|
905
|
-
sourceFile,
|
906
|
-
config,
|
907
|
-
});
|
908
|
-
opts = { ...vercelConfigOpts, ...opts };
|
909
|
-
}
|
910
|
-
let matchingGroup = groups.find(group => {
|
911
|
-
const matches = group.maxDuration === opts.maxDuration &&
|
912
|
-
group.memory === opts.memory &&
|
913
|
-
group.isPrerenders === isPrerenderRoute;
|
914
|
-
if (matches) {
|
915
|
-
let newTracedFilesSize = group.pseudoLayerBytes;
|
916
|
-
let newTracedFilesUncompressedSize = group.pseudoLayerUncompressedBytes;
|
917
|
-
for (const newPage of newPages) {
|
918
|
-
Object.keys(pageTraces[newPage] || {}).map(file => {
|
919
|
-
if (!group.pseudoLayer[file]) {
|
920
|
-
const item = tracedPseudoLayer[file];
|
921
|
-
newTracedFilesSize += item.compBuffer?.byteLength || 0;
|
922
|
-
newTracedFilesUncompressedSize += item.uncompressedSize || 0;
|
923
|
-
}
|
924
|
-
});
|
925
|
-
newTracedFilesSize += compressedPages[newPage].compBuffer.byteLength;
|
926
|
-
newTracedFilesUncompressedSize +=
|
927
|
-
compressedPages[newPage].uncompressedSize;
|
928
|
-
}
|
929
|
-
const underUncompressedLimit = newTracedFilesUncompressedSize <
|
930
|
-
exports.MAX_UNCOMPRESSED_LAMBDA_SIZE - LAMBDA_RESERVED_UNCOMPRESSED_SIZE;
|
931
|
-
const underCompressedLimit = newTracedFilesSize <
|
932
|
-
lambdaCompressedByteLimit - LAMBDA_RESERVED_COMPRESSED_SIZE;
|
933
|
-
return underUncompressedLimit && underCompressedLimit;
|
934
|
-
}
|
935
|
-
return false;
|
936
|
-
});
|
937
|
-
if (matchingGroup) {
|
938
|
-
matchingGroup.pages.push(page);
|
939
|
-
}
|
940
|
-
else {
|
941
|
-
const newGroup = {
|
942
|
-
pages: [page],
|
943
|
-
...opts,
|
944
|
-
isPrerenders: isPrerenderRoute,
|
945
|
-
isApiLambda: !!isApiPage(page),
|
946
|
-
pseudoLayerBytes: initialPseudoLayer.pseudoLayerBytes,
|
947
|
-
pseudoLayerUncompressedBytes: initialPseudoLayerUncompressed,
|
948
|
-
pseudoLayer: Object.assign({}, initialPseudoLayer.pseudoLayer),
|
949
|
-
};
|
950
|
-
groups.push(newGroup);
|
951
|
-
matchingGroup = newGroup;
|
952
|
-
}
|
953
|
-
for (const newPage of newPages) {
|
954
|
-
Object.keys(pageTraces[newPage] || {}).map(file => {
|
955
|
-
const pseudoItem = tracedPseudoLayer[file];
|
956
|
-
const compressedSize = pseudoItem?.compBuffer?.byteLength || 0;
|
957
|
-
if (!matchingGroup.pseudoLayer[file]) {
|
958
|
-
matchingGroup.pseudoLayer[file] = pseudoItem;
|
959
|
-
matchingGroup.pseudoLayerBytes += compressedSize;
|
960
|
-
matchingGroup.pseudoLayerUncompressedBytes +=
|
961
|
-
pseudoItem.uncompressedSize || 0;
|
962
|
-
}
|
963
|
-
});
|
964
|
-
// ensure the page file itself is accounted for when grouping as
|
965
|
-
// large pages can be created that can push the group over the limit
|
966
|
-
matchingGroup.pseudoLayerBytes +=
|
967
|
-
compressedPages[newPage].compBuffer.byteLength;
|
968
|
-
matchingGroup.pseudoLayerUncompressedBytes +=
|
969
|
-
compressedPages[newPage].uncompressedSize;
|
970
|
-
}
|
971
|
-
}
|
972
|
-
return groups;
|
973
|
-
}
|
974
|
-
exports.getPageLambdaGroups = getPageLambdaGroups;
|
975
|
-
const outputFunctionFileSizeInfo = (pages, pseudoLayer, pseudoLayerBytes, pseudoLayerUncompressedBytes, compressedPages) => {
|
976
|
-
const exceededLimitOutput = [];
|
977
|
-
console.log(`Serverless Function's page${pages.length === 1 ? '' : 's'}: ${pages.join(', ')}`);
|
978
|
-
exceededLimitOutput.push([
|
979
|
-
'Large Dependencies',
|
980
|
-
'Uncompressed size',
|
981
|
-
'Compressed size',
|
982
|
-
]);
|
983
|
-
const dependencies = {};
|
984
|
-
for (const fileKey of Object.keys(pseudoLayer)) {
|
985
|
-
if (!pseudoLayer[fileKey].isSymlink) {
|
986
|
-
const fileItem = pseudoLayer[fileKey];
|
987
|
-
const depKey = fileKey.split('/').slice(0, 3).join('/');
|
988
|
-
if (!dependencies[depKey]) {
|
989
|
-
dependencies[depKey] = {
|
990
|
-
compressed: 0,
|
991
|
-
uncompressed: 0,
|
992
|
-
};
|
993
|
-
}
|
994
|
-
dependencies[depKey].compressed += fileItem.compBuffer.byteLength;
|
995
|
-
dependencies[depKey].uncompressed += fileItem.uncompressedSize;
|
996
|
-
}
|
997
|
-
}
|
998
|
-
for (const page of pages) {
|
999
|
-
dependencies[`pages/${page}`] = {
|
1000
|
-
compressed: compressedPages[page].compBuffer.byteLength,
|
1001
|
-
uncompressed: compressedPages[page].uncompressedSize,
|
1002
|
-
};
|
1003
|
-
}
|
1004
|
-
let numLargeDependencies = 0;
|
1005
|
-
Object.keys(dependencies)
|
1006
|
-
.sort((a, b) => {
|
1007
|
-
// move largest dependencies to the top
|
1008
|
-
const aDep = dependencies[a];
|
1009
|
-
const bDep = dependencies[b];
|
1010
|
-
if (aDep.compressed > bDep.compressed) {
|
1011
|
-
return -1;
|
1012
|
-
}
|
1013
|
-
if (aDep.compressed < bDep.compressed) {
|
1014
|
-
return 1;
|
1015
|
-
}
|
1016
|
-
return 0;
|
1017
|
-
})
|
1018
|
-
.forEach(depKey => {
|
1019
|
-
const dep = dependencies[depKey];
|
1020
|
-
if (dep.compressed < 100 * exports.KIB && dep.uncompressed < 500 * exports.KIB) {
|
1021
|
-
// ignore smaller dependencies to reduce noise
|
1022
|
-
return;
|
1023
|
-
}
|
1024
|
-
exceededLimitOutput.push([
|
1025
|
-
depKey,
|
1026
|
-
(0, exports.prettyBytes)(dep.uncompressed),
|
1027
|
-
(0, exports.prettyBytes)(dep.compressed),
|
1028
|
-
]);
|
1029
|
-
numLargeDependencies += 1;
|
1030
|
-
});
|
1031
|
-
if (numLargeDependencies === 0) {
|
1032
|
-
exceededLimitOutput.push([
|
1033
|
-
'No large dependencies found (> 100KB compressed)',
|
1034
|
-
]);
|
1035
|
-
}
|
1036
|
-
exceededLimitOutput.push([]);
|
1037
|
-
exceededLimitOutput.push([
|
1038
|
-
'All dependencies',
|
1039
|
-
(0, exports.prettyBytes)(pseudoLayerUncompressedBytes),
|
1040
|
-
(0, exports.prettyBytes)(pseudoLayerBytes),
|
1041
|
-
]);
|
1042
|
-
console.log((0, text_table_1.default)(exceededLimitOutput, {
|
1043
|
-
align: ['l', 'r', 'r'],
|
1044
|
-
}));
|
1045
|
-
};
|
1046
|
-
exports.outputFunctionFileSizeInfo = outputFunctionFileSizeInfo;
|
1047
|
-
const detectLambdaLimitExceeding = async (lambdaGroups, compressedSizeLimit, compressedPages) => {
|
1048
|
-
// show debug info if within 5 MB of exceeding the limit
|
1049
|
-
const COMPRESSED_SIZE_LIMIT_CLOSE = compressedSizeLimit - 5 * exports.MIB;
|
1050
|
-
const UNCOMPRESSED_SIZE_LIMIT_CLOSE = exports.MAX_UNCOMPRESSED_LAMBDA_SIZE - 5 * exports.MIB;
|
1051
|
-
let numExceededLimit = 0;
|
1052
|
-
let numCloseToLimit = 0;
|
1053
|
-
let loggedHeadInfo = false;
|
1054
|
-
// pre-iterate to see if we are going to exceed the limit
|
1055
|
-
// or only get close so our first log line can be correct
|
1056
|
-
const filteredGroups = lambdaGroups.filter(group => {
|
1057
|
-
const exceededLimit = group.pseudoLayerBytes > compressedSizeLimit ||
|
1058
|
-
group.pseudoLayerUncompressedBytes > exports.MAX_UNCOMPRESSED_LAMBDA_SIZE;
|
1059
|
-
const closeToLimit = group.pseudoLayerBytes > COMPRESSED_SIZE_LIMIT_CLOSE ||
|
1060
|
-
group.pseudoLayerUncompressedBytes > UNCOMPRESSED_SIZE_LIMIT_CLOSE;
|
1061
|
-
if (closeToLimit ||
|
1062
|
-
exceededLimit ||
|
1063
|
-
(0, build_utils_1.getPlatformEnv)('BUILDER_DEBUG') ||
|
1064
|
-
process.env.NEXT_DEBUG_FUNCTION_SIZE) {
|
1065
|
-
if (exceededLimit) {
|
1066
|
-
numExceededLimit += 1;
|
1067
|
-
}
|
1068
|
-
if (closeToLimit) {
|
1069
|
-
numCloseToLimit += 1;
|
1070
|
-
}
|
1071
|
-
return true;
|
1072
|
-
}
|
1073
|
-
});
|
1074
|
-
for (const group of filteredGroups) {
|
1075
|
-
if (!loggedHeadInfo) {
|
1076
|
-
if (numExceededLimit || numCloseToLimit) {
|
1077
|
-
console.log(`Warning: Max serverless function size of ${(0, exports.prettyBytes)(compressedSizeLimit)} compressed or ${(0, exports.prettyBytes)(exports.MAX_UNCOMPRESSED_LAMBDA_SIZE)} uncompressed${numExceededLimit ? '' : ' almost'} reached`);
|
1078
|
-
}
|
1079
|
-
else {
|
1080
|
-
console.log(`Serverless function size info`);
|
1081
|
-
}
|
1082
|
-
loggedHeadInfo = true;
|
1083
|
-
}
|
1084
|
-
(0, exports.outputFunctionFileSizeInfo)(group.pages, group.pseudoLayer, group.pseudoLayerBytes, group.pseudoLayerUncompressedBytes, compressedPages);
|
1085
|
-
}
|
1086
|
-
if (numExceededLimit) {
|
1087
|
-
console.log(`Max serverless function size was exceeded for ${numExceededLimit} function${numExceededLimit === 1 ? '' : 's'}`);
|
1088
|
-
}
|
1089
|
-
};
|
1090
|
-
exports.detectLambdaLimitExceeding = detectLambdaLimitExceeding;
|
1091
|
-
// checks if prerender files are all static or not before creating lambdas
|
1092
|
-
const onPrerenderRouteInitial = (prerenderManifest, canUsePreviewMode, entryDirectory, nonLambdaSsgPages, routeKey, hasPages404, routesManifest, appDir) => {
|
1093
|
-
let static404Page;
|
1094
|
-
let static500Page;
|
1095
|
-
// Get the route file as it'd be mounted in the builder output
|
1096
|
-
const pr = prerenderManifest.staticRoutes[routeKey];
|
1097
|
-
const { initialRevalidate, srcRoute, dataRoute } = pr;
|
1098
|
-
const route = srcRoute || routeKey;
|
1099
|
-
const isAppPathRoute = appDir && (!dataRoute || dataRoute?.endsWith('.rsc'));
|
1100
|
-
const routeNoLocale = routesManifest?.i18n
|
1101
|
-
? normalizeLocalePath(routeKey, routesManifest.i18n.locales).pathname
|
1102
|
-
: routeKey;
|
1103
|
-
// if the 404 page used getStaticProps we need to update static404Page
|
1104
|
-
// since it wasn't populated from the staticPages group
|
1105
|
-
if (routeNoLocale === '/404') {
|
1106
|
-
static404Page = path_1.default.posix.join(entryDirectory, routeKey);
|
1107
|
-
}
|
1108
|
-
if (routeNoLocale === '/500') {
|
1109
|
-
static500Page = path_1.default.posix.join(entryDirectory, routeKey);
|
1110
|
-
}
|
1111
|
-
if (
|
1112
|
-
// App paths must be Prerenders to ensure Vary header is
|
1113
|
-
// correctly added
|
1114
|
-
!isAppPathRoute &&
|
1115
|
-
initialRevalidate === false &&
|
1116
|
-
(!canUsePreviewMode || (hasPages404 && routeNoLocale === '/404')) &&
|
1117
|
-
!prerenderManifest.fallbackRoutes[route] &&
|
1118
|
-
!prerenderManifest.blockingFallbackRoutes[route]) {
|
1119
|
-
if (routesManifest?.i18n &&
|
1120
|
-
Object.keys(prerenderManifest.staticRoutes).some(route => {
|
1121
|
-
const staticRoute = prerenderManifest.staticRoutes[route];
|
1122
|
-
return (staticRoute.srcRoute === srcRoute &&
|
1123
|
-
staticRoute.initialRevalidate !== false);
|
1124
|
-
})) {
|
1125
|
-
// if any locale static routes are using revalidate the page
|
1126
|
-
// requires a lambda
|
1127
|
-
return {
|
1128
|
-
static404Page,
|
1129
|
-
static500Page,
|
1130
|
-
};
|
1131
|
-
}
|
1132
|
-
nonLambdaSsgPages.add(route === '/' ? '/index' : route);
|
1133
|
-
}
|
1134
|
-
return {
|
1135
|
-
static404Page,
|
1136
|
-
static500Page,
|
1137
|
-
};
|
1138
|
-
};
|
1139
|
-
exports.onPrerenderRouteInitial = onPrerenderRouteInitial;
|
1140
|
-
let prerenderGroup = 1;
|
1141
|
-
const onPrerenderRoute = (prerenderRouteArgs) => (routeKey, { isBlocking, isFallback, isOmitted, locale, }) => {
|
1142
|
-
const { appDir, pagesDir, static404Page, localePrefixed404, entryDirectory, prerenderManifest, isSharedLambdas, isServerMode, canUsePreviewMode, lambdas, prerenders, pageLambdaMap, routesManifest, isCorrectNotFoundRoutes, isEmptyAllowQueryForPrendered, } = prerenderRouteArgs;
|
1143
|
-
if (isBlocking && isFallback) {
|
1144
|
-
throw new build_utils_1.NowBuildError({
|
1145
|
-
code: 'NEXT_ISBLOCKING_ISFALLBACK',
|
1146
|
-
message: 'invariant: isBlocking and isFallback cannot both be true',
|
1147
|
-
});
|
1148
|
-
}
|
1149
|
-
if (isFallback && isOmitted) {
|
1150
|
-
throw new build_utils_1.NowBuildError({
|
1151
|
-
code: 'NEXT_ISOMITTED_ISFALLBACK',
|
1152
|
-
message: 'invariant: isOmitted and isFallback cannot both be true',
|
1153
|
-
});
|
1154
|
-
}
|
1155
|
-
// Get the route file as it'd be mounted in the builder output
|
1156
|
-
let routeFileNoExt = routeKey === '/' ? '/index' : routeKey;
|
1157
|
-
let origRouteFileNoExt = routeFileNoExt;
|
1158
|
-
const { isLocalePrefixed } = prerenderManifest;
|
1159
|
-
if (!locale && isLocalePrefixed) {
|
1160
|
-
const localePathResult = normalizeLocalePath(routeKey, routesManifest?.i18n?.locales || []);
|
1161
|
-
locale = localePathResult.detectedLocale;
|
1162
|
-
origRouteFileNoExt =
|
1163
|
-
localePathResult.pathname === '/'
|
1164
|
-
? '/index'
|
1165
|
-
: localePathResult.pathname;
|
1166
|
-
}
|
1167
|
-
const nonDynamicSsg = !isFallback &&
|
1168
|
-
!isBlocking &&
|
1169
|
-
!isOmitted &&
|
1170
|
-
!prerenderManifest.staticRoutes[routeKey].srcRoute;
|
1171
|
-
// if there isn't a srcRoute then it's a non-dynamic SSG page
|
1172
|
-
if ((nonDynamicSsg && !isLocalePrefixed) || isFallback || isOmitted) {
|
1173
|
-
routeFileNoExt = addLocaleOrDefault(
|
1174
|
-
// root index files are located without folder/index.html
|
1175
|
-
routeFileNoExt, routesManifest, locale);
|
1176
|
-
}
|
1177
|
-
const isNotFound = prerenderManifest.notFoundRoutes.includes(routeKey);
|
1178
|
-
let initialRevalidate;
|
1179
|
-
let srcRoute;
|
1180
|
-
let dataRoute;
|
1181
|
-
let initialStatus;
|
1182
|
-
let initialHeaders;
|
1183
|
-
let experimentalBypassFor;
|
1184
|
-
if (isFallback || isBlocking) {
|
1185
|
-
const pr = isFallback
|
1186
|
-
? prerenderManifest.fallbackRoutes[routeKey]
|
1187
|
-
: prerenderManifest.blockingFallbackRoutes[routeKey];
|
1188
|
-
initialRevalidate = 1; // TODO: should Next.js provide this default?
|
1189
|
-
// @ts-ignore
|
1190
|
-
if (initialRevalidate === false) {
|
1191
|
-
// Lazy routes cannot be "snapshotted" in time.
|
1192
|
-
throw new build_utils_1.NowBuildError({
|
1193
|
-
code: 'NEXT_ISLAZY_INITIALREVALIDATE',
|
1194
|
-
message: 'invariant isLazy: initialRevalidate !== false',
|
1195
|
-
});
|
1196
|
-
}
|
1197
|
-
srcRoute = null;
|
1198
|
-
dataRoute = pr.dataRoute;
|
1199
|
-
experimentalBypassFor = pr.experimentalBypassFor;
|
1200
|
-
}
|
1201
|
-
else if (isOmitted) {
|
1202
|
-
initialRevalidate = false;
|
1203
|
-
srcRoute = routeKey;
|
1204
|
-
dataRoute = prerenderManifest.omittedRoutes[routeKey].dataRoute;
|
1205
|
-
experimentalBypassFor =
|
1206
|
-
prerenderManifest.omittedRoutes[routeKey].experimentalBypassFor;
|
1207
|
-
}
|
1208
|
-
else {
|
1209
|
-
const pr = prerenderManifest.staticRoutes[routeKey];
|
1210
|
-
({
|
1211
|
-
initialRevalidate,
|
1212
|
-
srcRoute,
|
1213
|
-
dataRoute,
|
1214
|
-
initialHeaders,
|
1215
|
-
initialStatus,
|
1216
|
-
experimentalBypassFor,
|
1217
|
-
} = pr);
|
1218
|
-
}
|
1219
|
-
let isAppPathRoute = false;
|
1220
|
-
// TODO: leverage manifest to determine app paths more accurately
|
1221
|
-
if (appDir && srcRoute && (!dataRoute || dataRoute?.endsWith('.rsc'))) {
|
1222
|
-
isAppPathRoute = true;
|
1223
|
-
}
|
1224
|
-
const isOmittedOrNotFound = isOmitted || isNotFound;
|
1225
|
-
let htmlFsRef;
|
1226
|
-
if (appDir && !dataRoute && isAppPathRoute && !(isBlocking || isFallback)) {
|
1227
|
-
const contentType = initialHeaders?.['content-type'];
|
1228
|
-
htmlFsRef = new build_utils_1.FileFsRef({
|
1229
|
-
fsPath: path_1.default.join(appDir, `${routeFileNoExt}.body`),
|
1230
|
-
contentType: contentType || 'text/html;charset=utf-8',
|
1231
|
-
});
|
1232
|
-
}
|
1233
|
-
else {
|
1234
|
-
htmlFsRef =
|
1235
|
-
isBlocking || (isNotFound && !static404Page)
|
1236
|
-
? // Blocking pages do not have an HTML fallback
|
1237
|
-
null
|
1238
|
-
: new build_utils_1.FileFsRef({
|
1239
|
-
fsPath: path_1.default.join(isAppPathRoute && !isOmittedOrNotFound && appDir
|
1240
|
-
? appDir
|
1241
|
-
: pagesDir, isFallback
|
1242
|
-
? // Fallback pages have a special file.
|
1243
|
-
addLocaleOrDefault(prerenderManifest.fallbackRoutes[routeKey].fallback, routesManifest, locale)
|
1244
|
-
: // Otherwise, the route itself should exist as a static HTML
|
1245
|
-
// file.
|
1246
|
-
`${isOmittedOrNotFound
|
1247
|
-
? localePrefixed404
|
1248
|
-
? addLocaleOrDefault('/404', routesManifest, locale)
|
1249
|
-
: '/404'
|
1250
|
-
: routeFileNoExt}.html`),
|
1251
|
-
});
|
1252
|
-
}
|
1253
|
-
const jsonFsRef =
|
1254
|
-
// JSON data does not exist for fallback or blocking pages
|
1255
|
-
isFallback || isBlocking || (isNotFound && !static404Page) || !dataRoute
|
1256
|
-
? null
|
1257
|
-
: new build_utils_1.FileFsRef({
|
1258
|
-
fsPath: path_1.default.join(isAppPathRoute && !isOmittedOrNotFound && appDir
|
1259
|
-
? appDir
|
1260
|
-
: pagesDir, `${isOmittedOrNotFound
|
1261
|
-
? localePrefixed404
|
1262
|
-
? addLocaleOrDefault('/404.html', routesManifest, locale)
|
1263
|
-
: '/404.html'
|
1264
|
-
: isAppPathRoute
|
1265
|
-
? dataRoute
|
1266
|
-
: routeFileNoExt + '.json'}`),
|
1267
|
-
});
|
1268
|
-
if (isOmittedOrNotFound) {
|
1269
|
-
initialStatus = 404;
|
1270
|
-
}
|
1271
|
-
if (isAppPathRoute) {
|
1272
|
-
// for literal index routes we need to append an additional /index
|
1273
|
-
// due to the proxy's normalizing for /index routes
|
1274
|
-
if (routeKey !== '/index' && routeKey.endsWith('/index')) {
|
1275
|
-
routeKey = `${routeKey}/index`;
|
1276
|
-
routeFileNoExt = routeKey;
|
1277
|
-
origRouteFileNoExt = routeKey;
|
1278
|
-
}
|
1279
|
-
}
|
1280
|
-
let outputPathPage = path_1.default.posix.join(entryDirectory, routeFileNoExt);
|
1281
|
-
if (!isAppPathRoute) {
|
1282
|
-
outputPathPage = normalizeIndexOutput(outputPathPage, isServerMode);
|
1283
|
-
}
|
1284
|
-
const outputPathPageOrig = path_1.default.posix.join(entryDirectory, origRouteFileNoExt);
|
1285
|
-
let lambda;
|
1286
|
-
let outputPathData = null;
|
1287
|
-
if (dataRoute) {
|
1288
|
-
outputPathData = path_1.default.posix.join(entryDirectory, dataRoute);
|
1289
|
-
if (nonDynamicSsg || isFallback || isOmitted) {
|
1290
|
-
outputPathData = outputPathData.replace(new RegExp(`${(0, escape_string_regexp_1.default)(origRouteFileNoExt)}.json$`),
|
1291
|
-
// ensure we escape "$" correctly while replacing as "$" is a special
|
1292
|
-
// character, we need to do double escaping as first is for the initial
|
1293
|
-
// replace on the routeFile and then the second on the outputPath
|
1294
|
-
`${routeFileNoExt.replace(/\$/g, '$$$$')}.json`);
|
1295
|
-
}
|
1296
|
-
}
|
1297
|
-
if (isSharedLambdas) {
|
1298
|
-
const outputSrcPathPage = normalizeIndexOutput(path_1.default.join('/', srcRoute == null
|
1299
|
-
? outputPathPageOrig
|
1300
|
-
: path_1.default.posix.join(entryDirectory, srcRoute === '/' ? '/index' : srcRoute)), isServerMode);
|
1301
|
-
const lambdaId = pageLambdaMap[outputSrcPathPage];
|
1302
|
-
lambda = lambdas[lambdaId];
|
1303
|
-
}
|
1304
|
-
else {
|
1305
|
-
const outputSrcPathPage = normalizeIndexOutput(srcRoute == null
|
1306
|
-
? outputPathPageOrig
|
1307
|
-
: path_1.default.posix.join(entryDirectory, srcRoute === '/' ? '/index' : srcRoute), isServerMode);
|
1308
|
-
lambda = lambdas[outputSrcPathPage];
|
1309
|
-
}
|
1310
|
-
if (!isAppPathRoute && !isNotFound && initialRevalidate === false) {
|
1311
|
-
if (htmlFsRef == null || jsonFsRef == null) {
|
1312
|
-
throw new build_utils_1.NowBuildError({
|
1313
|
-
code: 'NEXT_HTMLFSREF_JSONFSREF',
|
1314
|
-
message: `invariant: htmlFsRef != null && jsonFsRef != null ${routeFileNoExt}`,
|
1315
|
-
});
|
1316
|
-
}
|
1317
|
-
// if preview mode/On-Demand ISR can't be leveraged
|
1318
|
-
// we can output pure static outputs instead of prerenders
|
1319
|
-
if (!canUsePreviewMode ||
|
1320
|
-
(routeKey === '/404' && !lambdas[outputPathPage])) {
|
1321
|
-
htmlFsRef.contentType = _1.htmlContentType;
|
1322
|
-
prerenders[outputPathPage] = htmlFsRef;
|
1323
|
-
if (outputPathData) {
|
1324
|
-
prerenders[outputPathData] = jsonFsRef;
|
1325
|
-
}
|
1326
|
-
}
|
1327
|
-
}
|
1328
|
-
const isNotFoundPreview = isCorrectNotFoundRoutes &&
|
1329
|
-
!initialRevalidate &&
|
1330
|
-
canUsePreviewMode &&
|
1331
|
-
isServerMode &&
|
1332
|
-
isNotFound;
|
1333
|
-
if (prerenders[outputPathPage] == null &&
|
1334
|
-
(!isNotFound || initialRevalidate || isNotFoundPreview)) {
|
1335
|
-
if (lambda == null) {
|
1336
|
-
throw new build_utils_1.NowBuildError({
|
1337
|
-
code: 'NEXT_MISSING_LAMBDA',
|
1338
|
-
message: `Unable to find lambda for route: ${routeFileNoExt}`,
|
1339
|
-
});
|
1340
|
-
}
|
1341
|
-
// `allowQuery` is an array of query parameter keys that are allowed for
|
1342
|
-
// a given path. All other query keys will be striped. We can automatically
|
1343
|
-
// detect this for prerender (ISR) pages by reading the routes manifest file.
|
1344
|
-
const pageKey = srcRoute || routeKey;
|
1345
|
-
const route = routesManifest?.dynamicRoutes.find((r) => r.page === pageKey && !('isMiddleware' in r));
|
1346
|
-
const routeKeys = route?.routeKeys;
|
1347
|
-
// by default allowQuery should be undefined and only set when
|
1348
|
-
// we have sufficient information to set it
|
1349
|
-
let allowQuery;
|
1350
|
-
if (isEmptyAllowQueryForPrendered) {
|
1351
|
-
const isDynamic = isDynamicRoute(routeKey);
|
1352
|
-
if (!isDynamic) {
|
1353
|
-
// for non-dynamic routes we use an empty array since
|
1354
|
-
// no query values bust the cache for non-dynamic prerenders
|
1355
|
-
// prerendered paths also do not pass allowQuery as they match
|
1356
|
-
// during handle: 'filesystem' so should not cache differently
|
1357
|
-
// by query values
|
1358
|
-
allowQuery = [];
|
1359
|
-
}
|
1360
|
-
else if (routeKeys) {
|
1361
|
-
// if we have routeKeys in the routes-manifest we use those
|
1362
|
-
// for allowQuery for dynamic routes
|
1363
|
-
allowQuery = Object.values(routeKeys);
|
1364
|
-
}
|
1365
|
-
}
|
1366
|
-
else {
|
1367
|
-
const isDynamic = isDynamicRoute(pageKey);
|
1368
|
-
if (routeKeys) {
|
1369
|
-
// if we have routeKeys in the routes-manifest we use those
|
1370
|
-
// for allowQuery for dynamic routes
|
1371
|
-
allowQuery = Object.values(routeKeys);
|
1372
|
-
}
|
1373
|
-
else if (!isDynamic) {
|
1374
|
-
// for non-dynamic routes we use an empty array since
|
1375
|
-
// no query values bust the cache for non-dynamic prerenders
|
1376
|
-
allowQuery = [];
|
1377
|
-
}
|
1378
|
-
}
|
1379
|
-
const rscEnabled = !!routesManifest?.rsc;
|
1380
|
-
const rscVaryHeader = routesManifest?.rsc?.varyHeader ||
|
1381
|
-
'RSC, Next-Router-State-Tree, Next-Router-Prefetch';
|
1382
|
-
const rscContentTypeHeader = routesManifest?.rsc?.contentTypeHeader || exports.RSC_CONTENT_TYPE;
|
1383
|
-
let sourcePath;
|
1384
|
-
if (`/${outputPathPage}` !== srcRoute && srcRoute) {
|
1385
|
-
sourcePath = srcRoute;
|
1386
|
-
}
|
1387
|
-
prerenders[outputPathPage] = new build_utils_1.Prerender({
|
1388
|
-
expiration: initialRevalidate,
|
1389
|
-
lambda,
|
1390
|
-
allowQuery,
|
1391
|
-
fallback: htmlFsRef,
|
1392
|
-
group: prerenderGroup,
|
1393
|
-
bypassToken: prerenderManifest.bypassToken,
|
1394
|
-
experimentalBypassFor,
|
1395
|
-
initialStatus,
|
1396
|
-
initialHeaders,
|
1397
|
-
sourcePath,
|
1398
|
-
...(isNotFound
|
1399
|
-
? {
|
1400
|
-
initialStatus: 404,
|
1401
|
-
}
|
1402
|
-
: {}),
|
1403
|
-
...(rscEnabled
|
1404
|
-
? {
|
1405
|
-
initialHeaders: {
|
1406
|
-
...initialHeaders,
|
1407
|
-
vary: rscVaryHeader,
|
1408
|
-
},
|
1409
|
-
}
|
1410
|
-
: {}),
|
1411
|
-
});
|
1412
|
-
if (outputPathData) {
|
1413
|
-
prerenders[outputPathData] = new build_utils_1.Prerender({
|
1414
|
-
expiration: initialRevalidate,
|
1415
|
-
lambda,
|
1416
|
-
allowQuery,
|
1417
|
-
fallback: jsonFsRef,
|
1418
|
-
group: prerenderGroup,
|
1419
|
-
bypassToken: prerenderManifest.bypassToken,
|
1420
|
-
experimentalBypassFor,
|
1421
|
-
...(isNotFound
|
1422
|
-
? {
|
1423
|
-
initialStatus: 404,
|
1424
|
-
}
|
1425
|
-
: {}),
|
1426
|
-
...(rscEnabled
|
1427
|
-
? {
|
1428
|
-
initialHeaders: {
|
1429
|
-
'content-type': rscContentTypeHeader,
|
1430
|
-
vary: rscVaryHeader,
|
1431
|
-
},
|
1432
|
-
}
|
1433
|
-
: {}),
|
1434
|
-
});
|
1435
|
-
}
|
1436
|
-
++prerenderGroup;
|
1437
|
-
if (routesManifest?.i18n && isBlocking) {
|
1438
|
-
for (const locale of routesManifest.i18n.locales) {
|
1439
|
-
const localeRouteFileNoExt = addLocaleOrDefault(routeFileNoExt, routesManifest, locale);
|
1440
|
-
const localeOutputPathPage = normalizeIndexOutput(path_1.default.posix.join(entryDirectory, localeRouteFileNoExt), isServerMode);
|
1441
|
-
const origPrerenderPage = prerenders[outputPathPage];
|
1442
|
-
prerenders[localeOutputPathPage] = {
|
1443
|
-
...origPrerenderPage,
|
1444
|
-
group: prerenderGroup,
|
1445
|
-
};
|
1446
|
-
if (outputPathData) {
|
1447
|
-
const localeOutputPathData = outputPathData.replace(new RegExp(`${(0, escape_string_regexp_1.default)(origRouteFileNoExt)}.json$`), `${localeRouteFileNoExt}${localeRouteFileNoExt !== origRouteFileNoExt &&
|
1448
|
-
origRouteFileNoExt === '/index'
|
1449
|
-
? '/index'
|
1450
|
-
: ''}.json`);
|
1451
|
-
const origPrerenderData = prerenders[outputPathData];
|
1452
|
-
prerenders[localeOutputPathData] = {
|
1453
|
-
...origPrerenderData,
|
1454
|
-
group: prerenderGroup,
|
1455
|
-
};
|
1456
|
-
}
|
1457
|
-
++prerenderGroup;
|
1458
|
-
}
|
1459
|
-
}
|
1460
|
-
}
|
1461
|
-
if (((nonDynamicSsg && !isLocalePrefixed) || isFallback || isOmitted) &&
|
1462
|
-
routesManifest?.i18n &&
|
1463
|
-
!locale) {
|
1464
|
-
// load each locale
|
1465
|
-
for (const locale of routesManifest.i18n.locales) {
|
1466
|
-
if (locale === routesManifest.i18n.defaultLocale)
|
1467
|
-
continue;
|
1468
|
-
(0, exports.onPrerenderRoute)(prerenderRouteArgs)(routeKey, {
|
1469
|
-
isBlocking,
|
1470
|
-
isFallback,
|
1471
|
-
isOmitted,
|
1472
|
-
locale,
|
1473
|
-
});
|
1474
|
-
}
|
1475
|
-
}
|
1476
|
-
};
|
1477
|
-
exports.onPrerenderRoute = onPrerenderRoute;
|
1478
|
-
async function getStaticFiles(entryPath, entryDirectory, outputDirectory) {
|
1479
|
-
const collectLabel = 'Collected static files (public/, static/, .next/static)';
|
1480
|
-
console.time(collectLabel);
|
1481
|
-
const nextStaticFiles = await (0, build_utils_1.glob)('**', path_1.default.join(entryPath, outputDirectory, 'static'));
|
1482
|
-
const staticFolderFiles = await (0, build_utils_1.glob)('**', path_1.default.join(entryPath, 'static'));
|
1483
|
-
let publicFolderFiles = {};
|
1484
|
-
let publicFolderPath;
|
1485
|
-
if (await fs_extra_1.default.pathExists(path_1.default.join(entryPath, 'public'))) {
|
1486
|
-
publicFolderPath = path_1.default.join(entryPath, 'public');
|
1487
|
-
}
|
1488
|
-
else if (
|
1489
|
-
// check at the same level as the output directory also
|
1490
|
-
await fs_extra_1.default.pathExists(path_1.default.join(entryPath, outputDirectory, '../public'))) {
|
1491
|
-
publicFolderPath = path_1.default.join(entryPath, outputDirectory, '../public');
|
1492
|
-
}
|
1493
|
-
if (publicFolderPath) {
|
1494
|
-
(0, build_utils_1.debug)(`Using public folder at ${publicFolderPath}`);
|
1495
|
-
publicFolderFiles = await (0, build_utils_1.glob)('**/*', publicFolderPath);
|
1496
|
-
}
|
1497
|
-
else {
|
1498
|
-
(0, build_utils_1.debug)('No public folder found');
|
1499
|
-
}
|
1500
|
-
const staticFiles = {};
|
1501
|
-
const staticDirectoryFiles = {};
|
1502
|
-
const publicDirectoryFiles = {};
|
1503
|
-
for (const file of Object.keys(nextStaticFiles)) {
|
1504
|
-
staticFiles[path_1.default.posix.join(entryDirectory, `_next/static/${file}`)] =
|
1505
|
-
nextStaticFiles[file];
|
1506
|
-
}
|
1507
|
-
for (const file of Object.keys(staticFolderFiles)) {
|
1508
|
-
staticDirectoryFiles[path_1.default.posix.join(entryDirectory, 'static', file)] =
|
1509
|
-
staticFolderFiles[file];
|
1510
|
-
}
|
1511
|
-
for (const file of Object.keys(publicFolderFiles)) {
|
1512
|
-
publicDirectoryFiles[path_1.default.posix.join(entryDirectory, file)] =
|
1513
|
-
publicFolderFiles[file];
|
1514
|
-
}
|
1515
|
-
console.timeEnd(collectLabel);
|
1516
|
-
return {
|
1517
|
-
staticFiles,
|
1518
|
-
staticDirectoryFiles,
|
1519
|
-
publicDirectoryFiles,
|
1520
|
-
};
|
1521
|
-
}
|
1522
|
-
exports.getStaticFiles = getStaticFiles;
|
1523
|
-
function normalizeIndexOutput(outputName, isServerMode) {
|
1524
|
-
if (outputName !== 'index' && outputName !== '/index' && isServerMode) {
|
1525
|
-
return outputName.replace(/\/index$/, '');
|
1526
|
-
}
|
1527
|
-
return outputName;
|
1528
|
-
}
|
1529
|
-
exports.normalizeIndexOutput = normalizeIndexOutput;
|
1530
|
-
/**
|
1531
|
-
* The path to next-server was changed in
|
1532
|
-
* https://github.com/vercel/next.js/pull/26756
|
1533
|
-
*/
|
1534
|
-
function getNextServerPath(nextVersion) {
|
1535
|
-
return semver_1.default.gte(nextVersion, 'v11.0.2-canary.4')
|
1536
|
-
? 'next/dist/server'
|
1537
|
-
: 'next/dist/next-server/server';
|
1538
|
-
}
|
1539
|
-
exports.getNextServerPath = getNextServerPath;
|
1540
|
-
// update to leverage
|
1541
|
-
function updateRouteSrc(route, index, manifestItems) {
|
1542
|
-
if (route.src) {
|
1543
|
-
route.src = manifestItems[index].regex;
|
1544
|
-
}
|
1545
|
-
return route;
|
1546
|
-
}
|
1547
|
-
exports.updateRouteSrc = updateRouteSrc;
|
1548
|
-
async function getPrivateOutputs(dir, entries) {
|
1549
|
-
const files = {};
|
1550
|
-
const routes = [];
|
1551
|
-
for (const [existingFile, outputFile] of Object.entries(entries)) {
|
1552
|
-
const fsPath = path_1.default.join(dir, existingFile);
|
1553
|
-
try {
|
1554
|
-
const { mode, size } = await (0, fs_extra_1.stat)(fsPath);
|
1555
|
-
if (size > 30 * 1024 * 1024) {
|
1556
|
-
throw new Error(`Exceeds maximum file size: ${size}`);
|
1557
|
-
}
|
1558
|
-
files[outputFile] = new build_utils_1.FileFsRef({ mode, fsPath });
|
1559
|
-
routes.push({
|
1560
|
-
src: `/${outputFile}`,
|
1561
|
-
dest: '/404',
|
1562
|
-
status: 404,
|
1563
|
-
continue: true,
|
1564
|
-
});
|
1565
|
-
}
|
1566
|
-
catch (error) {
|
1567
|
-
(0, build_utils_1.debug)(`Private file ${existingFile} had an error and will not be uploaded: ${error}`);
|
1568
|
-
}
|
1569
|
-
}
|
1570
|
-
return { files, routes };
|
1571
|
-
}
|
1572
|
-
exports.getPrivateOutputs = getPrivateOutputs;
|
1573
|
-
const vercelFunctionRegionsVar = process.env.VERCEL_FUNCTION_REGIONS;
|
1574
|
-
let vercelFunctionRegions;
|
1575
|
-
if (vercelFunctionRegionsVar) {
|
1576
|
-
vercelFunctionRegions = vercelFunctionRegionsVar.split(',');
|
1577
|
-
}
|
1578
|
-
/**
|
1579
|
-
* Normalizes the regions config that comes from the Next.js edge functions manifest.
|
1580
|
-
* Ensures that config like `home` and `global` are converted to the corresponding Vercel region config.
|
1581
|
-
* In the future we'll want to make `home` and `global` part of the Build Output API.
|
1582
|
-
* - `home` refers to the regions set in vercel.json or on the Vercel dashboard project config.
|
1583
|
-
* - `global` refers to all regions.
|
1584
|
-
*/
|
1585
|
-
function normalizeRegions(regions) {
|
1586
|
-
if (typeof regions === 'string') {
|
1587
|
-
regions = [regions];
|
1588
|
-
}
|
1589
|
-
const newRegions = [];
|
1590
|
-
for (const region of regions) {
|
1591
|
-
// Explicitly mentioned as `home` is one of the explicit values for preferredRegion in Next.js.
|
1592
|
-
if (region === 'home') {
|
1593
|
-
if (vercelFunctionRegions) {
|
1594
|
-
// Includes the regions from the VERCEL_FUNCTION_REGIONS env var.
|
1595
|
-
newRegions.push(...vercelFunctionRegions);
|
1596
|
-
}
|
1597
|
-
continue;
|
1598
|
-
}
|
1599
|
-
// Explicitly mentioned as `global` is one of the explicit values for preferredRegion in Next.js.
|
1600
|
-
if (region === 'global') {
|
1601
|
-
// Uses `all` instead as that's how it's implemented on Vercel.
|
1602
|
-
// Returns here as when all is provided all regions will be matched.
|
1603
|
-
return 'all';
|
1604
|
-
}
|
1605
|
-
// Explicitly mentioned as `auto` is one of the explicit values for preferredRegion in Next.js.
|
1606
|
-
if (region === 'auto') {
|
1607
|
-
// Returns here as when auto is provided all regions will be matched.
|
1608
|
-
return 'auto';
|
1609
|
-
}
|
1610
|
-
newRegions.push(region);
|
1611
|
-
}
|
1612
|
-
// Ensure we don't pass an empty array as that is not supported.
|
1613
|
-
if (newRegions.length === 0) {
|
1614
|
-
return undefined;
|
1615
|
-
}
|
1616
|
-
return newRegions;
|
1617
|
-
}
|
1618
|
-
function normalizeEdgeFunctionPath(shortPath, appPathRoutesManifest) {
|
1619
|
-
if (shortPath.startsWith('app/') &&
|
1620
|
-
(shortPath.endsWith('/page') ||
|
1621
|
-
shortPath.endsWith('/route') ||
|
1622
|
-
shortPath === 'app/_not-found')) {
|
1623
|
-
const ogRoute = shortPath.replace(/^app\//, '/');
|
1624
|
-
shortPath = (appPathRoutesManifest[ogRoute] ||
|
1625
|
-
shortPath.replace(/(^|\/)(page|route)$/, '')).replace(/^\//, '');
|
1626
|
-
if (!shortPath || shortPath === '/') {
|
1627
|
-
shortPath = 'index';
|
1628
|
-
}
|
1629
|
-
}
|
1630
|
-
return shortPath;
|
1631
|
-
}
|
1632
|
-
exports.normalizeEdgeFunctionPath = normalizeEdgeFunctionPath;
|
1633
|
-
async function getMiddlewareBundle({ entryPath, outputDirectory, routesManifest, isCorrectMiddlewareOrder, prerenderBypassToken, nextVersion, appPathRoutesManifest, }) {
|
1634
|
-
const middlewareManifest = await getMiddlewareManifest(entryPath, outputDirectory);
|
1635
|
-
const sortedFunctions = [
|
1636
|
-
...(!middlewareManifest
|
1637
|
-
? []
|
1638
|
-
: middlewareManifest.sortedMiddleware.map(key => ({
|
1639
|
-
key,
|
1640
|
-
edgeFunction: middlewareManifest?.middleware[key],
|
1641
|
-
type: 'middleware',
|
1642
|
-
}))),
|
1643
|
-
...Object.entries(middlewareManifest?.functions ?? {}).map(([key, edgeFunction]) => {
|
1644
|
-
return {
|
1645
|
-
key,
|
1646
|
-
edgeFunction,
|
1647
|
-
type: 'function',
|
1648
|
-
};
|
1649
|
-
}),
|
1650
|
-
];
|
1651
|
-
if (middlewareManifest && sortedFunctions.length > 0) {
|
1652
|
-
const workerConfigs = await Promise.all(sortedFunctions.map(async ({ key, edgeFunction, type }) => {
|
1653
|
-
try {
|
1654
|
-
const wrappedModuleSource = await (0, get_edge_function_source_1.getNextjsEdgeFunctionSource)(edgeFunction.files, {
|
1655
|
-
name: edgeFunction.name,
|
1656
|
-
staticRoutes: routesManifest.staticRoutes,
|
1657
|
-
dynamicRoutes: routesManifest.dynamicRoutes.filter(r => !('isMiddleware' in r)),
|
1658
|
-
nextConfig: {
|
1659
|
-
basePath: routesManifest.basePath,
|
1660
|
-
i18n: routesManifest.i18n,
|
1661
|
-
},
|
1662
|
-
}, path_1.default.resolve(entryPath, outputDirectory), edgeFunction.wasm);
|
1663
|
-
return {
|
1664
|
-
type,
|
1665
|
-
page: edgeFunction.page,
|
1666
|
-
edgeFunction: (() => {
|
1667
|
-
const { source, map } = wrappedModuleSource.sourceAndMap();
|
1668
|
-
const transformedMap = (0, sourcemapped_1.stringifySourceMap)(transformSourceMap(map));
|
1669
|
-
const wasmFiles = (edgeFunction.wasm ?? []).reduce((acc, { filePath, name }) => {
|
1670
|
-
const fullFilePath = path_1.default.join(entryPath, outputDirectory, filePath);
|
1671
|
-
acc[`wasm/${name}.wasm`] = new build_utils_1.FileFsRef({
|
1672
|
-
mode: 0o644,
|
1673
|
-
contentType: 'application/wasm',
|
1674
|
-
fsPath: fullFilePath,
|
1675
|
-
});
|
1676
|
-
return acc;
|
1677
|
-
}, {});
|
1678
|
-
const assetFiles = (edgeFunction.assets ?? []).reduce((acc, { filePath, name }) => {
|
1679
|
-
const fullFilePath = path_1.default.join(entryPath, outputDirectory, filePath);
|
1680
|
-
acc[`assets/${name}`] = new build_utils_1.FileFsRef({
|
1681
|
-
mode: 0o644,
|
1682
|
-
contentType: 'application/octet-stream',
|
1683
|
-
fsPath: fullFilePath,
|
1684
|
-
});
|
1685
|
-
return acc;
|
1686
|
-
}, {});
|
1687
|
-
return new build_utils_1.EdgeFunction({
|
1688
|
-
deploymentTarget: 'v8-worker',
|
1689
|
-
name: edgeFunction.name,
|
1690
|
-
files: {
|
1691
|
-
'index.js': new build_utils_1.FileBlob({
|
1692
|
-
data: source,
|
1693
|
-
contentType: 'application/javascript',
|
1694
|
-
mode: 0o644,
|
1695
|
-
}),
|
1696
|
-
...(transformedMap && {
|
1697
|
-
'index.js.map': new build_utils_1.FileBlob({
|
1698
|
-
data: transformedMap,
|
1699
|
-
contentType: 'application/json',
|
1700
|
-
mode: 0o644,
|
1701
|
-
}),
|
1702
|
-
}),
|
1703
|
-
...wasmFiles,
|
1704
|
-
...assetFiles,
|
1705
|
-
},
|
1706
|
-
regions: edgeFunction.regions
|
1707
|
-
? normalizeRegions(edgeFunction.regions)
|
1708
|
-
: undefined,
|
1709
|
-
entrypoint: 'index.js',
|
1710
|
-
assets: (edgeFunction.assets ?? []).map(({ name }) => {
|
1711
|
-
return {
|
1712
|
-
name,
|
1713
|
-
path: `assets/${name}`,
|
1714
|
-
};
|
1715
|
-
}),
|
1716
|
-
framework: {
|
1717
|
-
slug: 'nextjs',
|
1718
|
-
version: nextVersion,
|
1719
|
-
},
|
1720
|
-
});
|
1721
|
-
})(),
|
1722
|
-
routeMatchers: getRouteMatchers(edgeFunction, routesManifest),
|
1723
|
-
};
|
1724
|
-
}
|
1725
|
-
catch (e) {
|
1726
|
-
e.message = `Can't build edge function ${key}: ${e.message}`;
|
1727
|
-
throw e;
|
1728
|
-
}
|
1729
|
-
}));
|
1730
|
-
const source = {
|
1731
|
-
staticRoutes: [],
|
1732
|
-
dynamicRouteMap: new Map(),
|
1733
|
-
edgeFunctions: {},
|
1734
|
-
};
|
1735
|
-
for (const worker of workerConfigs.values()) {
|
1736
|
-
const edgeFile = worker.edgeFunction.name;
|
1737
|
-
let shortPath = edgeFile;
|
1738
|
-
// Replacing the folder prefix for the page
|
1739
|
-
//
|
1740
|
-
// For `pages/`, use file base name directly:
|
1741
|
-
// pages/index -> index
|
1742
|
-
// For `app/`, use folder name, handle the root page as index:
|
1743
|
-
// app/route/page -> route
|
1744
|
-
// app/page -> index
|
1745
|
-
// app/index/page -> index/index
|
1746
|
-
if (shortPath.startsWith('pages/')) {
|
1747
|
-
shortPath = shortPath.replace(/^pages\//, '');
|
1748
|
-
}
|
1749
|
-
else {
|
1750
|
-
shortPath = normalizeEdgeFunctionPath(shortPath, appPathRoutesManifest);
|
1751
|
-
}
|
1752
|
-
if (routesManifest?.basePath) {
|
1753
|
-
shortPath = normalizeIndexOutput(path_1.default.posix.join('./', routesManifest?.basePath, shortPath.replace(/^\//, '')), true);
|
1754
|
-
}
|
1755
|
-
worker.edgeFunction.name = shortPath;
|
1756
|
-
source.edgeFunctions[shortPath] = worker.edgeFunction;
|
1757
|
-
// we don't add the route for edge functions as these
|
1758
|
-
// are already added in the routes-manifest under dynamicRoutes
|
1759
|
-
if (worker.type === 'function') {
|
1760
|
-
continue;
|
1761
|
-
}
|
1762
|
-
for (const matcher of worker.routeMatchers) {
|
1763
|
-
const route = {
|
1764
|
-
continue: true,
|
1765
|
-
src: matcher.regexp,
|
1766
|
-
has: matcher.has,
|
1767
|
-
missing: [
|
1768
|
-
{
|
1769
|
-
type: 'header',
|
1770
|
-
key: 'x-prerender-revalidate',
|
1771
|
-
value: prerenderBypassToken,
|
1772
|
-
},
|
1773
|
-
...(matcher.missing || []),
|
1774
|
-
],
|
1775
|
-
};
|
1776
|
-
route.middlewarePath = shortPath;
|
1777
|
-
route.middlewareRawSrc = matcher.originalSource
|
1778
|
-
? [matcher.originalSource]
|
1779
|
-
: [];
|
1780
|
-
if (isCorrectMiddlewareOrder) {
|
1781
|
-
route.override = true;
|
1782
|
-
}
|
1783
|
-
if (routesManifest.version > 3 && isDynamicRoute(worker.page)) {
|
1784
|
-
source.dynamicRouteMap.set(worker.page, route);
|
1785
|
-
}
|
1786
|
-
else {
|
1787
|
-
source.staticRoutes.push(route);
|
1788
|
-
}
|
1789
|
-
}
|
1790
|
-
}
|
1791
|
-
return source;
|
1792
|
-
}
|
1793
|
-
return {
|
1794
|
-
staticRoutes: [],
|
1795
|
-
dynamicRouteMap: new Map(),
|
1796
|
-
edgeFunctions: {},
|
1797
|
-
};
|
1798
|
-
}
|
1799
|
-
exports.getMiddlewareBundle = getMiddlewareBundle;
|
1800
|
-
/**
|
1801
|
-
* Attempts to read the functions config manifest from the pre-defined
|
1802
|
-
* location. If the manifest can't be found it will resolve to
|
1803
|
-
* undefined.
|
1804
|
-
*/
|
1805
|
-
async function getFunctionsConfigManifest(entryPath, outputDirectory) {
|
1806
|
-
const functionConfigManifestPath = path_1.default.join(entryPath, outputDirectory, './server/functions-config-manifest.json');
|
1807
|
-
const hasManifest = await fs_extra_1.default
|
1808
|
-
.access(functionConfigManifestPath)
|
1809
|
-
.then(() => true)
|
1810
|
-
.catch(() => false);
|
1811
|
-
if (!hasManifest) {
|
1812
|
-
return;
|
1813
|
-
}
|
1814
|
-
const manifest = await fs_extra_1.default.readJSON(functionConfigManifestPath);
|
1815
|
-
return manifest.version === 1 ? manifest : undefined;
|
1816
|
-
}
|
1817
|
-
exports.getFunctionsConfigManifest = getFunctionsConfigManifest;
|
1818
|
-
/**
|
1819
|
-
* Attempts to read the middleware manifest from the pre-defined
|
1820
|
-
* location. If the manifest can't be found it will resolve to
|
1821
|
-
* undefined.
|
1822
|
-
*/
|
1823
|
-
async function getMiddlewareManifest(entryPath, outputDirectory) {
|
1824
|
-
const middlewareManifestPath = path_1.default.join(entryPath, outputDirectory, './server/middleware-manifest.json');
|
1825
|
-
const hasManifest = await fs_extra_1.default
|
1826
|
-
.access(middlewareManifestPath)
|
1827
|
-
.then(() => true)
|
1828
|
-
.catch(() => false);
|
1829
|
-
if (!hasManifest) {
|
1830
|
-
return;
|
1831
|
-
}
|
1832
|
-
const manifest = (await fs_extra_1.default.readJSON(middlewareManifestPath));
|
1833
|
-
return manifest.version === 1
|
1834
|
-
? upgradeMiddlewareManifest(manifest)
|
1835
|
-
: manifest;
|
1836
|
-
}
|
1837
|
-
exports.getMiddlewareManifest = getMiddlewareManifest;
|
1838
|
-
function upgradeMiddlewareManifest(v1) {
|
1839
|
-
function updateInfo(v1Info) {
|
1840
|
-
const { regexp, ...rest } = v1Info;
|
1841
|
-
return {
|
1842
|
-
...rest,
|
1843
|
-
matchers: [{ regexp }],
|
1844
|
-
};
|
1845
|
-
}
|
1846
|
-
const middleware = Object.fromEntries(Object.entries(v1.middleware).map(([p, info]) => [p, updateInfo(info)]));
|
1847
|
-
const functions = v1.functions
|
1848
|
-
? Object.fromEntries(Object.entries(v1.functions).map(([p, info]) => [p, updateInfo(info)]))
|
1849
|
-
: undefined;
|
1850
|
-
return {
|
1851
|
-
...v1,
|
1852
|
-
version: 2,
|
1853
|
-
middleware,
|
1854
|
-
functions,
|
1855
|
-
};
|
1856
|
-
}
|
1857
|
-
exports.upgradeMiddlewareManifest = upgradeMiddlewareManifest;
|
1858
|
-
/**
|
1859
|
-
* For an object containing middleware info and a routes manifest this will
|
1860
|
-
* generate a string with the route that will activate the middleware on
|
1861
|
-
* Vercel Proxy.
|
1862
|
-
*
|
1863
|
-
* @param param0 The middleware info including matchers and page.
|
1864
|
-
* @param param1 The routes manifest
|
1865
|
-
* @returns matchers for the middleware route.
|
1866
|
-
*/
|
1867
|
-
function getRouteMatchers(info, { basePath = '', i18n }) {
|
1868
|
-
function getRegexp(regexp) {
|
1869
|
-
if (info.page === '/') {
|
1870
|
-
return regexp;
|
1871
|
-
}
|
1872
|
-
const locale = i18n?.locales.length
|
1873
|
-
? `(?:/(${i18n.locales
|
1874
|
-
.map(locale => (0, escape_string_regexp_1.default)(locale))
|
1875
|
-
.join('|')}))?`
|
1876
|
-
: '';
|
1877
|
-
return `(?:^${basePath}${locale}${regexp.substring(1)})`;
|
1878
|
-
}
|
1879
|
-
function normalizeHas(has) {
|
1880
|
-
return has.map(v => v.type === 'header'
|
1881
|
-
? {
|
1882
|
-
...v,
|
1883
|
-
key: v.key.toLowerCase(),
|
1884
|
-
}
|
1885
|
-
: v);
|
1886
|
-
}
|
1887
|
-
return info.matchers.map(matcher => {
|
1888
|
-
const m = {
|
1889
|
-
regexp: getRegexp(matcher.regexp),
|
1890
|
-
originalSource: matcher.originalSource,
|
1891
|
-
};
|
1892
|
-
if (matcher.has) {
|
1893
|
-
m.has = normalizeHas(matcher.has);
|
1894
|
-
}
|
1895
|
-
if (matcher.missing) {
|
1896
|
-
m.missing = normalizeHas(matcher.missing);
|
1897
|
-
}
|
1898
|
-
return m;
|
1899
|
-
});
|
1900
|
-
}
|
1901
|
-
/**
|
1902
|
-
* Makes the sources more human-readable in the source map
|
1903
|
-
* by removing webpack-specific prefixes
|
1904
|
-
*/
|
1905
|
-
function transformSourceMap(sourcemap) {
|
1906
|
-
if (!sourcemap)
|
1907
|
-
return;
|
1908
|
-
const sources = sourcemap.sources
|
1909
|
-
?.map(source => {
|
1910
|
-
return source.replace(/^webpack:\/\/?_N_E\/(?:\.\/)?/, '');
|
1911
|
-
})
|
1912
|
-
// Hide the Next.js entrypoint
|
1913
|
-
.map(source => {
|
1914
|
-
return source.startsWith('?') ? '[native code]' : source;
|
1915
|
-
});
|
1916
|
-
return { ...sourcemap, sources };
|
1917
|
-
}
|
1918
|
-
function getOperationType({ group, prerenderManifest, pageFileName, }) {
|
1919
|
-
if (group?.isApiLambda || isApiPage(pageFileName)) {
|
1920
|
-
return 'API';
|
1921
|
-
}
|
1922
|
-
if (group?.isPrerenders) {
|
1923
|
-
return 'ISR';
|
1924
|
-
}
|
1925
|
-
if (pageFileName && prerenderManifest) {
|
1926
|
-
const { blockingFallbackRoutes = {}, fallbackRoutes = {} } = prerenderManifest;
|
1927
|
-
if (pageFileName in blockingFallbackRoutes ||
|
1928
|
-
pageFileName in fallbackRoutes) {
|
1929
|
-
return 'ISR';
|
1930
|
-
}
|
1931
|
-
}
|
1932
|
-
return 'Page'; // aka SSR
|
1933
|
-
}
|
1934
|
-
exports.getOperationType = getOperationType;
|
1935
|
-
function isApiPage(page) {
|
1936
|
-
if (!page) {
|
1937
|
-
return false;
|
1938
|
-
}
|
1939
|
-
return page
|
1940
|
-
.replace(/\\/g, '/')
|
1941
|
-
.match(/(serverless|server)\/pages\/api(\/|\.js$)/);
|
1942
|
-
}
|
1943
|
-
exports.isApiPage = isApiPage;
|