@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.
@@ -1,1330 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.serverBuild = void 0;
7
- const path_1 = __importDefault(require("path"));
8
- const semver_1 = __importDefault(require("semver"));
9
- const async_sema_1 = require("async-sema");
10
- const build_utils_1 = require("@vercel/build-utils");
11
- const _1 = require(".");
12
- const utils_1 = require("./utils");
13
- const nft_1 = require("@vercel/nft");
14
- const resolve_from_1 = __importDefault(require("resolve-from"));
15
- const fs_extra_1 = __importDefault(require("fs-extra"));
16
- const escape_string_regexp_1 = __importDefault(require("escape-string-regexp"));
17
- const pretty_bytes_1 = __importDefault(require("pretty-bytes"));
18
- // related PR: https://github.com/vercel/next.js/pull/30046
19
- const CORRECT_NOT_FOUND_ROUTES_VERSION = 'v12.0.1';
20
- const CORRECT_MIDDLEWARE_ORDER_VERSION = 'v12.1.7-canary.29';
21
- const NEXT_DATA_MIDDLEWARE_RESOLVING_VERSION = 'v12.1.7-canary.33';
22
- const EMPTY_ALLOW_QUERY_FOR_PRERENDERED_VERSION = 'v12.2.0';
23
- const CORRECTED_MANIFESTS_VERSION = 'v12.2.0';
24
- // related PR: https://github.com/vercel/next.js/pull/52997
25
- const BUNDLED_SERVER_NEXT_VERSION = '13.4.20-canary.26';
26
- const BUNDLED_SERVER_NEXT_PATH = 'next/dist/compiled/next-server/server.runtime.prod.js';
27
- async function serverBuild({ dynamicPages, pagesDir, config = {}, functionsConfigManifest, privateOutputs, baseDir, workPath, entryPath, nodeVersion, buildId, escapedBuildId, dynamicPrefix, entryDirectory, outputDirectory, redirects, beforeFilesRewrites, afterFilesRewrites, fallbackRewrites, headers, dataRoutes, hasIsr404Page, hasIsr500Page, imagesManifest, wildcardConfig, routesManifest, staticPages, lambdaPages, localePrefixed404, nextVersion, lambdaAppPaths, canUsePreviewMode, trailingSlash, prerenderManifest, appPathRoutesManifest, omittedPrerenderRoutes, trailingSlashRedirects, isCorrectLocaleAPIRoutes, lambdaCompressedByteLimit, requiredServerFilesManifest, }) {
28
- lambdaPages = Object.assign({}, lambdaPages, lambdaAppPaths);
29
- const lambdas = {};
30
- const prerenders = {};
31
- const lambdaPageKeys = Object.keys(lambdaPages);
32
- const internalPages = ['_app.js', '_error.js', '_document.js'];
33
- const pageBuildTraces = await (0, build_utils_1.glob)('**/*.js.nft.json', pagesDir);
34
- const isEmptyAllowQueryForPrendered = semver_1.default.gte(nextVersion, EMPTY_ALLOW_QUERY_FOR_PRERENDERED_VERSION);
35
- const projectDir = requiredServerFilesManifest.relativeAppDir
36
- ? path_1.default.join(baseDir, requiredServerFilesManifest.relativeAppDir)
37
- : requiredServerFilesManifest.appDir || entryPath;
38
- // allow looking up original route from normalized route
39
- const inversedAppPathManifest = {};
40
- if (appPathRoutesManifest) {
41
- for (const ogRoute of Object.keys(appPathRoutesManifest)) {
42
- inversedAppPathManifest[appPathRoutesManifest[ogRoute]] = ogRoute;
43
- }
44
- }
45
- let appRscPrefetches = {};
46
- let appBuildTraces = {};
47
- let appDir = null;
48
- if (appPathRoutesManifest) {
49
- appDir = path_1.default.join(pagesDir, '../app');
50
- appBuildTraces = await (0, build_utils_1.glob)('**/*.js.nft.json', appDir);
51
- appRscPrefetches = await (0, build_utils_1.glob)(`**/*${utils_1.RSC_PREFETCH_SUFFIX}`, appDir);
52
- const rscContentTypeHeader = routesManifest?.rsc?.contentTypeHeader || utils_1.RSC_CONTENT_TYPE;
53
- // ensure all appRscPrefetches have a contentType since this is used by Next.js
54
- // to determine if it's a valid response
55
- for (const value of Object.values(appRscPrefetches)) {
56
- if (!value.contentType) {
57
- value.contentType = rscContentTypeHeader;
58
- }
59
- }
60
- }
61
- const isCorrectNotFoundRoutes = semver_1.default.gte(nextVersion, CORRECT_NOT_FOUND_ROUTES_VERSION);
62
- const isCorrectMiddlewareOrder = semver_1.default.gte(nextVersion, CORRECT_MIDDLEWARE_ORDER_VERSION);
63
- const isCorrectManifests = semver_1.default.gte(nextVersion, CORRECTED_MANIFESTS_VERSION);
64
- let hasStatic500 = !!staticPages[path_1.default.posix.join(entryDirectory, '500')];
65
- if (lambdaPageKeys.length === 0) {
66
- throw new build_utils_1.NowBuildError({
67
- code: 'NEXT_NO_SERVER_PAGES',
68
- message: 'No server pages were built',
69
- link: 'https://err.sh/vercel/vercel/now-next-no-serverless-pages-built',
70
- });
71
- }
72
- const pageMatchesApi = (page) => {
73
- const normalizedPage = `/${page.replace(/\.js$/, '')}`;
74
- return (!inversedAppPathManifest[normalizedPage] &&
75
- (page.startsWith('api/') || page === 'api.js'));
76
- };
77
- const { i18n } = routesManifest;
78
- const hasPages404 = routesManifest.pages404;
79
- let static404Page = staticPages[path_1.default.posix.join(entryDirectory, '404')] && hasPages404
80
- ? path_1.default.posix.join(entryDirectory, '404')
81
- : staticPages[path_1.default.posix.join(entryDirectory, '_errors/404')]
82
- ? path_1.default.posix.join(entryDirectory, '_errors/404')
83
- : undefined;
84
- if (!static404Page &&
85
- i18n &&
86
- staticPages[path_1.default.posix.join(entryDirectory, i18n.defaultLocale, '404')]) {
87
- static404Page = path_1.default.posix.join(entryDirectory, i18n.defaultLocale, '404');
88
- }
89
- if (!hasStatic500 && i18n) {
90
- hasStatic500 =
91
- !!staticPages[path_1.default.posix.join(entryDirectory, i18n.defaultLocale, '500')];
92
- }
93
- const lstatSema = new async_sema_1.Sema(25);
94
- const lstatResults = {};
95
- const nonLambdaSsgPages = new Set();
96
- Object.keys(prerenderManifest.staticRoutes).forEach(route => {
97
- const result = (0, utils_1.onPrerenderRouteInitial)(prerenderManifest, canUsePreviewMode, entryDirectory, nonLambdaSsgPages, route, routesManifest.pages404, routesManifest, appDir);
98
- if (result && result.static404Page) {
99
- static404Page = result.static404Page;
100
- }
101
- if (result && result.static500Page) {
102
- hasStatic500 = true;
103
- }
104
- });
105
- const hasLambdas = !static404Page ||
106
- lambdaPageKeys.some(page => !internalPages.includes(page) &&
107
- !nonLambdaSsgPages.has('/' + page.replace(/\.js$/, '')));
108
- if (lambdaPages['404.js']) {
109
- internalPages.push('404.js');
110
- }
111
- const prerenderRoutes = new Set([
112
- ...(canUsePreviewMode ? omittedPrerenderRoutes : []),
113
- ...Object.keys(prerenderManifest.blockingFallbackRoutes),
114
- ...Object.keys(prerenderManifest.fallbackRoutes),
115
- ...Object.keys(prerenderManifest.staticRoutes).map(route => {
116
- const staticRoute = prerenderManifest.staticRoutes[route];
117
- return staticRoute.srcRoute || route;
118
- }),
119
- ]);
120
- if (hasLambdas) {
121
- const initialTracingLabel = 'Traced Next.js server files in';
122
- console.time(initialTracingLabel);
123
- const initialTracedFiles = {};
124
- let initialFileList;
125
- let initialFileReasons;
126
- let nextServerBuildTrace;
127
- let instrumentationHookBuildTrace;
128
- const useBundledServer = semver_1.default.gte(nextVersion, BUNDLED_SERVER_NEXT_VERSION) &&
129
- process.env.VERCEL_NEXT_BUNDLED_SERVER === '1';
130
- if (useBundledServer) {
131
- (0, build_utils_1.debug)('Using bundled Next.js server');
132
- }
133
- const nextServerFile = (0, resolve_from_1.default)(projectDir, useBundledServer
134
- ? BUNDLED_SERVER_NEXT_PATH
135
- : `${(0, utils_1.getNextServerPath)(nextVersion)}/next-server.js`);
136
- try {
137
- // leverage next-server trace from build if available
138
- nextServerBuildTrace = JSON.parse(await fs_extra_1.default.readFile(path_1.default.join(entryPath, outputDirectory, useBundledServer
139
- ? 'next-minimal-server.js.nft.json'
140
- : 'next-server.js.nft.json'), 'utf8'));
141
- }
142
- catch (_) {
143
- // if the trace is unavailable we trace inside the runtime
144
- }
145
- try {
146
- instrumentationHookBuildTrace = JSON.parse(await fs_extra_1.default.readFile(path_1.default.join(entryPath, outputDirectory, 'server', 'instrumentation.js.nft.json'), 'utf8'));
147
- }
148
- catch (_) {
149
- // if the trace is unavailable it means `instrumentation.js` wasn't used
150
- }
151
- if (nextServerBuildTrace) {
152
- initialFileList = nextServerBuildTrace.files.map((file) => {
153
- return path_1.default.relative(baseDir, path_1.default.join(entryPath, outputDirectory, file));
154
- });
155
- initialFileReasons = new Map();
156
- (0, build_utils_1.debug)('Using next-server.js.nft.json trace from build');
157
- }
158
- else {
159
- (0, build_utils_1.debug)('tracing initial Next.js server files');
160
- const result = await (0, nft_1.nodeFileTrace)([nextServerFile], {
161
- base: baseDir,
162
- cache: {},
163
- processCwd: entryPath,
164
- ignore: [
165
- ...requiredServerFilesManifest.ignore.map(file => path_1.default.join(entryPath, file)),
166
- 'node_modules/next/dist/pages/**/*',
167
- `node_modules/${(0, utils_1.getNextServerPath)(nextVersion)}/lib/squoosh/**/*.wasm`,
168
- 'node_modules/next/dist/compiled/webpack/(bundle4|bundle5).js',
169
- 'node_modules/react/**/*.development.js',
170
- 'node_modules/react-dom/**/*.development.js',
171
- 'node_modules/use-subscription/**/*.development.js',
172
- 'node_modules/sharp/**/*',
173
- ],
174
- });
175
- initialFileList = Array.from(result.fileList);
176
- initialFileReasons = result.reasons;
177
- }
178
- if (instrumentationHookBuildTrace) {
179
- initialFileList = initialFileList.concat(instrumentationHookBuildTrace.files.map((file) => {
180
- return path_1.default.relative(baseDir, path_1.default.join(entryPath, outputDirectory, 'server', file));
181
- }));
182
- (0, build_utils_1.debug)('Using instrumentation.js.nft.json trace from build');
183
- }
184
- (0, build_utils_1.debug)('collecting initial Next.js server files');
185
- await Promise.all(initialFileList.map((0, utils_1.collectTracedFiles)(baseDir, lstatResults, lstatSema, initialFileReasons, initialTracedFiles)));
186
- (0, build_utils_1.debug)('creating initial pseudo layer');
187
- const initialPseudoLayer = await (0, utils_1.createPseudoLayer)(initialTracedFiles);
188
- console.timeEnd(initialTracingLabel);
189
- const lambdaCreationLabel = 'Created all serverless functions in';
190
- console.time(lambdaCreationLabel);
191
- const apiPages = [];
192
- const nonApiPages = [];
193
- const appRouterPages = [];
194
- const appRouteHandlers = [];
195
- lambdaPageKeys.forEach(page => {
196
- if (internalPages.includes(page) &&
197
- page !== '404.js' &&
198
- !(page === '_error.js' && !(static404Page || lambdaPages['404.js']))) {
199
- return;
200
- }
201
- const pathname = page.replace(/\.js$/, '');
202
- if (nonLambdaSsgPages.has(pathname)) {
203
- return;
204
- }
205
- const normalizedPathname = (0, utils_1.normalizePage)(pathname);
206
- if ((0, utils_1.isDynamicRoute)(normalizedPathname)) {
207
- dynamicPages.push(normalizedPathname);
208
- }
209
- if (lambdaAppPaths[page]) {
210
- if (lambdaAppPaths[page].fsPath.endsWith('route.js')) {
211
- appRouteHandlers.push(page);
212
- }
213
- else {
214
- appRouterPages.push(page);
215
- }
216
- }
217
- else if (pageMatchesApi(page)) {
218
- apiPages.push(page);
219
- }
220
- else {
221
- nonApiPages.push(page);
222
- }
223
- });
224
- const requiredFiles = {};
225
- requiredFiles[path_1.default.relative(baseDir, nextServerFile)] = new build_utils_1.FileFsRef({
226
- mode: (await fs_extra_1.default.lstat(nextServerFile)).mode,
227
- fsPath: nextServerFile,
228
- });
229
- if (static404Page) {
230
- // ensure static 404 page file is included in all lambdas
231
- // for notFound GS(S)P support
232
- if (i18n) {
233
- for (const locale of i18n.locales) {
234
- let static404File = staticPages[path_1.default.posix.join(entryDirectory, locale, '/404')];
235
- if (!static404File) {
236
- static404File = new build_utils_1.FileFsRef({
237
- fsPath: path_1.default.join(pagesDir, locale, '/404.html'),
238
- });
239
- if (!fs_extra_1.default.existsSync(static404File.fsPath)) {
240
- static404File = new build_utils_1.FileFsRef({
241
- fsPath: path_1.default.join(pagesDir, '/404.html'),
242
- });
243
- }
244
- }
245
- requiredFiles[path_1.default.relative(baseDir, static404File.fsPath)] =
246
- static404File;
247
- }
248
- }
249
- else {
250
- const static404File = staticPages[static404Page] ||
251
- new build_utils_1.FileFsRef({
252
- fsPath: path_1.default.join(pagesDir, '/404.html'),
253
- });
254
- requiredFiles[path_1.default.relative(baseDir, static404File.fsPath)] =
255
- static404File;
256
- }
257
- }
258
- // TODO: move this into Next.js' required server files manifest
259
- const envFiles = [];
260
- for (const file of await fs_extra_1.default.readdir(workPath)) {
261
- const isEnv = file === '.env' || file.startsWith('.env.');
262
- if (isEnv) {
263
- const statResult = await fs_extra_1.default.lstat(path_1.default.join(workPath, file));
264
- if (statResult.isFile()) {
265
- envFiles.push(file);
266
- }
267
- }
268
- }
269
- for (const envFile of envFiles) {
270
- requiredFiles[path_1.default.join(path_1.default.relative(baseDir, entryPath), envFile)] =
271
- new build_utils_1.FileFsRef({
272
- fsPath: path_1.default.join(workPath, envFile),
273
- });
274
- }
275
- await Promise.all(requiredServerFilesManifest.files.map(async (file) => {
276
- await lstatSema.acquire();
277
- let fsPath = path_1.default.join(entryPath,
278
- // remove last part of outputDirectory `.next` since this is already
279
- // included in the file path
280
- path_1.default.join(outputDirectory, '..'), file);
281
- if (projectDir) {
282
- fsPath = path_1.default.join(projectDir, file);
283
- }
284
- const relativePath = path_1.default.relative(baseDir, fsPath);
285
- const { mode } = await fs_extra_1.default.lstat(fsPath);
286
- lstatSema.release();
287
- requiredFiles[relativePath] = new build_utils_1.FileFsRef({
288
- mode,
289
- fsPath,
290
- });
291
- }));
292
- // add required files and internal pages to initial pseudo layer
293
- // so that we account for these in the size of each page group
294
- const requiredFilesLayer = await (0, utils_1.createPseudoLayer)(requiredFiles);
295
- Object.assign(initialPseudoLayer.pseudoLayer, requiredFilesLayer.pseudoLayer);
296
- initialPseudoLayer.pseudoLayerBytes += requiredFilesLayer.pseudoLayerBytes;
297
- const uncompressedInitialSize = Object.keys(initialPseudoLayer.pseudoLayer).reduce((prev, cur) => {
298
- const file = initialPseudoLayer.pseudoLayer[cur];
299
- return prev + file.uncompressedSize || 0;
300
- }, 0);
301
- (0, build_utils_1.debug)(JSON.stringify({
302
- uncompressedInitialSize,
303
- compressedInitialSize: initialPseudoLayer.pseudoLayerBytes,
304
- }, null, 2));
305
- if (initialPseudoLayer.pseudoLayerBytes > lambdaCompressedByteLimit ||
306
- uncompressedInitialSize > utils_1.MAX_UNCOMPRESSED_LAMBDA_SIZE) {
307
- console.log(`Warning: Max serverless function size of ${(0, pretty_bytes_1.default)(lambdaCompressedByteLimit)} compressed or ${(0, pretty_bytes_1.default)(utils_1.MAX_UNCOMPRESSED_LAMBDA_SIZE)} uncompressed reached`);
308
- (0, utils_1.outputFunctionFileSizeInfo)([], initialPseudoLayer.pseudoLayer, initialPseudoLayer.pseudoLayerBytes, uncompressedInitialSize, {});
309
- throw new build_utils_1.NowBuildError({
310
- message: `Required files read using Node.js fs library and node_modules exceed max lambda size of ${lambdaCompressedByteLimit} bytes`,
311
- code: 'NEXT_REQUIRED_FILES_LIMIT',
312
- link: 'https://vercel.com/docs/platform/limits#serverless-function-size',
313
- });
314
- }
315
- const launcherData = await fs_extra_1.default.readFile(path_1.default.join(__dirname, 'server-launcher.js'), 'utf8');
316
- let launcher = launcherData
317
- .replace('conf: __NEXT_CONFIG__', `conf: ${JSON.stringify({
318
- ...requiredServerFilesManifest.config,
319
- distDir: path_1.default.relative(projectDir, path_1.default.join(entryPath, outputDirectory)),
320
- compress: false,
321
- })}`)
322
- .replace('__NEXT_SERVER_PATH__', useBundledServer
323
- ? BUNDLED_SERVER_NEXT_PATH
324
- : `${(0, utils_1.getNextServerPath)(nextVersion)}/next-server.js`);
325
- const appLauncher = launcher.replace('// pre-next-server-target', `process.env.__NEXT_PRIVATE_PREBUNDLED_REACT = "${requiredServerFilesManifest.config?.experimental?.serverActions
326
- ? 'experimental'
327
- : 'next'}"`);
328
- if (entryDirectory !== '.' &&
329
- path_1.default.posix.join('/', entryDirectory) !== routesManifest.basePath) {
330
- // we normalize the entryDirectory in the request URL since
331
- // Next.js isn't aware of it and it isn't included in the
332
- // x-matched-path header
333
- launcher = launcher.replace('// entryDirectory handler', `req.url = req.url.replace(/^${path_1.default.posix
334
- .join('/', entryDirectory)
335
- .replace(/\//g, '\\/')}/, '')`);
336
- }
337
- const pageTraces = {};
338
- const compressedPages = {};
339
- const mergedPageKeys = [
340
- ...nonApiPages,
341
- ...appRouterPages,
342
- ...appRouteHandlers,
343
- ...apiPages,
344
- ...internalPages,
345
- ];
346
- const traceCache = {};
347
- const getOriginalPagePath = (page) => {
348
- let originalPagePath = page;
349
- if (appDir && lambdaAppPaths[page]) {
350
- const { fsPath } = lambdaAppPaths[page];
351
- originalPagePath = path_1.default.relative(appDir, fsPath);
352
- }
353
- return originalPagePath;
354
- };
355
- const getBuildTraceFile = (page) => {
356
- return (pageBuildTraces[page + '.nft.json'] ||
357
- appBuildTraces[page + '.nft.json']);
358
- };
359
- const pathsToTrace = mergedPageKeys
360
- .map(page => {
361
- if (!getBuildTraceFile(page)) {
362
- return lambdaPages[page].fsPath;
363
- }
364
- })
365
- .filter(Boolean);
366
- let traceResult;
367
- let parentFilesMap;
368
- if (pathsToTrace.length > 0) {
369
- traceResult = await (0, nft_1.nodeFileTrace)(pathsToTrace, {
370
- base: baseDir,
371
- cache: traceCache,
372
- processCwd: projectDir,
373
- });
374
- traceResult.esmFileList.forEach(file => traceResult?.fileList.add(file));
375
- parentFilesMap = (0, utils_1.getFilesMapFromReasons)(traceResult.fileList, traceResult.reasons);
376
- }
377
- for (const page of mergedPageKeys) {
378
- const tracedFiles = {};
379
- const originalPagePath = getOriginalPagePath(page);
380
- const pageBuildTrace = getBuildTraceFile(originalPagePath);
381
- let fileList;
382
- let reasons;
383
- if (pageBuildTrace) {
384
- const { files } = JSON.parse(await fs_extra_1.default.readFile(pageBuildTrace.fsPath, 'utf8'));
385
- // TODO: this will be moved to a separate worker in the future
386
- // although currently this is needed in the lambda
387
- const isAppPath = appDir && lambdaAppPaths[page];
388
- const serverComponentFile = isAppPath
389
- ? pageBuildTrace.fsPath.replace(/\.js\.nft\.json$/, '.__sc_client__.js')
390
- : null;
391
- if (serverComponentFile && (await fs_extra_1.default.pathExists(serverComponentFile))) {
392
- files.push(path_1.default.relative(path_1.default.dirname(pageBuildTrace.fsPath), serverComponentFile));
393
- try {
394
- const scTrace = JSON.parse(await fs_extra_1.default.readFile(`${serverComponentFile}.nft.json`, 'utf8'));
395
- scTrace.files.forEach((file) => files.push(file));
396
- }
397
- catch (err) {
398
- /* non-fatal for now */
399
- }
400
- }
401
- fileList = [];
402
- const curPagesDir = isAppPath && appDir ? appDir : pagesDir;
403
- const pageDir = path_1.default.dirname(path_1.default.join(curPagesDir, originalPagePath));
404
- const normalizedBaseDir = `${baseDir}${baseDir.endsWith(path_1.default.sep) ? '' : path_1.default.sep}`;
405
- files.forEach((file) => {
406
- const absolutePath = path_1.default.join(pageDir, file);
407
- // ensure we don't attempt including files outside
408
- // of the base dir e.g. `/bin/sh`
409
- if (absolutePath.startsWith(normalizedBaseDir)) {
410
- fileList.push(path_1.default.relative(baseDir, absolutePath));
411
- }
412
- });
413
- reasons = new Map();
414
- }
415
- else {
416
- fileList = Array.from(parentFilesMap?.get(path_1.default.relative(baseDir, lambdaPages[page].fsPath)) || []);
417
- if (!fileList) {
418
- throw new Error(`Invariant: Failed to trace ${page}, missing fileList`);
419
- }
420
- reasons = traceResult?.reasons || new Map();
421
- }
422
- await Promise.all(fileList.map((0, utils_1.collectTracedFiles)(baseDir, lstatResults, lstatSema, reasons, tracedFiles)));
423
- pageTraces[page] = tracedFiles;
424
- compressedPages[page] = (await (0, utils_1.createPseudoLayer)({
425
- [page]: lambdaPages[page],
426
- })).pseudoLayer[page];
427
- }
428
- const tracedPseudoLayer = await (0, utils_1.createPseudoLayer)(mergedPageKeys.reduce((prev, page) => {
429
- Object.assign(prev, pageTraces[page]);
430
- return prev;
431
- }, {}));
432
- const pageExtensions = requiredServerFilesManifest.config?.pageExtensions;
433
- const pageLambdaGroups = await (0, utils_1.getPageLambdaGroups)({
434
- entryPath: projectDir,
435
- config,
436
- functionsConfigManifest,
437
- pages: nonApiPages,
438
- prerenderRoutes,
439
- pageTraces,
440
- compressedPages,
441
- tracedPseudoLayer: tracedPseudoLayer.pseudoLayer,
442
- initialPseudoLayer,
443
- lambdaCompressedByteLimit,
444
- initialPseudoLayerUncompressed: uncompressedInitialSize,
445
- internalPages,
446
- pageExtensions,
447
- });
448
- for (const group of pageLambdaGroups) {
449
- group.isPages = true;
450
- }
451
- const appRouterLambdaGroups = await (0, utils_1.getPageLambdaGroups)({
452
- entryPath: projectDir,
453
- config,
454
- functionsConfigManifest,
455
- pages: appRouterPages,
456
- prerenderRoutes,
457
- pageTraces,
458
- compressedPages,
459
- tracedPseudoLayer: tracedPseudoLayer.pseudoLayer,
460
- initialPseudoLayer,
461
- lambdaCompressedByteLimit,
462
- initialPseudoLayerUncompressed: uncompressedInitialSize,
463
- internalPages,
464
- pageExtensions,
465
- });
466
- const appRouteHandlersLambdaGroups = await (0, utils_1.getPageLambdaGroups)({
467
- entryPath: projectDir,
468
- config,
469
- functionsConfigManifest,
470
- pages: appRouteHandlers,
471
- prerenderRoutes,
472
- pageTraces,
473
- compressedPages,
474
- tracedPseudoLayer: tracedPseudoLayer.pseudoLayer,
475
- initialPseudoLayer,
476
- lambdaCompressedByteLimit,
477
- initialPseudoLayerUncompressed: uncompressedInitialSize,
478
- internalPages,
479
- pageExtensions,
480
- });
481
- for (const group of appRouterLambdaGroups) {
482
- if (!group.isPrerenders) {
483
- group.isStreaming = true;
484
- }
485
- group.isAppRouter = true;
486
- }
487
- for (const group of appRouteHandlersLambdaGroups) {
488
- if (!group.isPrerenders) {
489
- group.isStreaming = true;
490
- }
491
- group.isAppRouter = true;
492
- group.isAppRouteHandler = true;
493
- }
494
- const apiLambdaGroups = await (0, utils_1.getPageLambdaGroups)({
495
- entryPath: projectDir,
496
- config,
497
- functionsConfigManifest,
498
- pages: apiPages,
499
- prerenderRoutes,
500
- pageTraces,
501
- compressedPages,
502
- tracedPseudoLayer: tracedPseudoLayer.pseudoLayer,
503
- initialPseudoLayer,
504
- initialPseudoLayerUncompressed: uncompressedInitialSize,
505
- lambdaCompressedByteLimit,
506
- internalPages,
507
- pageExtensions,
508
- });
509
- for (const group of apiLambdaGroups) {
510
- group.isApiLambda = true;
511
- }
512
- (0, build_utils_1.debug)(JSON.stringify({
513
- apiLambdaGroups: apiLambdaGroups.map(group => ({
514
- pages: group.pages,
515
- isPrerender: group.isPrerenders,
516
- pseudoLayerBytes: group.pseudoLayerBytes,
517
- uncompressedLayerBytes: group.pseudoLayerUncompressedBytes,
518
- })),
519
- pageLambdaGroups: pageLambdaGroups.map(group => ({
520
- pages: group.pages,
521
- isPrerender: group.isPrerenders,
522
- pseudoLayerBytes: group.pseudoLayerBytes,
523
- uncompressedLayerBytes: group.pseudoLayerUncompressedBytes,
524
- })),
525
- appRouterLambdaGroups: appRouterLambdaGroups.map(group => ({
526
- pages: group.pages,
527
- isPrerender: group.isPrerenders,
528
- pseudoLayerBytes: group.pseudoLayerBytes,
529
- uncompressedLayerBytes: group.pseudoLayerUncompressedBytes,
530
- })),
531
- appRouteHandlersLambdaGroups: appRouteHandlersLambdaGroups.map(group => ({
532
- pages: group.pages,
533
- isPrerender: group.isPrerenders,
534
- pseudoLayerBytes: group.pseudoLayerBytes,
535
- uncompressedLayerBytes: group.pseudoLayerUncompressedBytes,
536
- })),
537
- nextServerLayerSize: initialPseudoLayer.pseudoLayerBytes,
538
- }, null, 2));
539
- const combinedGroups = [
540
- ...pageLambdaGroups,
541
- ...appRouterLambdaGroups,
542
- ...apiLambdaGroups,
543
- ...appRouteHandlersLambdaGroups,
544
- ];
545
- await (0, utils_1.detectLambdaLimitExceeding)(combinedGroups, lambdaCompressedByteLimit, compressedPages);
546
- for (const group of combinedGroups) {
547
- const groupPageFiles = {};
548
- for (const page of [...group.pages, ...internalPages]) {
549
- const pageFileName = path_1.default.normalize(path_1.default.relative(baseDir, lambdaPages[page].fsPath));
550
- groupPageFiles[pageFileName] = compressedPages[page];
551
- }
552
- const updatedManifestFiles = {};
553
- if (isCorrectManifests) {
554
- // filter dynamic routes to only the included dynamic routes
555
- // in this specific serverless function so that we don't
556
- // accidentally match a dynamic route while resolving that
557
- // is not actually in this specific serverless function
558
- for (const manifest of [
559
- 'routes-manifest.json',
560
- 'server/pages-manifest.json',
561
- ]) {
562
- const fsPath = path_1.default.join(entryPath, outputDirectory, manifest);
563
- const relativePath = path_1.default.relative(baseDir, fsPath);
564
- delete group.pseudoLayer[relativePath];
565
- const manifestData = await fs_extra_1.default.readJSON(fsPath);
566
- const normalizedPages = new Set(group.pages.map(page => {
567
- page = `/${page.replace(/\.js$/, '')}`;
568
- if (page === '/index')
569
- page = '/';
570
- return page;
571
- }));
572
- switch (manifest) {
573
- case 'routes-manifest.json': {
574
- const filterItem = (item) => normalizedPages.has(item.page);
575
- manifestData.dynamicRoutes =
576
- manifestData.dynamicRoutes?.filter(filterItem);
577
- manifestData.staticRoutes =
578
- manifestData.staticRoutes?.filter(filterItem);
579
- break;
580
- }
581
- case 'server/pages-manifest.json': {
582
- for (const key of Object.keys(manifestData)) {
583
- if ((0, utils_1.isDynamicRoute)(key) && !normalizedPages.has(key)) {
584
- delete manifestData[key];
585
- }
586
- }
587
- break;
588
- }
589
- default: {
590
- throw new build_utils_1.NowBuildError({
591
- message: `Unexpected manifest value ${manifest}, please contact support if this continues`,
592
- code: 'NEXT_MANIFEST_INVARIANT',
593
- });
594
- }
595
- }
596
- updatedManifestFiles[relativePath] = new build_utils_1.FileBlob({
597
- contentType: 'application/json',
598
- data: JSON.stringify(manifestData),
599
- });
600
- }
601
- }
602
- const launcherFiles = {
603
- [path_1.default.join(path_1.default.relative(baseDir, projectDir), '___next_launcher.cjs')]: new build_utils_1.FileBlob({ data: group.isAppRouter ? appLauncher : launcher }),
604
- };
605
- const operationType = (0, utils_1.getOperationType)({ group, prerenderManifest });
606
- const lambda = await (0, utils_1.createLambdaFromPseudoLayers)({
607
- files: {
608
- ...launcherFiles,
609
- ...updatedManifestFiles,
610
- },
611
- layers: [group.pseudoLayer, groupPageFiles],
612
- handler: path_1.default.join(path_1.default.relative(baseDir, projectDir), '___next_launcher.cjs'),
613
- operationType,
614
- memory: group.memory,
615
- runtime: nodeVersion.runtime,
616
- maxDuration: group.maxDuration,
617
- isStreaming: group.isStreaming,
618
- nextVersion,
619
- });
620
- for (const page of group.pages) {
621
- const pageNoExt = page.replace(/\.js$/, '');
622
- let isPrerender = prerenderRoutes.has(path_1.default.join('/', pageNoExt === 'index' ? '' : pageNoExt));
623
- if (!isPrerender && routesManifest?.i18n) {
624
- isPrerender = routesManifest.i18n.locales.some(locale => {
625
- return prerenderRoutes.has(path_1.default.join('/', locale, pageNoExt === 'index' ? '' : pageNoExt));
626
- });
627
- }
628
- const outputName = (0, utils_1.normalizeIndexOutput)(path_1.default.posix.join(entryDirectory, pageNoExt), true);
629
- // we add locale prefixed outputs for SSR pages,
630
- // this is handled in onPrerenderRoute for SSG pages
631
- if (i18n &&
632
- !isPrerender &&
633
- !group.isAppRouter &&
634
- (!isCorrectLocaleAPIRoutes ||
635
- !(pageNoExt === 'api' || pageNoExt.startsWith('api/')))) {
636
- for (const locale of i18n.locales) {
637
- lambdas[(0, utils_1.normalizeIndexOutput)(path_1.default.posix.join(entryDirectory, locale, pageNoExt === 'index' ? '' : pageNoExt), true)] = lambda;
638
- }
639
- }
640
- else {
641
- lambdas[outputName] = lambda;
642
- }
643
- }
644
- }
645
- console.timeEnd(lambdaCreationLabel);
646
- }
647
- const prerenderRoute = (0, utils_1.onPrerenderRoute)({
648
- appDir,
649
- pagesDir,
650
- pageLambdaMap: {},
651
- lambdas,
652
- prerenders,
653
- entryDirectory,
654
- routesManifest,
655
- prerenderManifest,
656
- appPathRoutesManifest,
657
- isServerMode: true,
658
- isSharedLambdas: false,
659
- canUsePreviewMode,
660
- static404Page,
661
- localePrefixed404,
662
- hasPages404: routesManifest.pages404,
663
- isCorrectNotFoundRoutes,
664
- isEmptyAllowQueryForPrendered,
665
- });
666
- Object.keys(prerenderManifest.staticRoutes).forEach(route => prerenderRoute(route, {}));
667
- Object.keys(prerenderManifest.fallbackRoutes).forEach(route => prerenderRoute(route, { isFallback: true }));
668
- Object.keys(prerenderManifest.blockingFallbackRoutes).forEach(route => prerenderRoute(route, { isBlocking: true }));
669
- if (static404Page && canUsePreviewMode) {
670
- omittedPrerenderRoutes.forEach(route => {
671
- prerenderRoute(route, { isOmitted: true });
672
- });
673
- }
674
- prerenderRoutes.forEach(route => {
675
- if (routesManifest?.i18n) {
676
- route = (0, utils_1.normalizeLocalePath)(route, routesManifest.i18n.locales).pathname;
677
- }
678
- delete lambdas[path_1.default.posix.join('.', entryDirectory, route === '/' ? 'index' : route)];
679
- });
680
- const middleware = await (0, utils_1.getMiddlewareBundle)({
681
- config,
682
- entryPath,
683
- outputDirectory,
684
- routesManifest,
685
- isCorrectMiddlewareOrder,
686
- prerenderBypassToken: prerenderManifest.bypassToken || '',
687
- nextVersion,
688
- appPathRoutesManifest: appPathRoutesManifest || {},
689
- });
690
- const isNextDataServerResolving = middleware.staticRoutes.length > 0 &&
691
- semver_1.default.gte(nextVersion, NEXT_DATA_MIDDLEWARE_RESOLVING_VERSION);
692
- const dynamicRoutes = await (0, utils_1.getDynamicRoutes)(entryPath, entryDirectory, dynamicPages, false, routesManifest, omittedPrerenderRoutes, canUsePreviewMode, prerenderManifest.bypassToken || '', true, middleware.dynamicRouteMap).then(arr => (0, utils_1.localizeDynamicRoutes)(arr, dynamicPrefix, entryDirectory, staticPages, prerenderManifest, routesManifest, true, isCorrectLocaleAPIRoutes, inversedAppPathManifest));
693
- const pagesPlaceholderRscEntries = {};
694
- if (appDir) {
695
- // since we attempt to rewrite all paths to an .rsc variant,
696
- // we need to create dummy rsc outputs for all pages entries
697
- // this is so that an RSC request to a `pages` entry will match
698
- // rather than falling back to a catchall `app` entry
699
- // on the nextjs side, invalid RSC response payloads will correctly trigger an mpa navigation
700
- const pagesManifest = path_1.default.join(entryPath, outputDirectory, `server/pages-manifest.json`);
701
- const pagesData = await fs_extra_1.default.readJSON(pagesManifest);
702
- const pagesEntries = Object.keys(pagesData);
703
- for (const page of pagesEntries) {
704
- const pathName = page.startsWith('/') ? page.slice(1) : page;
705
- pagesPlaceholderRscEntries[`${pathName}.rsc`] = new build_utils_1.FileBlob({
706
- data: '{}',
707
- contentType: 'application/json',
708
- });
709
- }
710
- }
711
- const { staticFiles, publicDirectoryFiles, staticDirectoryFiles } = await (0, utils_1.getStaticFiles)(entryPath, entryDirectory, outputDirectory);
712
- const normalizeNextDataRoute = (isOverride = false) => {
713
- return isNextDataServerResolving
714
- ? [
715
- // strip _next/data prefix for resolving
716
- {
717
- src: `^${path_1.default.posix.join('/', entryDirectory, '/_next/data/', escapedBuildId, '/(.*).json')}`,
718
- dest: `${path_1.default.posix.join('/', entryDirectory, '/$1', trailingSlash ? '/' : '')}`,
719
- ...(isOverride ? { override: true } : {}),
720
- continue: true,
721
- has: [
722
- {
723
- type: 'header',
724
- key: 'x-nextjs-data',
725
- },
726
- ],
727
- },
728
- // normalize "/index" from "/_next/data/index.json" to -> just "/"
729
- // as matches a rewrite sources will expect just "/"
730
- {
731
- src: path_1.default.posix.join('^/', entryDirectory, '/index(?:/)?'),
732
- has: [
733
- {
734
- type: 'header',
735
- key: 'x-nextjs-data',
736
- },
737
- ],
738
- dest: path_1.default.posix.join('/', entryDirectory, trailingSlash ? '/' : ''),
739
- ...(isOverride ? { override: true } : {}),
740
- continue: true,
741
- },
742
- ]
743
- : [];
744
- };
745
- const denormalizeNextDataRoute = (isOverride = false) => {
746
- return isNextDataServerResolving
747
- ? [
748
- {
749
- src: path_1.default.posix.join('^/', entryDirectory !== '.'
750
- ? `${entryDirectory}${trailingSlash ? '/$' : '$'}`
751
- : '$'),
752
- has: [
753
- {
754
- type: 'header',
755
- key: 'x-nextjs-data',
756
- },
757
- ],
758
- dest: `${path_1.default.posix.join('/', entryDirectory, '/_next/data/', buildId, '/index.json')}`,
759
- continue: true,
760
- ...(isOverride ? { override: true } : {}),
761
- },
762
- {
763
- src: path_1.default.posix.join('^/', entryDirectory, '((?!_next/)(?:.*[^/]|.*))/?$'),
764
- has: [
765
- {
766
- type: 'header',
767
- key: 'x-nextjs-data',
768
- },
769
- ],
770
- dest: `${path_1.default.posix.join('/', entryDirectory, '/_next/data/', buildId, '/$1.json')}`,
771
- continue: true,
772
- ...(isOverride ? { override: true } : {}),
773
- },
774
- ]
775
- : [];
776
- };
777
- let nextDataCatchallOutput = undefined;
778
- if (isNextDataServerResolving) {
779
- const catchallFsPath = path_1.default.join(entryPath, outputDirectory, '__next_data_catchall.json');
780
- await fs_extra_1.default.writeFile(catchallFsPath, '{}');
781
- nextDataCatchallOutput = new build_utils_1.FileFsRef({
782
- contentType: 'application/json',
783
- fsPath: catchallFsPath,
784
- });
785
- }
786
- if (appPathRoutesManifest) {
787
- // create .rsc variant for app lambdas and edge functions
788
- // to match prerenders so we can route the same when the
789
- // __rsc__ header is present
790
- const edgeFunctions = middleware.edgeFunctions;
791
- for (let route of Object.values(appPathRoutesManifest)) {
792
- const ogRoute = inversedAppPathManifest[route];
793
- if (ogRoute.endsWith('/route')) {
794
- continue;
795
- }
796
- route = (0, utils_1.normalizeIndexOutput)(path_1.default.posix.join('./', entryDirectory, route === '/' ? '/index' : route), true);
797
- if (lambdas[route]) {
798
- lambdas[`${route}.rsc`] = lambdas[route];
799
- }
800
- if (edgeFunctions[route]) {
801
- edgeFunctions[`${route}.rsc`] = edgeFunctions[route];
802
- }
803
- }
804
- }
805
- const rscHeader = routesManifest.rsc?.header?.toLowerCase() || '__rsc__';
806
- const rscPrefetchHeader = routesManifest.rsc?.prefetchHeader?.toLowerCase();
807
- const rscVaryHeader = routesManifest?.rsc?.varyHeader ||
808
- 'RSC, Next-Router-State-Tree, Next-Router-Prefetch';
809
- const appNotFoundPath = path_1.default.posix.join('.', entryDirectory, '_not-found');
810
- return {
811
- wildcard: wildcardConfig,
812
- images: (0, utils_1.getImagesConfig)(imagesManifest),
813
- output: {
814
- ...publicDirectoryFiles,
815
- ...lambdas,
816
- ...appRscPrefetches,
817
- ...pagesPlaceholderRscEntries,
818
- // Prerenders may override Lambdas -- this is an intentional behavior.
819
- ...prerenders,
820
- ...staticPages,
821
- ...staticFiles,
822
- ...staticDirectoryFiles,
823
- ...privateOutputs.files,
824
- ...middleware.edgeFunctions,
825
- ...(isNextDataServerResolving
826
- ? {
827
- __next_data_catchall: nextDataCatchallOutput,
828
- }
829
- : {}),
830
- },
831
- routes: [
832
- /*
833
- Desired routes order
834
- - Runtime headers
835
- - User headers and redirects
836
- - Runtime redirects
837
- - Runtime routes
838
- - Check filesystem, if nothing found continue
839
- - User rewrites
840
- - Builder rewrites
841
- */
842
- // force trailingSlashRedirect to the very top so it doesn't
843
- // conflict with i18n routes that don't have or don't have the
844
- // trailing slash
845
- ...trailingSlashRedirects,
846
- ...privateOutputs.routes,
847
- // normalize _next/data URL before processing redirects
848
- ...normalizeNextDataRoute(true),
849
- ...(i18n
850
- ? [
851
- // Handle auto-adding current default locale to path based on
852
- // $wildcard
853
- {
854
- src: `^${path_1.default.posix.join('/', entryDirectory, '/')}(?!(?:_next/.*|${i18n.locales
855
- .map(locale => (0, escape_string_regexp_1.default)(locale))
856
- .join('|')})(?:/.*|$))(.*)$`,
857
- // we aren't able to ensure trailing slash mode here
858
- // so ensure this comes after the trailing slash redirect
859
- dest: `${entryDirectory !== '.'
860
- ? path_1.default.posix.join('/', entryDirectory)
861
- : ''}$wildcard/$1`,
862
- continue: true,
863
- },
864
- // Handle redirecting to locale specific domains
865
- ...(i18n.domains &&
866
- i18n.domains.length > 0 &&
867
- i18n.localeDetection !== false
868
- ? [
869
- {
870
- src: `^${path_1.default.posix.join('/', entryDirectory)}/?(?:${i18n.locales
871
- .map(locale => (0, escape_string_regexp_1.default)(locale))
872
- .join('|')})?/?$`,
873
- locale: {
874
- redirect: i18n.domains.reduce((prev, item) => {
875
- prev[item.defaultLocale] = `http${item.http ? '' : 's'}://${item.domain}/`;
876
- if (item.locales) {
877
- item.locales.map(locale => {
878
- prev[locale] = `http${item.http ? '' : 's'}://${item.domain}/${locale}`;
879
- });
880
- }
881
- return prev;
882
- }, {}),
883
- cookie: 'NEXT_LOCALE',
884
- },
885
- continue: true,
886
- },
887
- ]
888
- : []),
889
- // Handle redirecting to locale paths
890
- ...(i18n.localeDetection !== false
891
- ? [
892
- {
893
- // TODO: if default locale is included in this src it won't
894
- // be visitable by users who prefer another language since a
895
- // cookie isn't set signaling the default locale is
896
- // preferred on redirect currently, investigate adding this
897
- src: '/',
898
- locale: {
899
- redirect: i18n.locales.reduce((prev, locale) => {
900
- prev[locale] =
901
- locale === i18n.defaultLocale ? `/` : `/${locale}`;
902
- return prev;
903
- }, {}),
904
- cookie: 'NEXT_LOCALE',
905
- },
906
- continue: true,
907
- },
908
- ]
909
- : []),
910
- {
911
- src: `^${path_1.default.posix.join('/', entryDirectory)}$`,
912
- dest: `${path_1.default.posix.join('/', entryDirectory, i18n.defaultLocale)}`,
913
- continue: true,
914
- },
915
- // Auto-prefix non-locale path with default locale
916
- // note for prerendered pages this will cause
917
- // x-now-route-matches to contain the path minus the locale
918
- // e.g. for /de/posts/[slug] x-now-route-matches would have
919
- // 1=posts%2Fpost-1
920
- {
921
- src: `^${path_1.default.posix.join('/', entryDirectory, '/')}(?!(?:_next/.*|${i18n.locales
922
- .map(locale => (0, escape_string_regexp_1.default)(locale))
923
- .join('|')})(?:/.*|$))(.*)$`,
924
- dest: `${path_1.default.posix.join('/', entryDirectory, i18n.defaultLocale)}/$1`,
925
- continue: true,
926
- },
927
- ]
928
- : []),
929
- ...headers,
930
- ...redirects,
931
- // middleware comes directly after redirects but before
932
- // beforeFiles rewrites as middleware is not a "file" route
933
- ...(routesManifest?.skipMiddlewareUrlNormalize
934
- ? denormalizeNextDataRoute(true)
935
- : []),
936
- ...(isCorrectMiddlewareOrder ? middleware.staticRoutes : []),
937
- ...(routesManifest?.skipMiddlewareUrlNormalize
938
- ? normalizeNextDataRoute(true)
939
- : []),
940
- ...beforeFilesRewrites,
941
- // Make sure to 404 for the /404 path itself
942
- ...(i18n
943
- ? [
944
- {
945
- src: `${path_1.default.posix.join('/', entryDirectory, '/')}(?:${i18n.locales
946
- .map(locale => (0, escape_string_regexp_1.default)(locale))
947
- .join('|')})?[/]?404/?`,
948
- status: 404,
949
- continue: true,
950
- missing: [
951
- {
952
- type: 'header',
953
- key: 'x-prerender-revalidate',
954
- },
955
- ],
956
- },
957
- ]
958
- : [
959
- {
960
- src: path_1.default.posix.join('/', entryDirectory, '404/?'),
961
- status: 404,
962
- continue: true,
963
- missing: [
964
- {
965
- type: 'header',
966
- key: 'x-prerender-revalidate',
967
- },
968
- ],
969
- },
970
- ]),
971
- // Make sure to 500 when visiting /500 directly for static 500
972
- ...(!hasStatic500
973
- ? []
974
- : i18n
975
- ? [
976
- {
977
- src: `${path_1.default.posix.join('/', entryDirectory, '/')}(?:${i18n.locales
978
- .map(locale => (0, escape_string_regexp_1.default)(locale))
979
- .join('|')})?[/]?500`,
980
- status: 500,
981
- continue: true,
982
- },
983
- ]
984
- : [
985
- {
986
- src: path_1.default.posix.join('/', entryDirectory, '500'),
987
- status: 500,
988
- continue: true,
989
- },
990
- ]),
991
- // we need to undo _next/data normalize before checking filesystem
992
- ...denormalizeNextDataRoute(true),
993
- // while middleware was in beta the order came right before
994
- // handle: 'filesystem' we maintain this for older versions
995
- // to prevent a local/deploy mismatch
996
- ...(!isCorrectMiddlewareOrder ? middleware.staticRoutes : []),
997
- ...(appDir
998
- ? [
999
- ...(rscPrefetchHeader
1000
- ? [
1001
- {
1002
- src: `^${path_1.default.posix.join('/', entryDirectory, '/')}`,
1003
- has: [
1004
- {
1005
- type: 'header',
1006
- key: rscPrefetchHeader,
1007
- },
1008
- ],
1009
- dest: path_1.default.posix.join('/', entryDirectory, `/index${utils_1.RSC_PREFETCH_SUFFIX}`),
1010
- headers: { vary: rscVaryHeader },
1011
- continue: true,
1012
- override: true,
1013
- },
1014
- {
1015
- src: `^${path_1.default.posix.join('/', entryDirectory, '/((?!.+\\.rsc).+?)(?:/)?$')}`,
1016
- has: [
1017
- {
1018
- type: 'header',
1019
- key: rscPrefetchHeader,
1020
- },
1021
- ],
1022
- dest: path_1.default.posix.join('/', entryDirectory, `/$1${utils_1.RSC_PREFETCH_SUFFIX}`),
1023
- headers: { vary: rscVaryHeader },
1024
- continue: true,
1025
- override: true,
1026
- },
1027
- ]
1028
- : []),
1029
- {
1030
- src: `^${path_1.default.posix.join('/', entryDirectory, '/')}`,
1031
- has: [
1032
- {
1033
- type: 'header',
1034
- key: rscHeader,
1035
- },
1036
- ],
1037
- dest: path_1.default.posix.join('/', entryDirectory, '/index.rsc'),
1038
- headers: { vary: rscVaryHeader },
1039
- continue: true,
1040
- override: true,
1041
- },
1042
- {
1043
- src: `^${path_1.default.posix.join('/', entryDirectory, '/((?!.+\\.rsc).+?)(?:/)?$')}`,
1044
- has: [
1045
- {
1046
- type: 'header',
1047
- key: rscHeader,
1048
- },
1049
- ],
1050
- dest: path_1.default.posix.join('/', entryDirectory, '/$1.rsc'),
1051
- headers: { vary: rscVaryHeader },
1052
- continue: true,
1053
- override: true,
1054
- },
1055
- ]
1056
- : []),
1057
- // Next.js page lambdas, `static/` folder, reserved assets, and `public/`
1058
- // folder
1059
- { handle: 'filesystem' },
1060
- // ensure the basePath prefixed _next/image is rewritten to the root
1061
- // _next/image path
1062
- ...(routesManifest?.basePath
1063
- ? [
1064
- {
1065
- src: path_1.default.posix.join('/', entryDirectory, '_next/image/?'),
1066
- dest: '/_next/image',
1067
- check: true,
1068
- },
1069
- ]
1070
- : []),
1071
- // normalize _next/data URL before processing rewrites
1072
- ...normalizeNextDataRoute(),
1073
- ...(!isNextDataServerResolving
1074
- ? [
1075
- // No-op _next/data rewrite to trigger handle: 'rewrites' and then 404
1076
- // if no match to prevent rewriting _next/data unexpectedly
1077
- {
1078
- src: path_1.default.posix.join('/', entryDirectory, '_next/data/(.*)'),
1079
- dest: path_1.default.posix.join('/', entryDirectory, '_next/data/$1'),
1080
- check: true,
1081
- },
1082
- ]
1083
- : []),
1084
- ...(rscPrefetchHeader
1085
- ? [
1086
- {
1087
- src: path_1.default.posix.join('/', entryDirectory, `/index${utils_1.RSC_PREFETCH_SUFFIX}`),
1088
- dest: path_1.default.posix.join('/', entryDirectory, '/index.rsc'),
1089
- has: [
1090
- {
1091
- type: 'header',
1092
- key: rscPrefetchHeader,
1093
- },
1094
- ],
1095
- continue: true,
1096
- override: true,
1097
- },
1098
- {
1099
- src: `^${path_1.default.posix.join('/', entryDirectory, `/(.+?)${utils_1.RSC_PREFETCH_SUFFIX}(?:/)?$`)}`,
1100
- dest: path_1.default.posix.join('/', entryDirectory, '/$1.rsc'),
1101
- has: [
1102
- {
1103
- type: 'header',
1104
- key: rscPrefetchHeader,
1105
- },
1106
- ],
1107
- continue: true,
1108
- override: true,
1109
- },
1110
- ]
1111
- : []),
1112
- // These need to come before handle: miss or else they are grouped
1113
- // with that routing section
1114
- ...afterFilesRewrites,
1115
- { handle: 'resource' },
1116
- ...fallbackRewrites,
1117
- // make sure 404 page is used when a directory is matched without
1118
- // an index page
1119
- { src: path_1.default.posix.join('/', entryDirectory, '.*'), status: 404 },
1120
- { handle: 'miss' },
1121
- // We need to make sure to 404 for /_next after handle: miss since
1122
- // handle: miss is called before rewrites and to prevent rewriting /_next
1123
- {
1124
- src: path_1.default.posix.join('/', entryDirectory, '_next/static/(?:[^/]+/pages|pages|chunks|runtime|css|image|media)/.+'),
1125
- status: 404,
1126
- check: true,
1127
- dest: '$0',
1128
- },
1129
- // remove locale prefixes to check public files and
1130
- // to allow checking non-prefixed lambda outputs
1131
- ...(i18n
1132
- ? [
1133
- {
1134
- src: path_1.default.posix.join('/', entryDirectory, (0, escape_string_regexp_1.default)(i18n.defaultLocale)),
1135
- dest: '/',
1136
- check: true,
1137
- },
1138
- {
1139
- src: `^${path_1.default.posix.join('/', entryDirectory)}/?(?:${i18n.locales
1140
- .map(locale => (0, escape_string_regexp_1.default)(locale))
1141
- .join('|')})/(.*)`,
1142
- dest: `${path_1.default.posix.join('/', entryDirectory, '/')}$1`,
1143
- check: true,
1144
- },
1145
- ]
1146
- : []),
1147
- // routes that are called after each rewrite or after routes
1148
- // if there no rewrites
1149
- { handle: 'rewrite' },
1150
- // re-build /_next/data URL after resolving
1151
- ...denormalizeNextDataRoute(),
1152
- ...(isNextDataServerResolving
1153
- ? dataRoutes.filter(route => {
1154
- // filter to only static data routes as dynamic routes will be handled
1155
- // below
1156
- const { pathname } = new URL(route.dest || '/', 'http://n');
1157
- return !(0, utils_1.isDynamicRoute)(pathname.replace(/\.json$/, ''));
1158
- })
1159
- : []),
1160
- // /_next/data routes for getServerProps/getStaticProps pages
1161
- ...(isNextDataServerResolving
1162
- ? // when resolving data routes for middleware we need to include
1163
- // all dynamic routes including non-SSG/SSP so that the priority
1164
- // is correct
1165
- dynamicRoutes
1166
- .filter(route => !route.src.includes('.rsc'))
1167
- .map(route => {
1168
- route = Object.assign({}, route);
1169
- let normalizedSrc = route.src;
1170
- if (routesManifest.basePath) {
1171
- normalizedSrc = normalizedSrc.replace(new RegExp(`\\^${(0, escape_string_regexp_1.default)(routesManifest.basePath)}`), '^');
1172
- }
1173
- route.src = path_1.default.posix.join('^/', entryDirectory, '_next/data/', escapedBuildId, normalizedSrc
1174
- .replace(/\^\(\?:\/\(\?</, '(?:(?<')
1175
- .replace(/(^\^|\$$)/g, '') + '.json$');
1176
- const parsedDestination = new URL(route.dest || '/', 'http://n');
1177
- let pathname = parsedDestination.pathname;
1178
- const search = parsedDestination.search;
1179
- let isPrerender = !!prerenders[path_1.default.join('./', pathname)];
1180
- if (routesManifest.i18n) {
1181
- for (const locale of routesManifest.i18n?.locales || []) {
1182
- const prerenderPathname = pathname.replace(/^\/\$nextLocale/, `/${locale}`);
1183
- if (prerenders[path_1.default.join('./', prerenderPathname)]) {
1184
- isPrerender = true;
1185
- break;
1186
- }
1187
- }
1188
- }
1189
- if (isPrerender) {
1190
- if (routesManifest.basePath) {
1191
- pathname = pathname.replace(new RegExp(`^${(0, escape_string_regexp_1.default)(routesManifest.basePath)}`), '');
1192
- }
1193
- route.dest = `${routesManifest.basePath || ''}/_next/data/${buildId}${pathname}.json${search || ''}`;
1194
- }
1195
- return route;
1196
- })
1197
- .filter(Boolean)
1198
- : dataRoutes),
1199
- ...(!isNextDataServerResolving
1200
- ? [
1201
- // ensure we 404 for non-existent _next/data routes before
1202
- // trying page dynamic routes
1203
- {
1204
- src: path_1.default.posix.join('/', entryDirectory, '_next/data/(.*)'),
1205
- dest: path_1.default.posix.join('/', entryDirectory, '404'),
1206
- status: 404,
1207
- },
1208
- ]
1209
- : []),
1210
- // Dynamic routes (must come after dataRoutes as dataRoutes are more
1211
- // specific)
1212
- ...dynamicRoutes,
1213
- ...(isNextDataServerResolving
1214
- ? [
1215
- {
1216
- src: `^${path_1.default.posix.join('/', entryDirectory, '/_next/data/', escapedBuildId, '/(.*).json')}`,
1217
- headers: {
1218
- 'x-nextjs-matched-path': '/$1',
1219
- },
1220
- continue: true,
1221
- override: true,
1222
- },
1223
- // add a catch-all data route so we don't 404 when getting
1224
- // middleware effects
1225
- {
1226
- src: `^${path_1.default.posix.join('/', entryDirectory, '/_next/data/', escapedBuildId, '/(.*).json')}`,
1227
- dest: '__next_data_catchall',
1228
- },
1229
- ]
1230
- : []),
1231
- // routes to call after a file has been matched
1232
- { handle: 'hit' },
1233
- // Before we handle static files we need to set proper caching headers
1234
- {
1235
- // This ensures we only match known emitted-by-Next.js files and not
1236
- // user-emitted files which may be missing a hash in their filename.
1237
- src: path_1.default.posix.join('/', entryDirectory, `_next/static/(?:[^/]+/pages|pages|chunks|runtime|css|image|media|${escapedBuildId})/.+`),
1238
- // Next.js assets contain a hash or entropy in their filenames, so they
1239
- // are guaranteed to be unique and cacheable indefinitely.
1240
- headers: {
1241
- 'cache-control': `public,max-age=${_1.MAX_AGE_ONE_YEAR},immutable`,
1242
- },
1243
- continue: true,
1244
- important: true,
1245
- },
1246
- // TODO: remove below workaround when `/` is allowed to be output
1247
- // different than `/index`
1248
- {
1249
- src: path_1.default.posix.join('/', entryDirectory, '/index'),
1250
- headers: {
1251
- 'x-matched-path': '/',
1252
- },
1253
- continue: true,
1254
- important: true,
1255
- },
1256
- {
1257
- src: path_1.default.posix.join('/', entryDirectory, `/((?!index$).*)`),
1258
- headers: {
1259
- 'x-matched-path': '/$1',
1260
- },
1261
- continue: true,
1262
- important: true,
1263
- },
1264
- // error handling
1265
- { handle: 'error' },
1266
- // Custom Next.js 404 page
1267
- ...(i18n && (static404Page || hasIsr404Page || lambdaPages['404.js'])
1268
- ? [
1269
- {
1270
- src: `${path_1.default.posix.join('/', entryDirectory, '/')}(?<nextLocale>${i18n.locales
1271
- .map(locale => (0, escape_string_regexp_1.default)(locale))
1272
- .join('|')})(/.*|$)`,
1273
- dest: path_1.default.posix.join('/', entryDirectory, '/$nextLocale/404'),
1274
- status: 404,
1275
- caseSensitive: true,
1276
- },
1277
- {
1278
- src: path_1.default.posix.join('/', entryDirectory, '.*'),
1279
- dest: path_1.default.posix.join('/', entryDirectory, `/${i18n.defaultLocale}/404`),
1280
- status: 404,
1281
- },
1282
- ]
1283
- : [
1284
- {
1285
- src: path_1.default.posix.join('/', entryDirectory, '.*'),
1286
- dest: path_1.default.posix.join('/', entryDirectory, static404Page ||
1287
- hasIsr404Page ||
1288
- lambdas[path_1.default.posix.join(entryDirectory, '404')]
1289
- ? '/404'
1290
- : appPathRoutesManifest &&
1291
- (middleware.edgeFunctions[appNotFoundPath] ||
1292
- lambdas[appNotFoundPath])
1293
- ? '/_not-found'
1294
- : '/_error'),
1295
- status: 404,
1296
- },
1297
- ]),
1298
- // custom 500 page if present
1299
- ...(i18n && (hasStatic500 || hasIsr500Page || lambdaPages['500.js'])
1300
- ? [
1301
- {
1302
- src: `${path_1.default.posix.join('/', entryDirectory, '/')}(?<nextLocale>${i18n.locales
1303
- .map(locale => (0, escape_string_regexp_1.default)(locale))
1304
- .join('|')})(/.*|$)`,
1305
- dest: path_1.default.posix.join('/', entryDirectory, '/$nextLocale/500'),
1306
- status: 500,
1307
- caseSensitive: true,
1308
- },
1309
- {
1310
- src: path_1.default.posix.join('/', entryDirectory, '.*'),
1311
- dest: path_1.default.posix.join('/', entryDirectory, `/${i18n.defaultLocale}/500`),
1312
- status: 500,
1313
- },
1314
- ]
1315
- : [
1316
- {
1317
- src: path_1.default.posix.join('/', entryDirectory, '.*'),
1318
- dest: path_1.default.posix.join('/', entryDirectory, hasStatic500 ||
1319
- hasIsr500Page ||
1320
- lambdas[path_1.default.posix.join(entryDirectory, '500')]
1321
- ? '/500'
1322
- : '/_error'),
1323
- status: 500,
1324
- },
1325
- ]),
1326
- ],
1327
- framework: { version: nextVersion },
1328
- };
1329
- }
1330
- exports.serverBuild = serverBuild;