@vercel/next 2.7.9 → 2.8.66-canary.0

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.
@@ -0,0 +1,793 @@
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
+ async function serverBuild({ dynamicPages, pagesDir, config = {}, privateOutputs, baseDir, workPath, entryPath, nodeVersion, escapedBuildId, dynamicPrefix, entryDirectory, outputDirectory, redirects, beforeFilesRewrites, afterFilesRewrites, fallbackRewrites, headers, dataRoutes, hasIsr404Page, imagesManifest, wildcardConfig, routesManifest, staticPages, lambdaPages, nextVersion, canUsePreviewMode, prerenderManifest, omittedPrerenderRoutes, trailingSlashRedirects, isCorrectLocaleAPIRoutes, lambdaCompressedByteLimit, requiredServerFilesManifest, }) {
21
+ var _a, _b, _c, _d;
22
+ const lambdas = {};
23
+ const prerenders = {};
24
+ const lambdaPageKeys = Object.keys(lambdaPages);
25
+ const internalPages = ['_app.js', '_error.js', '_document.js'];
26
+ const pageBuildTraces = await (0, build_utils_1.glob)('**/*.js.nft.json', pagesDir);
27
+ const isCorrectNotFoundRoutes = semver_1.default.gte(nextVersion, CORRECT_NOT_FOUND_ROUTES_VERSION);
28
+ let hasStatic500 = !!staticPages[path_1.default.join(entryDirectory, '500')];
29
+ if (lambdaPageKeys.length === 0) {
30
+ throw new build_utils_1.NowBuildError({
31
+ code: 'NEXT_NO_SERVER_PAGES',
32
+ message: 'No server pages were built',
33
+ link: 'https://err.sh/vercel/vercel/now-next-no-serverless-pages-built',
34
+ });
35
+ }
36
+ const pageMatchesApi = (page) => {
37
+ return page.startsWith('api/') || page === 'api.js';
38
+ };
39
+ const { i18n } = routesManifest;
40
+ const hasPages404 = routesManifest.pages404;
41
+ let static404Page = staticPages[path_1.default.join(entryDirectory, '404')] && hasPages404
42
+ ? path_1.default.join(entryDirectory, '404')
43
+ : staticPages[path_1.default.join(entryDirectory, '_errors/404')]
44
+ ? path_1.default.join(entryDirectory, '_errors/404')
45
+ : undefined;
46
+ if (!static404Page && i18n) {
47
+ static404Page = staticPages[path_1.default.join(entryDirectory, i18n.defaultLocale, '404')]
48
+ ? path_1.default.join(entryDirectory, i18n.defaultLocale, '404')
49
+ : undefined;
50
+ }
51
+ if (!hasStatic500 && i18n) {
52
+ hasStatic500 =
53
+ !!staticPages[path_1.default.join(entryDirectory, i18n.defaultLocale, '500')];
54
+ }
55
+ const lstatSema = new async_sema_1.Sema(25);
56
+ const lstatResults = {};
57
+ const nonLambdaSsgPages = new Set();
58
+ Object.keys(prerenderManifest.staticRoutes).forEach(route => {
59
+ const result = (0, utils_1.onPrerenderRouteInitial)(prerenderManifest, canUsePreviewMode, entryDirectory, nonLambdaSsgPages, route, routesManifest.pages404, routesManifest);
60
+ if (result && result.static404Page) {
61
+ static404Page = result.static404Page;
62
+ }
63
+ if (result && result.static500Page) {
64
+ hasStatic500 = true;
65
+ }
66
+ });
67
+ const hasLambdas = !static404Page ||
68
+ lambdaPageKeys.some(page => !internalPages.includes(page) &&
69
+ !nonLambdaSsgPages.has('/' + page.replace(/\.js$/, '')));
70
+ if (lambdaPages['404.js']) {
71
+ internalPages.push('404.js');
72
+ }
73
+ const prerenderRoutes = new Set([
74
+ ...(canUsePreviewMode ? omittedPrerenderRoutes : []),
75
+ ...Object.keys(prerenderManifest.blockingFallbackRoutes),
76
+ ...Object.keys(prerenderManifest.fallbackRoutes),
77
+ ...Object.keys(prerenderManifest.staticRoutes).map(route => {
78
+ const staticRoute = prerenderManifest.staticRoutes[route];
79
+ return staticRoute.srcRoute || route;
80
+ }),
81
+ ]);
82
+ if (hasLambdas) {
83
+ const initialTracingLabel = 'Traced Next.js server files in';
84
+ console.time(initialTracingLabel);
85
+ const initialTracedFiles = {};
86
+ let initialFileList;
87
+ let initialFileReasons;
88
+ let nextServerBuildTrace;
89
+ const nextServerFile = (0, resolve_from_1.default)(requiredServerFilesManifest.appDir || entryPath, `${(0, utils_1.getNextServerPath)(nextVersion)}/next-server.js`);
90
+ try {
91
+ // leverage next-server trace from build if available
92
+ nextServerBuildTrace = JSON.parse(await fs_extra_1.default.readFile(path_1.default.join(entryPath, outputDirectory, 'next-server.js.nft.json'), 'utf8'));
93
+ }
94
+ catch (_) {
95
+ // if the trace is unavailable we trace inside the runtime
96
+ }
97
+ if (nextServerBuildTrace) {
98
+ initialFileList = nextServerBuildTrace.files.map((file) => {
99
+ return path_1.default.relative(baseDir, path_1.default.join(entryPath, outputDirectory, file));
100
+ });
101
+ initialFileReasons = new Map();
102
+ (0, build_utils_1.debug)('Using next-server.js.nft.json trace from build');
103
+ }
104
+ else {
105
+ (0, build_utils_1.debug)('tracing initial Next.js server files');
106
+ const result = await (0, nft_1.nodeFileTrace)([nextServerFile], {
107
+ base: baseDir,
108
+ cache: {},
109
+ processCwd: entryPath,
110
+ ignore: [
111
+ ...requiredServerFilesManifest.ignore.map(file => path_1.default.join(entryPath, file)),
112
+ 'node_modules/next/dist/pages/**/*',
113
+ `node_modules/${(0, utils_1.getNextServerPath)(nextVersion)}/lib/squoosh/**/*.wasm`,
114
+ 'node_modules/next/dist/compiled/webpack/(bundle4|bundle5).js',
115
+ 'node_modules/react/**/*.development.js',
116
+ 'node_modules/react-dom/**/*.development.js',
117
+ 'node_modules/use-subscription/**/*.development.js',
118
+ 'node_modules/sharp/**/*',
119
+ ],
120
+ });
121
+ initialFileList = Array.from(result.fileList);
122
+ initialFileReasons = result.reasons;
123
+ }
124
+ (0, build_utils_1.debug)('collecting initial Next.js server files');
125
+ await Promise.all(initialFileList.map((0, utils_1.collectTracedFiles)(baseDir, lstatResults, lstatSema, initialFileReasons, initialTracedFiles)));
126
+ (0, build_utils_1.debug)('creating initial pseudo layer');
127
+ const initialPseudoLayer = await (0, utils_1.createPseudoLayer)(initialTracedFiles);
128
+ console.timeEnd(initialTracingLabel);
129
+ const lambdaCreationLabel = 'Created all serverless functions in';
130
+ console.time(lambdaCreationLabel);
131
+ const apiPages = [];
132
+ const nonApiPages = [];
133
+ lambdaPageKeys.forEach(page => {
134
+ if (internalPages.includes(page) &&
135
+ page !== '404.js' &&
136
+ !(page === '_error.js' && !(static404Page || lambdaPages['404.js']))) {
137
+ return;
138
+ }
139
+ const pathname = page.replace(/\.js$/, '');
140
+ if (nonLambdaSsgPages.has(pathname)) {
141
+ return;
142
+ }
143
+ if ((0, utils_1.isDynamicRoute)(pathname)) {
144
+ dynamicPages.push((0, utils_1.normalizePage)(pathname));
145
+ }
146
+ if (pageMatchesApi(page)) {
147
+ apiPages.push(page);
148
+ }
149
+ else {
150
+ nonApiPages.push(page);
151
+ }
152
+ });
153
+ const requiredFiles = {};
154
+ requiredFiles[path_1.default.relative(baseDir, nextServerFile)] = new build_utils_1.FileFsRef({
155
+ mode: (await fs_extra_1.default.lstat(nextServerFile)).mode,
156
+ fsPath: nextServerFile,
157
+ });
158
+ if (static404Page) {
159
+ // ensure static 404 page file is included in all lambdas
160
+ // for notFound GS(S)P support
161
+ if (i18n) {
162
+ for (const locale of i18n.locales) {
163
+ const static404File = staticPages[path_1.default.join(entryDirectory, locale, '/404')] ||
164
+ new build_utils_1.FileFsRef({
165
+ fsPath: path_1.default.join(pagesDir, locale, '/404.html'),
166
+ });
167
+ requiredFiles[path_1.default.relative(baseDir, static404File.fsPath)] =
168
+ static404File;
169
+ }
170
+ }
171
+ else {
172
+ const static404File = staticPages[static404Page] ||
173
+ new build_utils_1.FileFsRef({
174
+ fsPath: path_1.default.join(pagesDir, '/404.html'),
175
+ });
176
+ requiredFiles[path_1.default.relative(baseDir, static404File.fsPath)] =
177
+ static404File;
178
+ }
179
+ }
180
+ // TODO: move this into Next.js' required server files manifest
181
+ const envFiles = [];
182
+ for (const file of await fs_extra_1.default.readdir(workPath)) {
183
+ const isEnv = file === '.env' || file.startsWith('.env.');
184
+ if (isEnv) {
185
+ const statResult = await fs_extra_1.default.lstat(path_1.default.join(workPath, file));
186
+ if (statResult.isFile()) {
187
+ envFiles.push(file);
188
+ }
189
+ }
190
+ }
191
+ for (const envFile of envFiles) {
192
+ requiredFiles[path_1.default.join(path_1.default.relative(baseDir, entryPath), envFile)] =
193
+ new build_utils_1.FileFsRef({
194
+ fsPath: path_1.default.join(workPath, envFile),
195
+ });
196
+ }
197
+ await Promise.all(requiredServerFilesManifest.files.map(async (file) => {
198
+ await lstatSema.acquire();
199
+ let fsPath = path_1.default.join(entryPath,
200
+ // remove last part of outputDirectory `.next` since this is already
201
+ // included in the file path
202
+ path_1.default.join(outputDirectory, '..'), file);
203
+ if (requiredServerFilesManifest.appDir) {
204
+ fsPath = path_1.default.join(requiredServerFilesManifest.appDir, file);
205
+ }
206
+ const relativePath = path_1.default.join(path_1.default.relative(baseDir, fsPath));
207
+ const { mode } = await fs_extra_1.default.lstat(fsPath);
208
+ lstatSema.release();
209
+ requiredFiles[relativePath] = new build_utils_1.FileFsRef({
210
+ mode,
211
+ fsPath,
212
+ });
213
+ }));
214
+ // add required files and internal pages to initial pseudo layer
215
+ // so that we account for these in the size of each page group
216
+ const requiredFilesLayer = await (0, utils_1.createPseudoLayer)(requiredFiles);
217
+ Object.assign(initialPseudoLayer.pseudoLayer, requiredFilesLayer.pseudoLayer);
218
+ initialPseudoLayer.pseudoLayerBytes += requiredFilesLayer.pseudoLayerBytes;
219
+ const uncompressedInitialSize = Object.keys(initialPseudoLayer.pseudoLayer).reduce((prev, cur) => {
220
+ return (prev +
221
+ initialPseudoLayer.pseudoLayer[cur]
222
+ .uncompressedSize || 0);
223
+ }, 0);
224
+ (0, build_utils_1.debug)(JSON.stringify({
225
+ uncompressedInitialSize,
226
+ compressedInitialSize: initialPseudoLayer.pseudoLayerBytes,
227
+ }, null, 2));
228
+ if (initialPseudoLayer.pseudoLayerBytes > lambdaCompressedByteLimit ||
229
+ uncompressedInitialSize > utils_1.MAX_UNCOMPRESSED_LAMBDA_SIZE) {
230
+ 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`);
231
+ (0, utils_1.outputFunctionFileSizeInfo)([], initialPseudoLayer.pseudoLayer, initialPseudoLayer.pseudoLayerBytes, uncompressedInitialSize, {});
232
+ throw new build_utils_1.NowBuildError({
233
+ message: `Required files read using Node.js fs library and node_modules exceed max lambda size of ${lambdaCompressedByteLimit} bytes`,
234
+ code: 'NEXT_REQUIRED_FILES_LIMIT',
235
+ link: 'https://vercel.com/docs/platform/limits#serverless-function-size',
236
+ });
237
+ }
238
+ const launcherData = await fs_extra_1.default.readFile(path_1.default.join(__dirname, 'server-launcher.js'), 'utf8');
239
+ let launcher = launcherData
240
+ .replace('conf: __NEXT_CONFIG__', `conf: ${JSON.stringify({
241
+ ...requiredServerFilesManifest.config,
242
+ distDir: path_1.default.relative(requiredServerFilesManifest.appDir || entryPath, path_1.default.join(entryPath, outputDirectory)),
243
+ compress: false,
244
+ })}`)
245
+ .replace('__NEXT_SERVER_PATH__', `${(0, utils_1.getNextServerPath)(nextVersion)}/next-server.js`);
246
+ if (entryDirectory !== '.' &&
247
+ path_1.default.join('/', entryDirectory) !== routesManifest.basePath) {
248
+ // we normalize the entryDirectory in the request URL since
249
+ // Next.js isn't aware of it and it isn't included in the
250
+ // x-matched-path header
251
+ launcher = launcher.replace('// entryDirectory handler', `req.url = req.url.replace(/^${path_1.default
252
+ .join('/', entryDirectory)
253
+ .replace(/\//g, '\\/')}/, '')`);
254
+ }
255
+ const launcherFiles = {
256
+ [path_1.default.join(path_1.default.relative(baseDir, requiredServerFilesManifest.appDir || entryPath), '___next_launcher.js')]: new build_utils_1.FileBlob({ data: launcher }),
257
+ };
258
+ const pageTraces = {};
259
+ const compressedPages = {};
260
+ const mergedPageKeys = [...nonApiPages, ...apiPages, ...internalPages];
261
+ const traceCache = {};
262
+ const pathsToTrace = mergedPageKeys
263
+ .map(page => {
264
+ if (!pageBuildTraces[page + '.nft.json']) {
265
+ return lambdaPages[page].fsPath;
266
+ }
267
+ })
268
+ .filter(Boolean);
269
+ let traceResult;
270
+ let parentFilesMap;
271
+ if (pathsToTrace.length > 0) {
272
+ traceResult = await (0, nft_1.nodeFileTrace)(pathsToTrace, {
273
+ base: baseDir,
274
+ cache: traceCache,
275
+ processCwd: requiredServerFilesManifest.appDir || entryPath,
276
+ });
277
+ traceResult.esmFileList.forEach(file => traceResult === null || traceResult === void 0 ? void 0 : traceResult.fileList.add(file));
278
+ parentFilesMap = (0, utils_1.getFilesMapFromReasons)(traceResult.fileList, traceResult.reasons);
279
+ }
280
+ for (const page of mergedPageKeys) {
281
+ const tracedFiles = {};
282
+ const pageBuildTrace = pageBuildTraces[page + '.nft.json'];
283
+ let fileList;
284
+ let reasons;
285
+ if (pageBuildTrace) {
286
+ const { files } = JSON.parse(await fs_extra_1.default.readFile(pageBuildTrace.fsPath, 'utf8'));
287
+ fileList = [];
288
+ const pageDir = path_1.default.dirname(path_1.default.join(pagesDir, page));
289
+ const normalizedBaseDir = `${baseDir}${baseDir.endsWith('/') ? '' : '/'}`;
290
+ files.forEach((file) => {
291
+ const absolutePath = path_1.default.join(pageDir, file);
292
+ // ensure we don't attempt including files outside
293
+ // of the base dir e.g. `/bin/sh`
294
+ if (absolutePath.startsWith(normalizedBaseDir)) {
295
+ fileList.push(path_1.default.relative(baseDir, absolutePath));
296
+ }
297
+ });
298
+ reasons = new Map();
299
+ }
300
+ else {
301
+ fileList = Array.from((parentFilesMap === null || parentFilesMap === void 0 ? void 0 : parentFilesMap.get(path_1.default.relative(baseDir, lambdaPages[page].fsPath))) || []);
302
+ if (!fileList) {
303
+ throw new Error(`Invariant: Failed to trace ${page}, missing fileList`);
304
+ }
305
+ reasons = (traceResult === null || traceResult === void 0 ? void 0 : traceResult.reasons) || new Map();
306
+ }
307
+ await Promise.all(fileList.map((0, utils_1.collectTracedFiles)(baseDir, lstatResults, lstatSema, reasons, tracedFiles)));
308
+ pageTraces[page] = tracedFiles;
309
+ compressedPages[page] = (await (0, utils_1.createPseudoLayer)({
310
+ [page]: lambdaPages[page],
311
+ })).pseudoLayer[page];
312
+ }
313
+ const tracedPseudoLayer = await (0, utils_1.createPseudoLayer)(mergedPageKeys.reduce((prev, page) => {
314
+ Object.assign(prev, pageTraces[page]);
315
+ return prev;
316
+ }, {}));
317
+ const initialPseudoLayerSize = Object.keys(initialPseudoLayer.pseudoLayer).reduce((prev, cur) => {
318
+ const file = initialPseudoLayer.pseudoLayer[cur];
319
+ return prev + file.uncompressedSize || 0;
320
+ }, 0);
321
+ const pageExtensions = (_a = requiredServerFilesManifest.config) === null || _a === void 0 ? void 0 : _a.pageExtensions;
322
+ const pageLambdaGroups = await (0, utils_1.getPageLambdaGroups)(requiredServerFilesManifest.appDir || entryPath, config, nonApiPages, prerenderRoutes, pageTraces, compressedPages, tracedPseudoLayer.pseudoLayer, initialPseudoLayer.pseudoLayerBytes, initialPseudoLayerSize, lambdaCompressedByteLimit, internalPages, pageExtensions);
323
+ const apiLambdaGroups = await (0, utils_1.getPageLambdaGroups)(requiredServerFilesManifest.appDir || entryPath, config, apiPages, prerenderRoutes, pageTraces, compressedPages, tracedPseudoLayer.pseudoLayer, initialPseudoLayer.pseudoLayerBytes, initialPseudoLayerSize, lambdaCompressedByteLimit, internalPages);
324
+ (0, build_utils_1.debug)(JSON.stringify({
325
+ apiLambdaGroups: apiLambdaGroups.map(group => ({
326
+ pages: group.pages,
327
+ isPrerender: group.isPrerenders,
328
+ pseudoLayerBytes: group.pseudoLayerBytes,
329
+ uncompressedLayerBytes: group.pseudoLayerUncompressedBytes,
330
+ })),
331
+ pageLambdaGroups: pageLambdaGroups.map(group => ({
332
+ pages: group.pages,
333
+ isPrerender: group.isPrerenders,
334
+ pseudoLayerBytes: group.pseudoLayerBytes,
335
+ uncompressedLayerBytes: group.pseudoLayerUncompressedBytes,
336
+ })),
337
+ nextServerLayerSize: initialPseudoLayer.pseudoLayerBytes,
338
+ }, null, 2));
339
+ const combinedGroups = [...pageLambdaGroups, ...apiLambdaGroups];
340
+ await (0, utils_1.detectLambdaLimitExceeding)(combinedGroups, lambdaCompressedByteLimit, compressedPages);
341
+ for (const group of combinedGroups) {
342
+ const lambda = await (0, utils_1.createLambdaFromPseudoLayers)({
343
+ files: launcherFiles,
344
+ layers: [
345
+ initialPseudoLayer.pseudoLayer,
346
+ group.pseudoLayer,
347
+ [...group.pages, ...internalPages].reduce((prev, page) => {
348
+ const pageFileName = path_1.default.normalize(path_1.default.relative(baseDir, lambdaPages[page].fsPath));
349
+ prev[pageFileName] = compressedPages[page];
350
+ return prev;
351
+ }, {}),
352
+ ],
353
+ handler: path_1.default.join(path_1.default.relative(baseDir, requiredServerFilesManifest.appDir || entryPath), '___next_launcher.js'),
354
+ memory: group.memory,
355
+ runtime: nodeVersion.runtime,
356
+ maxDuration: group.maxDuration,
357
+ });
358
+ for (const page of group.pages) {
359
+ const pageNoExt = page.replace(/\.js$/, '');
360
+ let isPrerender = prerenderRoutes.has(path_1.default.join('/', pageNoExt === 'index' ? '' : pageNoExt));
361
+ if (!isPrerender && (routesManifest === null || routesManifest === void 0 ? void 0 : routesManifest.i18n)) {
362
+ isPrerender = routesManifest.i18n.locales.some(locale => {
363
+ return prerenderRoutes.has(path_1.default.join('/', locale, pageNoExt === 'index' ? '' : pageNoExt));
364
+ });
365
+ }
366
+ const outputName = (0, utils_1.normalizeIndexOutput)(path_1.default.join(entryDirectory, pageNoExt), true);
367
+ // we add locale prefixed outputs for SSR pages,
368
+ // this is handled in onPrerenderRoute for SSG pages
369
+ if (i18n &&
370
+ !isPrerender &&
371
+ (!isCorrectLocaleAPIRoutes ||
372
+ !(pageNoExt === 'api' || pageNoExt.startsWith('api/')))) {
373
+ for (const locale of i18n.locales) {
374
+ lambdas[(0, utils_1.normalizeIndexOutput)(path_1.default.join(entryDirectory, locale, pageNoExt === 'index' ? '' : pageNoExt), true)] = lambda;
375
+ }
376
+ }
377
+ else {
378
+ lambdas[outputName] = lambda;
379
+ }
380
+ }
381
+ }
382
+ console.timeEnd(lambdaCreationLabel);
383
+ }
384
+ const prerenderRoute = (0, utils_1.onPrerenderRoute)({
385
+ pagesDir,
386
+ pageLambdaMap: {},
387
+ lambdas,
388
+ prerenders,
389
+ entryDirectory,
390
+ routesManifest,
391
+ prerenderManifest,
392
+ isServerMode: true,
393
+ isSharedLambdas: false,
394
+ canUsePreviewMode,
395
+ static404Page,
396
+ hasPages404: routesManifest.pages404,
397
+ isCorrectNotFoundRoutes,
398
+ });
399
+ Object.keys(prerenderManifest.staticRoutes).forEach(route => prerenderRoute(route, {}));
400
+ Object.keys(prerenderManifest.fallbackRoutes).forEach(route => prerenderRoute(route, { isFallback: true }));
401
+ Object.keys(prerenderManifest.blockingFallbackRoutes).forEach(route => prerenderRoute(route, { isBlocking: true }));
402
+ if (static404Page && canUsePreviewMode) {
403
+ omittedPrerenderRoutes.forEach(route => {
404
+ prerenderRoute(route, { isOmitted: true });
405
+ });
406
+ }
407
+ prerenderRoutes.forEach(route => {
408
+ if (routesManifest === null || routesManifest === void 0 ? void 0 : routesManifest.i18n) {
409
+ route = (0, utils_1.normalizeLocalePath)(route, routesManifest.i18n.locales).pathname;
410
+ }
411
+ delete lambdas[path_1.default.join('.', entryDirectory, route === '/' ? 'index' : route)];
412
+ });
413
+ const middleware = await (0, utils_1.getMiddlewareBundle)({
414
+ entryPath,
415
+ outputDirectory,
416
+ routesManifest,
417
+ });
418
+ 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));
419
+ const { staticFiles, publicDirectoryFiles, staticDirectoryFiles } = await (0, utils_1.getStaticFiles)(entryPath, entryDirectory, outputDirectory);
420
+ const notFoundPreviewRoutes = [];
421
+ if (((_b = prerenderManifest.notFoundRoutes) === null || _b === void 0 ? void 0 : _b.length) > 0 && canUsePreviewMode) {
422
+ // we combine routes into one src here to reduce the number of needed
423
+ // routes since only the status is being modified and we don't want
424
+ // to exceed the routes limit
425
+ const starterRouteSrc = `^${entryDirectory !== '.' ? path_1.default.join('/', entryDirectory, '()') : '()'}`;
426
+ let currentRouteSrc = starterRouteSrc;
427
+ const pushRoute = (src) => {
428
+ notFoundPreviewRoutes.push({
429
+ src,
430
+ missing: [
431
+ {
432
+ type: 'cookie',
433
+ key: '__prerender_bypass',
434
+ value: prerenderManifest.bypassToken || undefined,
435
+ },
436
+ {
437
+ type: 'cookie',
438
+ key: '__next_preview_data',
439
+ },
440
+ ],
441
+ status: 404,
442
+ });
443
+ };
444
+ for (let i = 0; i < prerenderManifest.notFoundRoutes.length; i++) {
445
+ const route = prerenderManifest.notFoundRoutes[i];
446
+ const isLastRoute = i === prerenderManifest.notFoundRoutes.length - 1;
447
+ if (((_c = prerenderManifest.staticRoutes[route]) === null || _c === void 0 ? void 0 : _c.initialRevalidate) === false) {
448
+ if (currentRouteSrc.length + route.length + 1 >= 4096) {
449
+ pushRoute(currentRouteSrc);
450
+ currentRouteSrc = starterRouteSrc;
451
+ }
452
+ // add to existing route src if src length limit isn't reached
453
+ currentRouteSrc = `${currentRouteSrc.substr(0, currentRouteSrc.length - 1)}${currentRouteSrc[currentRouteSrc.length - 2] === '(' ? '' : '|'}${route})`;
454
+ if (isLastRoute) {
455
+ pushRoute(currentRouteSrc);
456
+ }
457
+ }
458
+ }
459
+ }
460
+ return {
461
+ middleware: middleware.middleware,
462
+ wildcard: wildcardConfig,
463
+ images: ((_d = imagesManifest === null || imagesManifest === void 0 ? void 0 : imagesManifest.images) === null || _d === void 0 ? void 0 : _d.loader) === 'default'
464
+ ? {
465
+ domains: imagesManifest.images.domains,
466
+ sizes: imagesManifest.images.sizes,
467
+ remotePatterns: imagesManifest.images.remotePatterns,
468
+ minimumCacheTTL: imagesManifest.images.minimumCacheTTL,
469
+ formats: imagesManifest.images.formats,
470
+ dangerouslyAllowSVG: imagesManifest.images.dangerouslyAllowSVG,
471
+ contentSecurityPolicy: imagesManifest.images.contentSecurityPolicy,
472
+ }
473
+ : undefined,
474
+ output: {
475
+ ...publicDirectoryFiles,
476
+ ...lambdas,
477
+ // Prerenders may override Lambdas -- this is an intentional behavior.
478
+ ...prerenders,
479
+ ...staticPages,
480
+ ...staticFiles,
481
+ ...staticDirectoryFiles,
482
+ ...privateOutputs.files,
483
+ ...middleware.edgeFunctions,
484
+ },
485
+ routes: [
486
+ /*
487
+ Desired routes order
488
+ - Runtime headers
489
+ - User headers and redirects
490
+ - Runtime redirects
491
+ - Runtime routes
492
+ - Check filesystem, if nothing found continue
493
+ - User rewrites
494
+ - Builder rewrites
495
+ */
496
+ // force trailingSlashRedirect to the very top so it doesn't
497
+ // conflict with i18n routes that don't have or don't have the
498
+ // trailing slash
499
+ ...trailingSlashRedirects,
500
+ ...privateOutputs.routes,
501
+ ...(i18n
502
+ ? [
503
+ // Handle auto-adding current default locale to path based on
504
+ // $wildcard
505
+ {
506
+ src: `^${path_1.default.join('/', entryDirectory, '/')}(?!(?:_next/.*|${i18n.locales
507
+ .map(locale => (0, escape_string_regexp_1.default)(locale))
508
+ .join('|')})(?:/.*|$))(.*)$`,
509
+ // we aren't able to ensure trailing slash mode here
510
+ // so ensure this comes after the trailing slash redirect
511
+ dest: `${entryDirectory !== '.' ? path_1.default.join('/', entryDirectory) : ''}$wildcard/$1`,
512
+ continue: true,
513
+ },
514
+ // Handle redirecting to locale specific domains
515
+ ...(i18n.domains &&
516
+ i18n.domains.length > 0 &&
517
+ i18n.localeDetection !== false
518
+ ? [
519
+ {
520
+ src: `^${path_1.default.join('/', entryDirectory)}/?(?:${i18n.locales
521
+ .map(locale => (0, escape_string_regexp_1.default)(locale))
522
+ .join('|')})?/?$`,
523
+ locale: {
524
+ redirect: i18n.domains.reduce((prev, item) => {
525
+ prev[item.defaultLocale] = `http${item.http ? '' : 's'}://${item.domain}/`;
526
+ if (item.locales) {
527
+ item.locales.map(locale => {
528
+ prev[locale] = `http${item.http ? '' : 's'}://${item.domain}/${locale}`;
529
+ });
530
+ }
531
+ return prev;
532
+ }, {}),
533
+ cookie: 'NEXT_LOCALE',
534
+ },
535
+ continue: true,
536
+ },
537
+ ]
538
+ : []),
539
+ // Handle redirecting to locale paths
540
+ ...(i18n.localeDetection !== false
541
+ ? [
542
+ {
543
+ // TODO: if default locale is included in this src it won't
544
+ // be visitable by users who prefer another language since a
545
+ // cookie isn't set signaling the default locale is
546
+ // preferred on redirect currently, investigate adding this
547
+ src: '/',
548
+ locale: {
549
+ redirect: i18n.locales.reduce((prev, locale) => {
550
+ prev[locale] =
551
+ locale === i18n.defaultLocale ? `/` : `/${locale}`;
552
+ return prev;
553
+ }, {}),
554
+ cookie: 'NEXT_LOCALE',
555
+ },
556
+ continue: true,
557
+ },
558
+ ]
559
+ : []),
560
+ {
561
+ src: `^${path_1.default.join('/', entryDirectory)}$`,
562
+ dest: `${path_1.default.join('/', entryDirectory, i18n.defaultLocale)}`,
563
+ continue: true,
564
+ },
565
+ // Auto-prefix non-locale path with default locale
566
+ // note for prerendered pages this will cause
567
+ // x-now-route-matches to contain the path minus the locale
568
+ // e.g. for /de/posts/[slug] x-now-route-matches would have
569
+ // 1=posts%2Fpost-1
570
+ {
571
+ src: `^${path_1.default.join('/', entryDirectory, '/')}(?!(?:_next/.*|${i18n.locales
572
+ .map(locale => (0, escape_string_regexp_1.default)(locale))
573
+ .join('|')})(?:/.*|$))(.*)$`,
574
+ dest: `${path_1.default.join('/', entryDirectory, i18n.defaultLocale)}/$1`,
575
+ continue: true,
576
+ },
577
+ ]
578
+ : []),
579
+ // ensure prerender's for notFound: true static routes
580
+ // have 404 status code when not in preview mode
581
+ ...notFoundPreviewRoutes,
582
+ ...headers,
583
+ ...redirects,
584
+ ...beforeFilesRewrites,
585
+ // Make sure to 404 for the /404 path itself
586
+ ...(i18n
587
+ ? [
588
+ {
589
+ src: `${path_1.default.join('/', entryDirectory, '/')}(?:${i18n.locales
590
+ .map(locale => (0, escape_string_regexp_1.default)(locale))
591
+ .join('|')})?[/]?404/?`,
592
+ status: 404,
593
+ continue: true,
594
+ },
595
+ ]
596
+ : [
597
+ {
598
+ src: path_1.default.join('/', entryDirectory, '404/?'),
599
+ status: 404,
600
+ continue: true,
601
+ },
602
+ ]),
603
+ // Make sure to 500 when visiting /500 directly for static 500
604
+ ...(!hasStatic500
605
+ ? []
606
+ : i18n
607
+ ? [
608
+ {
609
+ src: `${path_1.default.join('/', entryDirectory, '/')}(?:${i18n.locales
610
+ .map(locale => (0, escape_string_regexp_1.default)(locale))
611
+ .join('|')})?[/]?500`,
612
+ status: 500,
613
+ continue: true,
614
+ },
615
+ ]
616
+ : [
617
+ {
618
+ src: path_1.default.join('/', entryDirectory, '500'),
619
+ status: 500,
620
+ continue: true,
621
+ },
622
+ ]),
623
+ ...middleware.staticRoutes,
624
+ // Next.js page lambdas, `static/` folder, reserved assets, and `public/`
625
+ // folder
626
+ { handle: 'filesystem' },
627
+ // ensure the basePath prefixed _next/image is rewritten to the root
628
+ // _next/image path
629
+ ...((routesManifest === null || routesManifest === void 0 ? void 0 : routesManifest.basePath)
630
+ ? [
631
+ {
632
+ src: path_1.default.join('/', entryDirectory, '_next/image/?'),
633
+ dest: '/_next/image',
634
+ check: true,
635
+ },
636
+ ]
637
+ : []),
638
+ // No-op _next/data rewrite to trigger handle: 'rewrites' and then 404
639
+ // if no match to prevent rewriting _next/data unexpectedly
640
+ {
641
+ src: path_1.default.join('/', entryDirectory, '_next/data/(.*)'),
642
+ dest: path_1.default.join('/', entryDirectory, '_next/data/$1'),
643
+ check: true,
644
+ },
645
+ // These need to come before handle: miss or else they are grouped
646
+ // with that routing section
647
+ ...afterFilesRewrites,
648
+ // make sure 404 page is used when a directory is matched without
649
+ // an index page
650
+ { handle: 'resource' },
651
+ ...fallbackRewrites,
652
+ { src: path_1.default.join('/', entryDirectory, '.*'), status: 404 },
653
+ // We need to make sure to 404 for /_next after handle: miss since
654
+ // handle: miss is called before rewrites and to prevent rewriting /_next
655
+ { handle: 'miss' },
656
+ {
657
+ src: path_1.default.join('/', entryDirectory, '_next/static/(?:[^/]+/pages|pages|chunks|runtime|css|image|media)/.+'),
658
+ status: 404,
659
+ check: true,
660
+ dest: '$0',
661
+ },
662
+ // remove locale prefixes to check public files
663
+ ...(i18n
664
+ ? [
665
+ {
666
+ src: `^${path_1.default.join('/', entryDirectory)}/?(?:${i18n.locales
667
+ .map(locale => (0, escape_string_regexp_1.default)(locale))
668
+ .join('|')})/(.*)`,
669
+ dest: `${path_1.default.join('/', entryDirectory, '/')}$1`,
670
+ check: true,
671
+ },
672
+ ]
673
+ : []),
674
+ // for non-shared lambdas remove locale prefix if present
675
+ // to allow checking for lambda
676
+ ...(!i18n
677
+ ? []
678
+ : [
679
+ {
680
+ src: `${path_1.default.join('/', entryDirectory, '/')}(?:${i18n === null || i18n === void 0 ? void 0 : i18n.locales.map(locale => (0, escape_string_regexp_1.default)(locale)).join('|')})/(.*)`,
681
+ dest: '/$1',
682
+ check: true,
683
+ },
684
+ ]),
685
+ // routes that are called after each rewrite or after routes
686
+ // if there no rewrites
687
+ { handle: 'rewrite' },
688
+ // /_next/data routes for getServerProps/getStaticProps pages
689
+ ...dataRoutes,
690
+ // ensure we 404 for non-existent _next/data routes before
691
+ // trying page dynamic routes
692
+ {
693
+ src: path_1.default.join('/', entryDirectory, '_next/data/(.*)'),
694
+ dest: path_1.default.join('/', entryDirectory, '404'),
695
+ status: 404,
696
+ },
697
+ // Dynamic routes (must come after dataRoutes as dataRoutes are more
698
+ // specific)
699
+ ...dynamicRoutes,
700
+ // routes to call after a file has been matched
701
+ { handle: 'hit' },
702
+ // Before we handle static files we need to set proper caching headers
703
+ {
704
+ // This ensures we only match known emitted-by-Next.js files and not
705
+ // user-emitted files which may be missing a hash in their filename.
706
+ src: path_1.default.join('/', entryDirectory, `_next/static/(?:[^/]+/pages|pages|chunks|runtime|css|image|media|${escapedBuildId})/.+`),
707
+ // Next.js assets contain a hash or entropy in their filenames, so they
708
+ // are guaranteed to be unique and cacheable indefinitely.
709
+ headers: {
710
+ 'cache-control': `public,max-age=${_1.MAX_AGE_ONE_YEAR},immutable`,
711
+ },
712
+ continue: true,
713
+ important: true,
714
+ },
715
+ // TODO: remove below workaround when `/` is allowed to be output
716
+ // different than `/index`
717
+ {
718
+ src: path_1.default.join('/', entryDirectory, '/index'),
719
+ headers: {
720
+ 'x-matched-path': '/',
721
+ },
722
+ continue: true,
723
+ important: true,
724
+ },
725
+ {
726
+ src: path_1.default.join('/', entryDirectory, `/((?!index$).*)`),
727
+ headers: {
728
+ 'x-matched-path': '/$1',
729
+ },
730
+ continue: true,
731
+ important: true,
732
+ },
733
+ // error handling
734
+ { handle: 'error' },
735
+ // Custom Next.js 404 page
736
+ ...(i18n && (static404Page || hasIsr404Page || lambdaPages['404.js'])
737
+ ? [
738
+ {
739
+ src: `${path_1.default.join('/', entryDirectory, '/')}(?<nextLocale>${i18n.locales
740
+ .map(locale => (0, escape_string_regexp_1.default)(locale))
741
+ .join('|')})(/.*|$)`,
742
+ dest: path_1.default.join('/', entryDirectory, '/$nextLocale/404'),
743
+ status: 404,
744
+ caseSensitive: true,
745
+ },
746
+ {
747
+ src: path_1.default.join('/', entryDirectory, '.*'),
748
+ dest: path_1.default.join('/', entryDirectory, `/${i18n.defaultLocale}/404`),
749
+ status: 404,
750
+ },
751
+ ]
752
+ : [
753
+ {
754
+ src: path_1.default.join('/', entryDirectory, '.*'),
755
+ dest: path_1.default.join('/', entryDirectory, static404Page ||
756
+ hasIsr404Page ||
757
+ lambdas[path_1.default.join(entryDirectory, '404')]
758
+ ? '/404'
759
+ : '/_error'),
760
+ status: 404,
761
+ },
762
+ ]),
763
+ // static 500 page if present
764
+ ...(!hasStatic500
765
+ ? []
766
+ : i18n
767
+ ? [
768
+ {
769
+ src: `${path_1.default.join('/', entryDirectory, '/')}(?<nextLocale>${i18n.locales
770
+ .map(locale => (0, escape_string_regexp_1.default)(locale))
771
+ .join('|')})(/.*|$)`,
772
+ dest: path_1.default.join('/', entryDirectory, '/$nextLocale/500'),
773
+ status: 500,
774
+ },
775
+ {
776
+ src: path_1.default.join('/', entryDirectory, '.*'),
777
+ dest: path_1.default.join('/', entryDirectory, `/${i18n.defaultLocale}/500`),
778
+ status: 500,
779
+ },
780
+ ]
781
+ : [
782
+ {
783
+ src: path_1.default.join('/', entryDirectory, '.*'),
784
+ dest: path_1.default.join('/', entryDirectory, '/500'),
785
+ status: 500,
786
+ },
787
+ ]),
788
+ ],
789
+ watch: [],
790
+ childProcesses: [],
791
+ };
792
+ }
793
+ exports.serverBuild = serverBuild;