@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.
- package/LICENSE +202 -190
- package/dist/___get-nextjs-edge-function.js +1 -0
- package/dist/create-serverless-config.js +6 -1
- package/dist/edge-function-source/constants.js +23 -0
- package/dist/edge-function-source/get-edge-function-source.js +72 -0
- package/dist/edge-function-source/get-edge-function.js +140 -0
- package/dist/edge-function-source/to-plain-headers.js +87 -0
- package/dist/index.js +6 -1
- package/dist/legacy-launcher.js +3 -8
- package/dist/server-build.js +793 -0
- package/dist/server-launcher.js +38 -0
- package/dist/sourcemapped.js +89 -0
- package/dist/templated-launcher-shared.js +7 -8
- package/dist/templated-launcher.js +1 -7
- package/dist/utils.js +962 -217
- package/package.json +39 -13
- package/dist/build-utils.js +0 -11
- package/dist/dev-server.js +0 -1
- package/dist/now__bridge.js +0 -179
package/dist/utils.js
CHANGED
@@ -1,19 +1,43 @@
|
|
1
1
|
"use strict";
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
+
if (k2 === undefined) k2 = k;
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
5
|
+
}) : (function(o, m, k, k2) {
|
6
|
+
if (k2 === undefined) k2 = k;
|
7
|
+
o[k2] = m[k];
|
8
|
+
}));
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
11
|
+
}) : function(o, v) {
|
12
|
+
o["default"] = v;
|
13
|
+
});
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
15
|
+
if (mod && mod.__esModule) return mod;
|
16
|
+
var result = {};
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
18
|
+
__setModuleDefault(result, mod);
|
19
|
+
return result;
|
20
|
+
};
|
2
21
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
22
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
23
|
};
|
5
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
-
exports.getSourceFilePathFromPage = exports.isDynamicRoute = exports.normalizePage = exports.
|
25
|
+
exports.getMiddlewareBundle = exports.getSourceFilePathFromPage = exports.isDynamicRoute = exports.normalizePage = 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 = void 0;
|
26
|
+
const build_utils_1 = require("@vercel/build-utils");
|
7
27
|
const async_sema_1 = require("async-sema");
|
8
28
|
const buffer_crc32_1 = __importDefault(require("buffer-crc32"));
|
9
|
-
const fs_extra_1 =
|
29
|
+
const fs_extra_1 = __importStar(require("fs-extra"));
|
10
30
|
const path_1 = __importDefault(require("path"));
|
11
31
|
const resolve_from_1 = __importDefault(require("resolve-from"));
|
12
32
|
const semver_1 = __importDefault(require("semver"));
|
13
|
-
const yazl_1 = require("yazl");
|
14
33
|
const zlib_1 = __importDefault(require("zlib"));
|
15
|
-
const
|
16
|
-
const
|
34
|
+
const url_1 = __importDefault(require("url"));
|
35
|
+
const escape_string_regexp_1 = __importDefault(require("escape-string-regexp"));
|
36
|
+
const _1 = require(".");
|
37
|
+
const text_table_1 = __importDefault(require("text-table"));
|
38
|
+
const pretty_bytes_1 = __importDefault(require("pretty-bytes"));
|
39
|
+
const get_edge_function_source_1 = require("./edge-function-source/get-edge-function-source");
|
40
|
+
const sourcemapped_1 = require("./sourcemapped");
|
17
41
|
// Identify /[param]/ in route string
|
18
42
|
// eslint-disable-next-line no-useless-escape
|
19
43
|
const TEST_DYNAMIC_ROUTE = /\/\[[^\/]+?\](?=\/|$)/;
|
@@ -28,7 +52,7 @@ exports.isDynamicRoute = isDynamicRoute;
|
|
28
52
|
function validateEntrypoint(entrypoint) {
|
29
53
|
if (!/package\.json$/.exec(entrypoint) &&
|
30
54
|
!/next\.config\.js$/.exec(entrypoint)) {
|
31
|
-
throw new NowBuildError({
|
55
|
+
throw new build_utils_1.NowBuildError({
|
32
56
|
message: 'Specified "src" for "@vercel/next" has to be "package.json" or "next.config.js"',
|
33
57
|
code: 'NEXT_INCORRECT_SRC',
|
34
58
|
});
|
@@ -50,20 +74,6 @@ function excludeFiles(files, matcher) {
|
|
50
74
|
}, {});
|
51
75
|
}
|
52
76
|
exports.excludeFiles = excludeFiles;
|
53
|
-
/**
|
54
|
-
* Exclude package manager lockfiles from files
|
55
|
-
*/
|
56
|
-
function excludeLockFiles(files) {
|
57
|
-
const newFiles = files;
|
58
|
-
if (newFiles['package-lock.json']) {
|
59
|
-
delete newFiles['package-lock.json'];
|
60
|
-
}
|
61
|
-
if (newFiles['yarn.lock']) {
|
62
|
-
delete newFiles['yarn.lock'];
|
63
|
-
}
|
64
|
-
return files;
|
65
|
-
}
|
66
|
-
exports.excludeLockFiles = excludeLockFiles;
|
67
77
|
/**
|
68
78
|
* Enforce specific package.json configuration for smallest possible lambda
|
69
79
|
*/
|
@@ -116,22 +126,6 @@ async function getNextConfig(workPath, entryPath) {
|
|
116
126
|
return null;
|
117
127
|
}
|
118
128
|
exports.getNextConfig = getNextConfig;
|
119
|
-
function pathIsInside(firstPath, secondPath) {
|
120
|
-
return !path_1.default.relative(firstPath, secondPath).startsWith('..');
|
121
|
-
}
|
122
|
-
function getPathsInside(entryDirectory, files) {
|
123
|
-
const watch = [];
|
124
|
-
for (const file of Object.keys(files)) {
|
125
|
-
// If the file is outside of the entrypoint directory, we do
|
126
|
-
// not want to monitor it for changes.
|
127
|
-
if (!pathIsInside(entryDirectory, file)) {
|
128
|
-
continue;
|
129
|
-
}
|
130
|
-
watch.push(file);
|
131
|
-
}
|
132
|
-
return watch;
|
133
|
-
}
|
134
|
-
exports.getPathsInside = getPathsInside;
|
135
129
|
function normalizePage(page) {
|
136
130
|
// Resolve on anything that doesn't start with `/`
|
137
131
|
if (!page.startsWith('/')) {
|
@@ -142,95 +136,6 @@ function normalizePage(page) {
|
|
142
136
|
return page;
|
143
137
|
}
|
144
138
|
exports.normalizePage = normalizePage;
|
145
|
-
async function getRoutes(entryPath, entryDirectory, pathsInside, files, url) {
|
146
|
-
let pagesDir = '';
|
147
|
-
const filesInside = {};
|
148
|
-
const prefix = entryDirectory === `.` ? `/` : `/${entryDirectory}/`;
|
149
|
-
const fileKeys = Object.keys(files);
|
150
|
-
for (const file of fileKeys) {
|
151
|
-
if (!pathsInside.includes(file)) {
|
152
|
-
continue;
|
153
|
-
}
|
154
|
-
if (!pagesDir) {
|
155
|
-
if (file.startsWith(path_1.default.join(entryDirectory, 'pages'))) {
|
156
|
-
pagesDir = 'pages';
|
157
|
-
}
|
158
|
-
}
|
159
|
-
filesInside[file] = files[file];
|
160
|
-
}
|
161
|
-
// If default pages dir isn't found check for `src/pages`
|
162
|
-
if (!pagesDir &&
|
163
|
-
fileKeys.some(file => file.startsWith(path_1.default.join(entryDirectory, 'src/pages')))) {
|
164
|
-
pagesDir = 'src/pages';
|
165
|
-
}
|
166
|
-
const routes = [
|
167
|
-
{
|
168
|
-
src: `${prefix}_next/(.*)`,
|
169
|
-
dest: `${url}/_next/$1`,
|
170
|
-
},
|
171
|
-
{
|
172
|
-
src: `${prefix}static/(.*)`,
|
173
|
-
dest: `${url}/static/$1`,
|
174
|
-
},
|
175
|
-
];
|
176
|
-
const filePaths = Object.keys(filesInside);
|
177
|
-
const dynamicPages = [];
|
178
|
-
for (const file of filePaths) {
|
179
|
-
const relativePath = path_1.default.relative(entryDirectory, file);
|
180
|
-
const isPage = pathIsInside(pagesDir, relativePath);
|
181
|
-
if (!isPage) {
|
182
|
-
continue;
|
183
|
-
}
|
184
|
-
const relativeToPages = path_1.default.relative(pagesDir, relativePath);
|
185
|
-
const extension = path_1.default.extname(relativeToPages);
|
186
|
-
const pageName = relativeToPages.replace(extension, '').replace(/\\/g, '/');
|
187
|
-
if (pageName.startsWith('_')) {
|
188
|
-
continue;
|
189
|
-
}
|
190
|
-
if (isDynamicRoute(pageName)) {
|
191
|
-
dynamicPages.push(normalizePage(pageName));
|
192
|
-
continue;
|
193
|
-
}
|
194
|
-
routes.push({
|
195
|
-
src: `${prefix}${pageName}`,
|
196
|
-
dest: `${url}/${pageName}`,
|
197
|
-
});
|
198
|
-
if (pageName.endsWith('index')) {
|
199
|
-
const resolvedIndex = pageName.replace('/index', '').replace('index', '');
|
200
|
-
routes.push({
|
201
|
-
src: `${prefix}${resolvedIndex}`,
|
202
|
-
dest: `${url}/${resolvedIndex}`,
|
203
|
-
});
|
204
|
-
}
|
205
|
-
}
|
206
|
-
routes.push(...(await getDynamicRoutes(entryPath, entryDirectory, dynamicPages, true).then(arr => arr.map((route) => {
|
207
|
-
// convert to make entire RegExp match as one group
|
208
|
-
route.src = route.src
|
209
|
-
.replace('^', `^${prefix}(`)
|
210
|
-
.replace('(\\/', '(')
|
211
|
-
.replace('$', ')$');
|
212
|
-
route.dest = `${url}/$1`;
|
213
|
-
return route;
|
214
|
-
}))));
|
215
|
-
// Add public folder routes
|
216
|
-
for (const file of filePaths) {
|
217
|
-
const relativePath = path_1.default.relative(entryDirectory, file);
|
218
|
-
const isPublic = pathIsInside('public', relativePath);
|
219
|
-
if (!isPublic)
|
220
|
-
continue;
|
221
|
-
const fileName = path_1.default.relative('public', relativePath);
|
222
|
-
const route = {
|
223
|
-
src: `${prefix}${fileName}`,
|
224
|
-
dest: `${url}/${fileName}`,
|
225
|
-
};
|
226
|
-
// Only add the route if a page is not already using it
|
227
|
-
if (!routes.some(r => r.src === route.src)) {
|
228
|
-
routes.push(route);
|
229
|
-
}
|
230
|
-
}
|
231
|
-
return routes;
|
232
|
-
}
|
233
|
-
exports.getRoutes = getRoutes;
|
234
139
|
async function getRoutesManifest(entryPath, outputDirectory, nextVersion) {
|
235
140
|
const shouldHaveManifest = nextVersion && semver_1.default.gte(nextVersion, '9.1.4-canary.0');
|
236
141
|
if (!shouldHaveManifest)
|
@@ -241,8 +146,8 @@ async function getRoutesManifest(entryPath, outputDirectory, nextVersion) {
|
|
241
146
|
.then(() => true)
|
242
147
|
.catch(() => false);
|
243
148
|
if (shouldHaveManifest && !hasRoutesManifest) {
|
244
|
-
throw new NowBuildError({
|
245
|
-
message: `
|
149
|
+
throw new build_utils_1.NowBuildError({
|
150
|
+
message: `The file "${pathRoutesManifest}" couldn't be found. This is normally caused by a misconfiguration in your project.\n` +
|
246
151
|
'Please check the following, and reach out to support if you cannot resolve the problem:\n' +
|
247
152
|
' 1. If present, be sure your `build` script in "package.json" calls `next build`.' +
|
248
153
|
' 2. Navigate to your project\'s settings in the Vercel dashboard, and verify that the "Build Command" is not overridden, or that it calls `next build`.' +
|
@@ -262,7 +167,7 @@ async function getRoutesManifest(entryPath, outputDirectory, nextVersion) {
|
|
262
167
|
}
|
263
168
|
}
|
264
169
|
for (const route of routesManifest.dynamicRoutes || []) {
|
265
|
-
if (Array.isArray(route.routeKeys)) {
|
170
|
+
if ('routeKeys' in route && Array.isArray(route.routeKeys)) {
|
266
171
|
delete route.routeKeys;
|
267
172
|
delete route.namedRegex;
|
268
173
|
}
|
@@ -270,42 +175,67 @@ async function getRoutesManifest(entryPath, outputDirectory, nextVersion) {
|
|
270
175
|
return routesManifest;
|
271
176
|
}
|
272
177
|
exports.getRoutesManifest = getRoutesManifest;
|
273
|
-
async function getDynamicRoutes(entryPath, entryDirectory, dynamicPages, isDev, routesManifest, omittedRoutes) {
|
274
|
-
if (!dynamicPages.length) {
|
275
|
-
return [];
|
276
|
-
}
|
178
|
+
async function getDynamicRoutes(entryPath, entryDirectory, dynamicPages, isDev, routesManifest, omittedRoutes, canUsePreviewMode, bypassToken, isServerMode, dynamicMiddlewareRouteMap) {
|
277
179
|
if (routesManifest) {
|
278
180
|
switch (routesManifest.version) {
|
279
181
|
case 1:
|
280
182
|
case 2: {
|
281
183
|
return routesManifest.dynamicRoutes
|
282
|
-
.filter(({ page }) => omittedRoutes ?
|
184
|
+
.filter(({ page }) => canUsePreviewMode || !(omittedRoutes === null || omittedRoutes === void 0 ? void 0 : omittedRoutes.has(page)))
|
283
185
|
.map(({ page, regex }) => {
|
284
186
|
return {
|
285
187
|
src: regex,
|
286
188
|
dest: !isDev ? path_1.default.join('/', entryDirectory, page) : page,
|
287
189
|
check: true,
|
190
|
+
status: canUsePreviewMode && (omittedRoutes === null || omittedRoutes === void 0 ? void 0 : omittedRoutes.has(page)) ? 404 : undefined,
|
288
191
|
};
|
289
192
|
});
|
290
193
|
}
|
291
|
-
case 3:
|
194
|
+
case 3:
|
195
|
+
case 4: {
|
292
196
|
return routesManifest.dynamicRoutes
|
293
|
-
.filter(({ page }) => omittedRoutes ?
|
294
|
-
.map(
|
295
|
-
|
197
|
+
.filter(({ page }) => canUsePreviewMode || !(omittedRoutes === null || omittedRoutes === void 0 ? void 0 : omittedRoutes.has(page)))
|
198
|
+
.map(params => {
|
199
|
+
if ('isMiddleware' in params) {
|
200
|
+
const route = dynamicMiddlewareRouteMap === null || dynamicMiddlewareRouteMap === void 0 ? void 0 : dynamicMiddlewareRouteMap.get(params.page);
|
201
|
+
if (!route) {
|
202
|
+
throw new Error(`Could not find dynamic middleware route for ${params.page}`);
|
203
|
+
}
|
204
|
+
return route;
|
205
|
+
}
|
206
|
+
const { page, namedRegex, regex, routeKeys } = params;
|
207
|
+
const route = {
|
296
208
|
src: namedRegex || regex,
|
297
209
|
dest: `${!isDev ? path_1.default.join('/', entryDirectory, page) : page}${routeKeys
|
298
210
|
? `?${Object.keys(routeKeys)
|
299
211
|
.map(key => `${routeKeys[key]}=$${key}`)
|
300
212
|
.join('&')}`
|
301
213
|
: ''}`,
|
302
|
-
check: true,
|
303
214
|
};
|
215
|
+
if (!isServerMode) {
|
216
|
+
route.check = true;
|
217
|
+
}
|
218
|
+
if (isServerMode && canUsePreviewMode && (omittedRoutes === null || omittedRoutes === void 0 ? void 0 : omittedRoutes.has(page))) {
|
219
|
+
// only match this route when in preview mode so
|
220
|
+
// preview works for non-prerender fallback: false pages
|
221
|
+
route.has = [
|
222
|
+
{
|
223
|
+
type: 'cookie',
|
224
|
+
key: '__prerender_bypass',
|
225
|
+
value: bypassToken || undefined,
|
226
|
+
},
|
227
|
+
{
|
228
|
+
type: 'cookie',
|
229
|
+
key: '__next_preview_data',
|
230
|
+
},
|
231
|
+
];
|
232
|
+
}
|
233
|
+
return route;
|
304
234
|
});
|
305
235
|
}
|
306
236
|
default: {
|
307
237
|
// update MIN_ROUTES_MANIFEST_VERSION
|
308
|
-
throw new NowBuildError({
|
238
|
+
throw new build_utils_1.NowBuildError({
|
309
239
|
message: 'This version of `@vercel/next` does not support the version of Next.js you are trying to deploy.\n' +
|
310
240
|
'Please upgrade your `@vercel/next` builder and try again. Contact support if this continues to happen.',
|
311
241
|
code: 'NEXT_VERSION_UPGRADE',
|
@@ -316,10 +246,13 @@ async function getDynamicRoutes(entryPath, entryDirectory, dynamicPages, isDev,
|
|
316
246
|
// FALLBACK:
|
317
247
|
// When `routes-manifest.json` does not exist (old Next.js versions), we'll try to
|
318
248
|
// require the methods we need from Next.js' internals.
|
249
|
+
if (!dynamicPages.length) {
|
250
|
+
return [];
|
251
|
+
}
|
319
252
|
let getRouteRegex = undefined;
|
320
253
|
let getSortedRoutes;
|
321
254
|
try {
|
322
|
-
({ getRouteRegex, getSortedRoutes } = require(resolve_from_1.default(entryPath, 'next-server/dist/lib/router/utils')));
|
255
|
+
({ getRouteRegex, getSortedRoutes } = require((0, resolve_from_1.default)(entryPath, 'next-server/dist/lib/router/utils')));
|
323
256
|
if (typeof getRouteRegex !== 'function') {
|
324
257
|
getRouteRegex = undefined;
|
325
258
|
}
|
@@ -327,7 +260,7 @@ async function getDynamicRoutes(entryPath, entryDirectory, dynamicPages, isDev,
|
|
327
260
|
catch (_) { } // eslint-disable-line no-empty
|
328
261
|
if (!getRouteRegex || !getSortedRoutes) {
|
329
262
|
try {
|
330
|
-
({ getRouteRegex, getSortedRoutes } = require(resolve_from_1.default(entryPath, 'next/dist/next-server/lib/router/utils')));
|
263
|
+
({ getRouteRegex, getSortedRoutes } = require((0, resolve_from_1.default)(entryPath, 'next/dist/next-server/lib/router/utils')));
|
331
264
|
if (typeof getRouteRegex !== 'function') {
|
332
265
|
getRouteRegex = undefined;
|
333
266
|
}
|
@@ -335,7 +268,7 @@ async function getDynamicRoutes(entryPath, entryDirectory, dynamicPages, isDev,
|
|
335
268
|
catch (_) { } // eslint-disable-line no-empty
|
336
269
|
}
|
337
270
|
if (!getRouteRegex || !getSortedRoutes) {
|
338
|
-
throw new NowBuildError({
|
271
|
+
throw new build_utils_1.NowBuildError({
|
339
272
|
message: 'Found usage of dynamic routes but not on a new enough version of Next.js.',
|
340
273
|
code: 'NEXT_DYNAMIC_ROUTES_OUTDATED',
|
341
274
|
});
|
@@ -361,6 +294,34 @@ async function getDynamicRoutes(entryPath, entryDirectory, dynamicPages, isDev,
|
|
361
294
|
return routes;
|
362
295
|
}
|
363
296
|
exports.getDynamicRoutes = getDynamicRoutes;
|
297
|
+
function localizeDynamicRoutes(dynamicRoutes, dynamicPrefix, entryDirectory, staticPages, prerenderManifest, routesManifest, isServerMode, isCorrectLocaleAPIRoutes) {
|
298
|
+
return dynamicRoutes.map((route) => {
|
299
|
+
// i18n is already handled for middleware
|
300
|
+
if (route.middleware !== undefined || route.middlewarePath !== undefined)
|
301
|
+
return route;
|
302
|
+
const { i18n } = routesManifest || {};
|
303
|
+
if (i18n) {
|
304
|
+
const { pathname } = url_1.default.parse(route.dest);
|
305
|
+
const pathnameNoPrefix = pathname === null || pathname === void 0 ? void 0 : pathname.replace(dynamicPrefix, '');
|
306
|
+
const isFallback = prerenderManifest.fallbackRoutes[pathname];
|
307
|
+
const isBlocking = prerenderManifest.blockingFallbackRoutes[pathname];
|
308
|
+
const isApiRoute = pathnameNoPrefix === '/api' || (pathnameNoPrefix === null || pathnameNoPrefix === void 0 ? void 0 : pathnameNoPrefix.startsWith('/api/'));
|
309
|
+
const isAutoExport = staticPages[addLocaleOrDefault(pathname, routesManifest).substr(1)];
|
310
|
+
const isLocalePrefixed = isFallback || isBlocking || isAutoExport || isServerMode;
|
311
|
+
route.src = route.src.replace('^', `^${dynamicPrefix ? `${dynamicPrefix}[/]?` : '[/]?'}(?${isLocalePrefixed ? '<nextLocale>' : ':'}${i18n.locales.map(locale => (0, escape_string_regexp_1.default)(locale)).join('|')})?`);
|
312
|
+
if (isLocalePrefixed && !(isCorrectLocaleAPIRoutes && isApiRoute)) {
|
313
|
+
// ensure destination has locale prefix to match prerender output
|
314
|
+
// path so that the prerender object is used
|
315
|
+
route.dest = route.dest.replace(`${path_1.default.join('/', entryDirectory, '/')}`, `${path_1.default.join('/', entryDirectory, '$nextLocale', '/')}`);
|
316
|
+
}
|
317
|
+
}
|
318
|
+
else {
|
319
|
+
route.src = route.src.replace('^', `^${dynamicPrefix}`);
|
320
|
+
}
|
321
|
+
return route;
|
322
|
+
});
|
323
|
+
}
|
324
|
+
exports.localizeDynamicRoutes = localizeDynamicRoutes;
|
364
325
|
async function getImagesManifest(entryPath, outputDirectory) {
|
365
326
|
const pathImagesManifest = path_1.default.join(entryPath, outputDirectory, 'images-manifest.json');
|
366
327
|
const hasImagesManifest = await fs_extra_1.default
|
@@ -375,19 +336,90 @@ async function getImagesManifest(entryPath, outputDirectory) {
|
|
375
336
|
return imagesManifest;
|
376
337
|
}
|
377
338
|
exports.getImagesManifest = getImagesManifest;
|
378
|
-
function
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
339
|
+
function filterStaticPages(staticPageFiles, dynamicPages, entryDirectory, htmlContentType, prerenderManifest, routesManifest) {
|
340
|
+
const staticPages = {};
|
341
|
+
Object.keys(staticPageFiles).forEach((page) => {
|
342
|
+
var _a;
|
343
|
+
const pathname = page.replace(/\.html$/, '');
|
344
|
+
const routeName = normalizeLocalePath(normalizePage(pathname), (_a = routesManifest === null || routesManifest === void 0 ? void 0 : routesManifest.i18n) === null || _a === void 0 ? void 0 : _a.locales).pathname;
|
345
|
+
// Prerendered routes emit a `.html` file but should not be treated as a
|
346
|
+
// static page.
|
347
|
+
// Lazily prerendered routes have a fallback `.html` file on newer
|
348
|
+
// Next.js versions so we need to also not treat it as a static page here.
|
349
|
+
if (prerenderManifest.staticRoutes[routeName] ||
|
350
|
+
prerenderManifest.fallbackRoutes[routeName] ||
|
351
|
+
prerenderManifest.staticRoutes[normalizePage(pathname)] ||
|
352
|
+
prerenderManifest.fallbackRoutes[normalizePage(pathname)]) {
|
353
|
+
return;
|
354
|
+
}
|
355
|
+
const staticRoute = path_1.default.join(entryDirectory, pathname);
|
356
|
+
staticPages[staticRoute] = staticPageFiles[page];
|
357
|
+
staticPages[staticRoute].contentType = htmlContentType;
|
358
|
+
if (isDynamicRoute(pathname)) {
|
359
|
+
dynamicPages.push(routeName);
|
360
|
+
return;
|
361
|
+
}
|
362
|
+
});
|
363
|
+
return staticPages;
|
364
|
+
}
|
365
|
+
exports.filterStaticPages = filterStaticPages;
|
366
|
+
function getFilesMapFromReasons(fileList, reasons, ignoreFn) {
|
367
|
+
// this uses the reasons tree to collect files specific to a
|
368
|
+
// certain parent allowing us to not have to trace each parent
|
369
|
+
// separately
|
370
|
+
const parentFilesMap = new Map();
|
371
|
+
function propagateToParents(parents, file, seen = new Set()) {
|
372
|
+
for (const parent of parents || []) {
|
373
|
+
if (!seen.has(parent)) {
|
374
|
+
seen.add(parent);
|
375
|
+
let parentFiles = parentFilesMap.get(parent);
|
376
|
+
if (!parentFiles) {
|
377
|
+
parentFiles = new Set();
|
378
|
+
parentFilesMap.set(parent, parentFiles);
|
379
|
+
}
|
380
|
+
if (!(ignoreFn === null || ignoreFn === void 0 ? void 0 : ignoreFn(file, parent))) {
|
381
|
+
parentFiles.add(file);
|
382
|
+
}
|
383
|
+
const parentReason = reasons.get(parent);
|
384
|
+
if (parentReason === null || parentReason === void 0 ? void 0 : parentReason.parents) {
|
385
|
+
propagateToParents(parentReason.parents, file, seen);
|
386
|
+
}
|
387
|
+
}
|
385
388
|
}
|
386
389
|
}
|
387
|
-
|
388
|
-
|
390
|
+
for (const file of fileList) {
|
391
|
+
const reason = reasons.get(file);
|
392
|
+
const isInitial = (reason === null || reason === void 0 ? void 0 : reason.type.length) === 1 && reason.type.includes('initial');
|
393
|
+
if (!reason ||
|
394
|
+
!reason.parents ||
|
395
|
+
(isInitial && reason.parents.size === 0)) {
|
396
|
+
continue;
|
397
|
+
}
|
398
|
+
propagateToParents(reason.parents, file);
|
399
|
+
}
|
400
|
+
return parentFilesMap;
|
389
401
|
}
|
390
|
-
exports.
|
402
|
+
exports.getFilesMapFromReasons = getFilesMapFromReasons;
|
403
|
+
const collectTracedFiles = (baseDir, lstatResults, lstatSema, reasons, files) => async (file) => {
|
404
|
+
const reason = reasons.get(file);
|
405
|
+
if (reason && reason.type.includes('initial')) {
|
406
|
+
// Initial files are manually added to the lambda later
|
407
|
+
return;
|
408
|
+
}
|
409
|
+
const filePath = path_1.default.join(baseDir, file);
|
410
|
+
if (!lstatResults[filePath]) {
|
411
|
+
lstatResults[filePath] = lstatSema
|
412
|
+
.acquire()
|
413
|
+
.then(() => (0, fs_extra_1.lstat)(filePath))
|
414
|
+
.finally(() => lstatSema.release());
|
415
|
+
}
|
416
|
+
const { mode } = await lstatResults[filePath];
|
417
|
+
files[file] = new build_utils_1.FileFsRef({
|
418
|
+
fsPath: path_1.default.join(baseDir, file),
|
419
|
+
mode,
|
420
|
+
});
|
421
|
+
};
|
422
|
+
exports.collectTracedFiles = collectTracedFiles;
|
391
423
|
exports.ExperimentalTraceVersion = `9.0.4-canary.1`;
|
392
424
|
const compressBuffer = (buf) => {
|
393
425
|
return new Promise((resolve, reject) => {
|
@@ -403,7 +435,7 @@ async function createPseudoLayer(files) {
|
|
403
435
|
let pseudoLayerBytes = 0;
|
404
436
|
for (const fileName of Object.keys(files)) {
|
405
437
|
const file = files[fileName];
|
406
|
-
if (isSymbolicLink(file.mode)) {
|
438
|
+
if ((0, build_utils_1.isSymbolicLink)(file.mode)) {
|
407
439
|
const symlinkTarget = await fs_extra_1.default.readlink(file.fsPath);
|
408
440
|
pseudoLayer[fileName] = {
|
409
441
|
file,
|
@@ -412,15 +444,15 @@ async function createPseudoLayer(files) {
|
|
412
444
|
};
|
413
445
|
}
|
414
446
|
else {
|
415
|
-
const origBuffer = await streamToBuffer(file.toStream());
|
447
|
+
const origBuffer = await (0, build_utils_1.streamToBuffer)(file.toStream());
|
416
448
|
const compBuffer = await compressBuffer(origBuffer);
|
417
449
|
pseudoLayerBytes += compBuffer.byteLength;
|
418
450
|
pseudoLayer[fileName] = {
|
451
|
+
file,
|
419
452
|
compBuffer,
|
420
453
|
isSymlink: false,
|
421
454
|
crc32: buffer_crc32_1.default.unsigned(origBuffer),
|
422
455
|
uncompressedSize: origBuffer.byteLength,
|
423
|
-
mode: file.mode,
|
424
456
|
};
|
425
457
|
}
|
426
458
|
}
|
@@ -430,66 +462,38 @@ exports.createPseudoLayer = createPseudoLayer;
|
|
430
462
|
// measured with 1, 2, 5, 10, and `os.cpus().length || 5`
|
431
463
|
// and sema(1) produced the best results
|
432
464
|
const createLambdaSema = new async_sema_1.Sema(1);
|
433
|
-
async function createLambdaFromPseudoLayers({ files, layers,
|
465
|
+
async function createLambdaFromPseudoLayers({ files: baseFiles, layers, ...lambdaOptions }) {
|
434
466
|
await createLambdaSema.acquire();
|
435
|
-
const
|
467
|
+
const files = {};
|
436
468
|
const addedFiles = new Set();
|
437
|
-
|
438
|
-
const symlinkTargets = new Map();
|
439
|
-
for (const name of names) {
|
440
|
-
const file = files[name];
|
441
|
-
if (file.mode && isSymbolicLink(file.mode) && file.type === 'FileFsRef') {
|
442
|
-
const symlinkTarget = await fs_extra_1.default.readlink(file.fsPath);
|
443
|
-
symlinkTargets.set(name, symlinkTarget);
|
444
|
-
}
|
445
|
-
}
|
446
|
-
// apply pseudo layers (already compressed objects)
|
469
|
+
// Add files from pseudo layers
|
447
470
|
for (const layer of layers) {
|
448
471
|
for (const seedKey of Object.keys(layer)) {
|
449
|
-
|
450
|
-
|
451
|
-
const { symlinkTarget, file } = item;
|
452
|
-
zipFile.addBuffer(Buffer.from(symlinkTarget, 'utf8'), seedKey, {
|
453
|
-
mode: file.mode,
|
454
|
-
});
|
472
|
+
if (addedFiles.has(seedKey)) {
|
473
|
+
// File was already added in a previous pseudo layer
|
455
474
|
continue;
|
456
475
|
}
|
457
|
-
const
|
458
|
-
|
459
|
-
zipFile.addDeflatedBuffer(compBuffer, seedKey, {
|
460
|
-
crc32,
|
461
|
-
uncompressedSize,
|
462
|
-
mode: mode,
|
463
|
-
});
|
476
|
+
const item = layer[seedKey];
|
477
|
+
files[seedKey] = item.file;
|
464
478
|
addedFiles.add(seedKey);
|
465
479
|
}
|
466
480
|
}
|
467
|
-
for (const fileName of Object.keys(
|
468
|
-
|
469
|
-
|
481
|
+
for (const fileName of Object.keys(baseFiles)) {
|
482
|
+
if (addedFiles.has(fileName)) {
|
483
|
+
// File was already added in a previous pseudo layer
|
470
484
|
continue;
|
471
|
-
const file = files[fileName];
|
472
|
-
const symlinkTarget = symlinkTargets.get(fileName);
|
473
|
-
if (typeof symlinkTarget === 'string') {
|
474
|
-
zipFile.addBuffer(Buffer.from(symlinkTarget, 'utf8'), fileName, {
|
475
|
-
mode: file.mode,
|
476
|
-
});
|
477
|
-
}
|
478
|
-
else {
|
479
|
-
const fileBuffer = await streamToBuffer(file.toStream());
|
480
|
-
zipFile.addBuffer(fileBuffer, fileName);
|
481
485
|
}
|
486
|
+
const file = baseFiles[fileName];
|
487
|
+
files[fileName] = file;
|
488
|
+
addedFiles.add(fileName);
|
482
489
|
}
|
483
|
-
zipFile.end();
|
484
|
-
const zipBuffer = await streamToBuffer(zipFile.outputStream);
|
485
490
|
createLambdaSema.release();
|
486
|
-
return new
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
environment,
|
491
|
+
return new build_utils_1.NodejsLambda({
|
492
|
+
...lambdaOptions,
|
493
|
+
files,
|
494
|
+
shouldAddHelpers: false,
|
495
|
+
shouldAddSourcemapSupport: false,
|
496
|
+
supportsMultiPayloads: !!process.env.NEXT_PRIVATE_MULTI_PAYLOAD,
|
493
497
|
});
|
494
498
|
}
|
495
499
|
exports.createLambdaFromPseudoLayers = createLambdaFromPseudoLayers;
|
@@ -539,6 +543,37 @@ async function getExportStatus(entryPath) {
|
|
539
543
|
}
|
540
544
|
}
|
541
545
|
exports.getExportStatus = getExportStatus;
|
546
|
+
async function getRequiredServerFilesManifest(entryPath, outputDirectory) {
|
547
|
+
const pathRequiredServerFilesManifest = path_1.default.join(entryPath, outputDirectory, 'required-server-files.json');
|
548
|
+
const hasManifest = await fs_extra_1.default
|
549
|
+
.access(pathRequiredServerFilesManifest, fs_extra_1.default.constants.F_OK)
|
550
|
+
.then(() => true)
|
551
|
+
.catch(() => false);
|
552
|
+
if (!hasManifest) {
|
553
|
+
return false;
|
554
|
+
}
|
555
|
+
const manifestData = JSON.parse(await fs_extra_1.default.readFile(pathRequiredServerFilesManifest, 'utf8'));
|
556
|
+
const requiredServerFiles = {
|
557
|
+
files: [],
|
558
|
+
ignore: [],
|
559
|
+
config: {},
|
560
|
+
appDir: manifestData.appDir,
|
561
|
+
};
|
562
|
+
switch (manifestData.version) {
|
563
|
+
case 1: {
|
564
|
+
requiredServerFiles.files = manifestData.files;
|
565
|
+
requiredServerFiles.ignore = manifestData.ignore;
|
566
|
+
requiredServerFiles.config = manifestData.config;
|
567
|
+
requiredServerFiles.appDir = manifestData.appDir;
|
568
|
+
break;
|
569
|
+
}
|
570
|
+
default: {
|
571
|
+
throw new Error(`Invalid required-server-files manifest version ${manifestData.version}, please contact support if this error persists`);
|
572
|
+
}
|
573
|
+
}
|
574
|
+
return requiredServerFiles;
|
575
|
+
}
|
576
|
+
exports.getRequiredServerFilesManifest = getRequiredServerFilesManifest;
|
542
577
|
async function getPrerenderManifest(entryPath, outputDirectory) {
|
543
578
|
const pathPrerenderManifest = path_1.default.join(entryPath, outputDirectory, 'prerender-manifest.json');
|
544
579
|
const hasManifest = await fs_extra_1.default
|
@@ -551,8 +586,9 @@ async function getPrerenderManifest(entryPath, outputDirectory) {
|
|
551
586
|
blockingFallbackRoutes: {},
|
552
587
|
fallbackRoutes: {},
|
553
588
|
bypassToken: null,
|
554
|
-
omittedRoutes:
|
589
|
+
omittedRoutes: {},
|
555
590
|
notFoundRoutes: [],
|
591
|
+
isLocalePrefixed: false,
|
556
592
|
};
|
557
593
|
}
|
558
594
|
const manifest = JSON.parse(await fs_extra_1.default.readFile(pathPrerenderManifest, 'utf8'));
|
@@ -565,11 +601,12 @@ async function getPrerenderManifest(entryPath, outputDirectory) {
|
|
565
601
|
blockingFallbackRoutes: {},
|
566
602
|
fallbackRoutes: {},
|
567
603
|
bypassToken: (manifest.preview && manifest.preview.previewModeId) || null,
|
568
|
-
omittedRoutes:
|
604
|
+
omittedRoutes: {},
|
569
605
|
notFoundRoutes: [],
|
606
|
+
isLocalePrefixed: false,
|
570
607
|
};
|
571
608
|
routes.forEach(route => {
|
572
|
-
const { initialRevalidateSeconds, dataRoute, srcRoute
|
609
|
+
const { initialRevalidateSeconds, dataRoute, srcRoute } = manifest.routes[route];
|
573
610
|
ret.staticRoutes[route] = {
|
574
611
|
initialRevalidate: initialRevalidateSeconds === false
|
575
612
|
? false
|
@@ -579,7 +616,7 @@ async function getPrerenderManifest(entryPath, outputDirectory) {
|
|
579
616
|
};
|
580
617
|
});
|
581
618
|
lazyRoutes.forEach(lazyRoute => {
|
582
|
-
const { routeRegex, fallback, dataRoute, dataRouteRegex
|
619
|
+
const { routeRegex, fallback, dataRoute, dataRouteRegex } = manifest.dynamicRoutes[lazyRoute];
|
583
620
|
if (fallback) {
|
584
621
|
ret.fallbackRoutes[lazyRoute] = {
|
585
622
|
routeRegex,
|
@@ -598,7 +635,8 @@ async function getPrerenderManifest(entryPath, outputDirectory) {
|
|
598
635
|
});
|
599
636
|
return ret;
|
600
637
|
}
|
601
|
-
case 2:
|
638
|
+
case 2:
|
639
|
+
case 3: {
|
602
640
|
const routes = Object.keys(manifest.routes);
|
603
641
|
const lazyRoutes = Object.keys(manifest.dynamicRoutes);
|
604
642
|
const ret = {
|
@@ -606,14 +644,15 @@ async function getPrerenderManifest(entryPath, outputDirectory) {
|
|
606
644
|
blockingFallbackRoutes: {},
|
607
645
|
fallbackRoutes: {},
|
608
646
|
bypassToken: manifest.preview.previewModeId,
|
609
|
-
omittedRoutes:
|
647
|
+
omittedRoutes: {},
|
610
648
|
notFoundRoutes: [],
|
649
|
+
isLocalePrefixed: manifest.version > 2,
|
611
650
|
};
|
612
651
|
if (manifest.notFoundRoutes) {
|
613
652
|
ret.notFoundRoutes.push(...manifest.notFoundRoutes);
|
614
653
|
}
|
615
654
|
routes.forEach(route => {
|
616
|
-
const { initialRevalidateSeconds, dataRoute, srcRoute
|
655
|
+
const { initialRevalidateSeconds, dataRoute, srcRoute } = manifest.routes[route];
|
617
656
|
ret.staticRoutes[route] = {
|
618
657
|
initialRevalidate: initialRevalidateSeconds === false
|
619
658
|
? false
|
@@ -623,7 +662,7 @@ async function getPrerenderManifest(entryPath, outputDirectory) {
|
|
623
662
|
};
|
624
663
|
});
|
625
664
|
lazyRoutes.forEach(lazyRoute => {
|
626
|
-
const { routeRegex, fallback, dataRoute, dataRouteRegex
|
665
|
+
const { routeRegex, fallback, dataRoute, dataRouteRegex } = manifest.dynamicRoutes[lazyRoute];
|
627
666
|
if (typeof fallback === 'string') {
|
628
667
|
ret.fallbackRoutes[lazyRoute] = {
|
629
668
|
routeRegex,
|
@@ -642,7 +681,11 @@ async function getPrerenderManifest(entryPath, outputDirectory) {
|
|
642
681
|
else {
|
643
682
|
// Fallback behavior is disabled, all routes would've been provided
|
644
683
|
// in the top-level `routes` key (`staticRoutes`).
|
645
|
-
ret.omittedRoutes
|
684
|
+
ret.omittedRoutes[lazyRoute] = {
|
685
|
+
routeRegex,
|
686
|
+
dataRoute,
|
687
|
+
dataRouteRegex,
|
688
|
+
};
|
646
689
|
}
|
647
690
|
});
|
648
691
|
return ret;
|
@@ -653,8 +696,9 @@ async function getPrerenderManifest(entryPath, outputDirectory) {
|
|
653
696
|
blockingFallbackRoutes: {},
|
654
697
|
fallbackRoutes: {},
|
655
698
|
bypassToken: null,
|
656
|
-
omittedRoutes:
|
699
|
+
omittedRoutes: {},
|
657
700
|
notFoundRoutes: [],
|
701
|
+
isLocalePrefixed: false,
|
658
702
|
};
|
659
703
|
}
|
660
704
|
}
|
@@ -676,10 +720,10 @@ async function usesSrcDirectory(workPath) {
|
|
676
720
|
}
|
677
721
|
return Boolean(_usesSrcCache);
|
678
722
|
}
|
679
|
-
async function getSourceFilePathFromPage({ workPath, page, }) {
|
723
|
+
async function getSourceFilePathFromPage({ workPath, page, pageExtensions, }) {
|
680
724
|
// TODO: this should be updated to get the pageExtensions
|
681
725
|
// value used during next build
|
682
|
-
const extensionsToTry = ['
|
726
|
+
const extensionsToTry = pageExtensions || ['js', 'jsx', 'ts', 'tsx'];
|
683
727
|
let fsPath = path_1.default.join(workPath, 'pages', page);
|
684
728
|
if (await usesSrcDirectory(workPath)) {
|
685
729
|
fsPath = path_1.default.join(workPath, 'src', 'pages', page);
|
@@ -689,20 +733,20 @@ async function getSourceFilePathFromPage({ workPath, page, }) {
|
|
689
733
|
}
|
690
734
|
const extensionless = fsPath.slice(0, -3); // remove ".js"
|
691
735
|
for (const ext of extensionsToTry) {
|
692
|
-
fsPath = extensionless
|
736
|
+
fsPath = `${extensionless}.${ext}`;
|
693
737
|
if (fs_extra_1.default.existsSync(fsPath)) {
|
694
738
|
return path_1.default.relative(workPath, fsPath);
|
695
739
|
}
|
696
740
|
}
|
697
741
|
if (isDirectory(extensionless)) {
|
698
742
|
for (const ext of extensionsToTry) {
|
699
|
-
fsPath = path_1.default.join(extensionless,
|
743
|
+
fsPath = path_1.default.join(extensionless, `index.${ext}`);
|
700
744
|
if (fs_extra_1.default.existsSync(fsPath)) {
|
701
745
|
return path_1.default.relative(workPath, fsPath);
|
702
746
|
}
|
703
747
|
}
|
704
748
|
}
|
705
|
-
console.log(`WARNING: Unable to find source file for page ${page}`);
|
749
|
+
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`);
|
706
750
|
return '';
|
707
751
|
}
|
708
752
|
exports.getSourceFilePathFromPage = getSourceFilePathFromPage;
|
@@ -738,3 +782,704 @@ function addLocaleOrDefault(pathname, routesManifest, locale) {
|
|
738
782
|
: pathname;
|
739
783
|
}
|
740
784
|
exports.addLocaleOrDefault = addLocaleOrDefault;
|
785
|
+
exports.MAX_UNCOMPRESSED_LAMBDA_SIZE = 250 * 1000 * 1000; // 250MB
|
786
|
+
const LAMBDA_RESERVED_UNCOMPRESSED_SIZE = 2.5 * 1000 * 1000; // 2.5MB
|
787
|
+
const LAMBDA_RESERVED_COMPRESSED_SIZE = 250 * 1000; // 250KB
|
788
|
+
async function getPageLambdaGroups(entryPath, config, pages, prerenderRoutes, pageTraces, compressedPages, tracedPseudoLayer, initialPseudoLayerSize, initialPseudoLayerUncompressedSize, lambdaCompressedByteLimit, internalPages, pageExtensions) {
|
789
|
+
const groups = [];
|
790
|
+
for (const page of pages) {
|
791
|
+
const newPages = [...internalPages, page];
|
792
|
+
const routeName = normalizePage(page.replace(/\.js$/, ''));
|
793
|
+
const isPrerenderRoute = prerenderRoutes.has(routeName);
|
794
|
+
let opts = {};
|
795
|
+
if (config && config.functions) {
|
796
|
+
const sourceFile = await getSourceFilePathFromPage({
|
797
|
+
workPath: entryPath,
|
798
|
+
page,
|
799
|
+
pageExtensions,
|
800
|
+
});
|
801
|
+
opts = await (0, build_utils_1.getLambdaOptionsFromFunction)({
|
802
|
+
sourceFile,
|
803
|
+
config,
|
804
|
+
});
|
805
|
+
}
|
806
|
+
let matchingGroup = groups.find(group => {
|
807
|
+
const matches = group.maxDuration === opts.maxDuration &&
|
808
|
+
group.memory === opts.memory &&
|
809
|
+
group.isPrerenders === isPrerenderRoute;
|
810
|
+
if (matches) {
|
811
|
+
let newTracedFilesSize = group.pseudoLayerBytes;
|
812
|
+
let newTracedFilesUncompressedSize = group.pseudoLayerUncompressedBytes;
|
813
|
+
for (const newPage of newPages) {
|
814
|
+
Object.keys(pageTraces[newPage] || {}).map(file => {
|
815
|
+
var _a;
|
816
|
+
if (!group.pseudoLayer[file]) {
|
817
|
+
const item = tracedPseudoLayer[file];
|
818
|
+
newTracedFilesSize += ((_a = item.compBuffer) === null || _a === void 0 ? void 0 : _a.byteLength) || 0;
|
819
|
+
newTracedFilesUncompressedSize += item.uncompressedSize || 0;
|
820
|
+
}
|
821
|
+
});
|
822
|
+
newTracedFilesSize += compressedPages[newPage].compBuffer.byteLength;
|
823
|
+
newTracedFilesUncompressedSize +=
|
824
|
+
compressedPages[newPage].uncompressedSize;
|
825
|
+
}
|
826
|
+
const underUncompressedLimit = newTracedFilesUncompressedSize + initialPseudoLayerUncompressedSize <
|
827
|
+
exports.MAX_UNCOMPRESSED_LAMBDA_SIZE - LAMBDA_RESERVED_UNCOMPRESSED_SIZE;
|
828
|
+
const underCompressedLimit = newTracedFilesSize + initialPseudoLayerSize <
|
829
|
+
lambdaCompressedByteLimit - LAMBDA_RESERVED_COMPRESSED_SIZE;
|
830
|
+
return underUncompressedLimit && underCompressedLimit;
|
831
|
+
}
|
832
|
+
return false;
|
833
|
+
});
|
834
|
+
if (matchingGroup) {
|
835
|
+
matchingGroup.pages.push(page);
|
836
|
+
}
|
837
|
+
else {
|
838
|
+
const newGroup = {
|
839
|
+
pages: [page],
|
840
|
+
...opts,
|
841
|
+
isPrerenders: isPrerenderRoute,
|
842
|
+
pseudoLayerBytes: 0,
|
843
|
+
pseudoLayerUncompressedBytes: 0,
|
844
|
+
pseudoLayer: {},
|
845
|
+
};
|
846
|
+
groups.push(newGroup);
|
847
|
+
matchingGroup = newGroup;
|
848
|
+
}
|
849
|
+
for (const newPage of newPages) {
|
850
|
+
Object.keys(pageTraces[newPage] || {}).map(file => {
|
851
|
+
var _a;
|
852
|
+
const pseudoItem = tracedPseudoLayer[file];
|
853
|
+
const compressedSize = ((_a = pseudoItem === null || pseudoItem === void 0 ? void 0 : pseudoItem.compBuffer) === null || _a === void 0 ? void 0 : _a.byteLength) || 0;
|
854
|
+
if (!matchingGroup.pseudoLayer[file]) {
|
855
|
+
matchingGroup.pseudoLayer[file] = pseudoItem;
|
856
|
+
matchingGroup.pseudoLayerBytes += compressedSize;
|
857
|
+
matchingGroup.pseudoLayerUncompressedBytes +=
|
858
|
+
pseudoItem.uncompressedSize || 0;
|
859
|
+
}
|
860
|
+
});
|
861
|
+
// ensure the page file itself is accounted for when grouping as
|
862
|
+
// large pages can be created that can push the group over the limit
|
863
|
+
matchingGroup.pseudoLayerBytes +=
|
864
|
+
compressedPages[newPage].compBuffer.byteLength;
|
865
|
+
matchingGroup.pseudoLayerUncompressedBytes +=
|
866
|
+
compressedPages[newPage].uncompressedSize;
|
867
|
+
}
|
868
|
+
}
|
869
|
+
return groups;
|
870
|
+
}
|
871
|
+
exports.getPageLambdaGroups = getPageLambdaGroups;
|
872
|
+
const outputFunctionFileSizeInfo = (pages, pseudoLayer, pseudoLayerBytes, pseudoLayerUncompressedBytes, compressedPages) => {
|
873
|
+
const exceededLimitOutput = [];
|
874
|
+
console.log(`Serverless Function's page${pages.length === 1 ? '' : 's'}: ${pages.join(', ')}`);
|
875
|
+
exceededLimitOutput.push([
|
876
|
+
'Large Dependencies',
|
877
|
+
'Uncompressed size',
|
878
|
+
'Compressed size',
|
879
|
+
]);
|
880
|
+
const dependencies = {};
|
881
|
+
for (const fileKey of Object.keys(pseudoLayer)) {
|
882
|
+
if (!pseudoLayer[fileKey].isSymlink) {
|
883
|
+
const fileItem = pseudoLayer[fileKey];
|
884
|
+
const depKey = fileKey.split('/').slice(0, 3).join('/');
|
885
|
+
if (!dependencies[depKey]) {
|
886
|
+
dependencies[depKey] = {
|
887
|
+
compressed: 0,
|
888
|
+
uncompressed: 0,
|
889
|
+
};
|
890
|
+
}
|
891
|
+
dependencies[depKey].compressed += fileItem.compBuffer.byteLength;
|
892
|
+
dependencies[depKey].uncompressed += fileItem.uncompressedSize;
|
893
|
+
}
|
894
|
+
}
|
895
|
+
for (const page of pages) {
|
896
|
+
dependencies[`pages/${page}`] = {
|
897
|
+
compressed: compressedPages[page].compBuffer.byteLength,
|
898
|
+
uncompressed: compressedPages[page].uncompressedSize,
|
899
|
+
};
|
900
|
+
}
|
901
|
+
let numLargeDependencies = 0;
|
902
|
+
Object.keys(dependencies)
|
903
|
+
.sort((a, b) => {
|
904
|
+
// move largest dependencies to the top
|
905
|
+
const aDep = dependencies[a];
|
906
|
+
const bDep = dependencies[b];
|
907
|
+
if (aDep.compressed > bDep.compressed) {
|
908
|
+
return -1;
|
909
|
+
}
|
910
|
+
if (aDep.compressed < bDep.compressed) {
|
911
|
+
return 1;
|
912
|
+
}
|
913
|
+
return 0;
|
914
|
+
})
|
915
|
+
.forEach(depKey => {
|
916
|
+
const dep = dependencies[depKey];
|
917
|
+
if (dep.compressed < 100 * 1000 && dep.uncompressed < 500 * 1000) {
|
918
|
+
// ignore smaller dependencies to reduce noise
|
919
|
+
return;
|
920
|
+
}
|
921
|
+
exceededLimitOutput.push([
|
922
|
+
depKey,
|
923
|
+
(0, pretty_bytes_1.default)(dep.uncompressed),
|
924
|
+
(0, pretty_bytes_1.default)(dep.compressed),
|
925
|
+
]);
|
926
|
+
numLargeDependencies += 1;
|
927
|
+
});
|
928
|
+
if (numLargeDependencies === 0) {
|
929
|
+
exceededLimitOutput.push([
|
930
|
+
'No large dependencies found (> 100KB compressed)',
|
931
|
+
]);
|
932
|
+
}
|
933
|
+
exceededLimitOutput.push([]);
|
934
|
+
exceededLimitOutput.push([
|
935
|
+
'All dependencies',
|
936
|
+
(0, pretty_bytes_1.default)(pseudoLayerUncompressedBytes),
|
937
|
+
(0, pretty_bytes_1.default)(pseudoLayerBytes),
|
938
|
+
]);
|
939
|
+
console.log((0, text_table_1.default)(exceededLimitOutput, {
|
940
|
+
align: ['l', 'r', 'r'],
|
941
|
+
}));
|
942
|
+
};
|
943
|
+
exports.outputFunctionFileSizeInfo = outputFunctionFileSizeInfo;
|
944
|
+
const detectLambdaLimitExceeding = async (lambdaGroups, compressedSizeLimit, compressedPages) => {
|
945
|
+
// show debug info if within 5 MB of exceeding the limit
|
946
|
+
const COMPRESSED_SIZE_LIMIT_CLOSE = compressedSizeLimit - 5 * 1000 * 1000;
|
947
|
+
const UNCOMPRESSED_SIZE_LIMIT_CLOSE = exports.MAX_UNCOMPRESSED_LAMBDA_SIZE - 5 * 1000 * 1000;
|
948
|
+
let numExceededLimit = 0;
|
949
|
+
let numCloseToLimit = 0;
|
950
|
+
let loggedHeadInfo = false;
|
951
|
+
// pre-iterate to see if we are going to exceed the limit
|
952
|
+
// or only get close so our first log line can be correct
|
953
|
+
const filteredGroups = lambdaGroups.filter(group => {
|
954
|
+
const exceededLimit = group.pseudoLayerBytes > compressedSizeLimit ||
|
955
|
+
group.pseudoLayerUncompressedBytes > exports.MAX_UNCOMPRESSED_LAMBDA_SIZE;
|
956
|
+
const closeToLimit = group.pseudoLayerBytes > COMPRESSED_SIZE_LIMIT_CLOSE ||
|
957
|
+
group.pseudoLayerUncompressedBytes > UNCOMPRESSED_SIZE_LIMIT_CLOSE;
|
958
|
+
if (closeToLimit ||
|
959
|
+
exceededLimit ||
|
960
|
+
(0, build_utils_1.getPlatformEnv)('BUILDER_DEBUG') ||
|
961
|
+
process.env.NEXT_DEBUG_FUNCTION_SIZE) {
|
962
|
+
if (exceededLimit) {
|
963
|
+
numExceededLimit += 1;
|
964
|
+
}
|
965
|
+
if (closeToLimit) {
|
966
|
+
numCloseToLimit += 1;
|
967
|
+
}
|
968
|
+
return true;
|
969
|
+
}
|
970
|
+
});
|
971
|
+
for (const group of filteredGroups) {
|
972
|
+
if (!loggedHeadInfo) {
|
973
|
+
if (numExceededLimit || numCloseToLimit) {
|
974
|
+
console.log(`Warning: Max serverless function size of ${(0, pretty_bytes_1.default)(compressedSizeLimit)} compressed or ${(0, pretty_bytes_1.default)(exports.MAX_UNCOMPRESSED_LAMBDA_SIZE)} uncompressed${numExceededLimit ? '' : ' almost'} reached`);
|
975
|
+
}
|
976
|
+
else {
|
977
|
+
console.log(`Serverless function size info`);
|
978
|
+
}
|
979
|
+
loggedHeadInfo = true;
|
980
|
+
}
|
981
|
+
(0, exports.outputFunctionFileSizeInfo)(group.pages, group.pseudoLayer, group.pseudoLayerBytes, group.pseudoLayerUncompressedBytes, compressedPages);
|
982
|
+
}
|
983
|
+
if (numExceededLimit) {
|
984
|
+
console.log(`Max serverless function size was exceeded for ${numExceededLimit} function${numExceededLimit === 1 ? '' : 's'}`);
|
985
|
+
}
|
986
|
+
};
|
987
|
+
exports.detectLambdaLimitExceeding = detectLambdaLimitExceeding;
|
988
|
+
// checks if prerender files are all static or not before creating lambdas
|
989
|
+
const onPrerenderRouteInitial = (prerenderManifest, canUsePreviewMode, entryDirectory, nonLambdaSsgPages, routeKey, hasPages404, routesManifest) => {
|
990
|
+
let static404Page;
|
991
|
+
let static500Page;
|
992
|
+
// Get the route file as it'd be mounted in the builder output
|
993
|
+
const pr = prerenderManifest.staticRoutes[routeKey];
|
994
|
+
const { initialRevalidate, srcRoute } = pr;
|
995
|
+
const route = srcRoute || routeKey;
|
996
|
+
const routeNoLocale = (routesManifest === null || routesManifest === void 0 ? void 0 : routesManifest.i18n)
|
997
|
+
? normalizeLocalePath(routeKey, routesManifest.i18n.locales).pathname
|
998
|
+
: routeKey;
|
999
|
+
// if the 404 page used getStaticProps we need to update static404Page
|
1000
|
+
// since it wasn't populated from the staticPages group
|
1001
|
+
if (routeNoLocale === '/404') {
|
1002
|
+
static404Page = path_1.default.join(entryDirectory, routeKey);
|
1003
|
+
}
|
1004
|
+
if (routeNoLocale === '/500') {
|
1005
|
+
static500Page = path_1.default.join(entryDirectory, routeKey);
|
1006
|
+
}
|
1007
|
+
if (initialRevalidate === false &&
|
1008
|
+
(!canUsePreviewMode || (hasPages404 && routeNoLocale === '/404')) &&
|
1009
|
+
!prerenderManifest.fallbackRoutes[route] &&
|
1010
|
+
!prerenderManifest.blockingFallbackRoutes[route]) {
|
1011
|
+
if ((routesManifest === null || routesManifest === void 0 ? void 0 : routesManifest.i18n) &&
|
1012
|
+
Object.keys(prerenderManifest.staticRoutes).some(route => {
|
1013
|
+
const staticRoute = prerenderManifest.staticRoutes[route];
|
1014
|
+
return (staticRoute.srcRoute === srcRoute &&
|
1015
|
+
staticRoute.initialRevalidate !== false);
|
1016
|
+
})) {
|
1017
|
+
// if any locale static routes are using revalidate the page
|
1018
|
+
// requires a lambda
|
1019
|
+
return {
|
1020
|
+
static404Page,
|
1021
|
+
static500Page,
|
1022
|
+
};
|
1023
|
+
}
|
1024
|
+
nonLambdaSsgPages.add(route === '/' ? '/index' : route);
|
1025
|
+
}
|
1026
|
+
return {
|
1027
|
+
static404Page,
|
1028
|
+
static500Page,
|
1029
|
+
};
|
1030
|
+
};
|
1031
|
+
exports.onPrerenderRouteInitial = onPrerenderRouteInitial;
|
1032
|
+
let prerenderGroup = 1;
|
1033
|
+
const onPrerenderRoute = (prerenderRouteArgs) => (routeKey, { isBlocking, isFallback, isOmitted, locale, }) => {
|
1034
|
+
var _a;
|
1035
|
+
const { pagesDir, hasPages404, static404Page, entryDirectory, prerenderManifest, isSharedLambdas, isServerMode, canUsePreviewMode, lambdas, prerenders, pageLambdaMap, routesManifest, isCorrectNotFoundRoutes, } = prerenderRouteArgs;
|
1036
|
+
if (isBlocking && isFallback) {
|
1037
|
+
throw new build_utils_1.NowBuildError({
|
1038
|
+
code: 'NEXT_ISBLOCKING_ISFALLBACK',
|
1039
|
+
message: 'invariant: isBlocking and isFallback cannot both be true',
|
1040
|
+
});
|
1041
|
+
}
|
1042
|
+
if (isFallback && isOmitted) {
|
1043
|
+
throw new build_utils_1.NowBuildError({
|
1044
|
+
code: 'NEXT_ISOMITTED_ISFALLBACK',
|
1045
|
+
message: 'invariant: isOmitted and isFallback cannot both be true',
|
1046
|
+
});
|
1047
|
+
}
|
1048
|
+
// Get the route file as it'd be mounted in the builder output
|
1049
|
+
let routeFileNoExt = routeKey === '/' ? '/index' : routeKey;
|
1050
|
+
let origRouteFileNoExt = routeFileNoExt;
|
1051
|
+
const { isLocalePrefixed } = prerenderManifest;
|
1052
|
+
if (!locale && isLocalePrefixed) {
|
1053
|
+
const localePathResult = normalizeLocalePath(routeKey, ((_a = routesManifest === null || routesManifest === void 0 ? void 0 : routesManifest.i18n) === null || _a === void 0 ? void 0 : _a.locales) || []);
|
1054
|
+
locale = localePathResult.detectedLocale;
|
1055
|
+
origRouteFileNoExt =
|
1056
|
+
localePathResult.pathname === '/'
|
1057
|
+
? '/index'
|
1058
|
+
: localePathResult.pathname;
|
1059
|
+
}
|
1060
|
+
const nonDynamicSsg = !isFallback &&
|
1061
|
+
!isBlocking &&
|
1062
|
+
!isOmitted &&
|
1063
|
+
!prerenderManifest.staticRoutes[routeKey].srcRoute;
|
1064
|
+
// if there isn't a srcRoute then it's a non-dynamic SSG page
|
1065
|
+
if ((nonDynamicSsg && !isLocalePrefixed) || isFallback || isOmitted) {
|
1066
|
+
routeFileNoExt = addLocaleOrDefault(
|
1067
|
+
// root index files are located without folder/index.html
|
1068
|
+
routeFileNoExt, routesManifest, locale);
|
1069
|
+
}
|
1070
|
+
const isNotFound = prerenderManifest.notFoundRoutes.includes(routeKey);
|
1071
|
+
const htmlFsRef = isBlocking || (isNotFound && !static404Page)
|
1072
|
+
? // Blocking pages do not have an HTML fallback
|
1073
|
+
null
|
1074
|
+
: new build_utils_1.FileFsRef({
|
1075
|
+
fsPath: path_1.default.join(pagesDir, isFallback
|
1076
|
+
? // Fallback pages have a special file.
|
1077
|
+
addLocaleOrDefault(prerenderManifest.fallbackRoutes[routeKey].fallback, routesManifest, locale)
|
1078
|
+
: // Otherwise, the route itself should exist as a static HTML
|
1079
|
+
// file.
|
1080
|
+
`${isOmitted || isNotFound
|
1081
|
+
? addLocaleOrDefault('/404', routesManifest, locale)
|
1082
|
+
: routeFileNoExt}.html`),
|
1083
|
+
});
|
1084
|
+
const jsonFsRef =
|
1085
|
+
// JSON data does not exist for fallback or blocking pages
|
1086
|
+
isFallback || isBlocking || (isNotFound && !static404Page)
|
1087
|
+
? null
|
1088
|
+
: new build_utils_1.FileFsRef({
|
1089
|
+
fsPath: path_1.default.join(pagesDir, `${isOmitted || isNotFound
|
1090
|
+
? addLocaleOrDefault('/404.html', routesManifest, locale)
|
1091
|
+
: routeFileNoExt + '.json'}`),
|
1092
|
+
});
|
1093
|
+
let initialRevalidate;
|
1094
|
+
let srcRoute;
|
1095
|
+
let dataRoute;
|
1096
|
+
if (isFallback || isBlocking) {
|
1097
|
+
const pr = isFallback
|
1098
|
+
? prerenderManifest.fallbackRoutes[routeKey]
|
1099
|
+
: prerenderManifest.blockingFallbackRoutes[routeKey];
|
1100
|
+
initialRevalidate = 1; // TODO: should Next.js provide this default?
|
1101
|
+
// @ts-ignore
|
1102
|
+
if (initialRevalidate === false) {
|
1103
|
+
// Lazy routes cannot be "snapshotted" in time.
|
1104
|
+
throw new build_utils_1.NowBuildError({
|
1105
|
+
code: 'NEXT_ISLAZY_INITIALREVALIDATE',
|
1106
|
+
message: 'invariant isLazy: initialRevalidate !== false',
|
1107
|
+
});
|
1108
|
+
}
|
1109
|
+
srcRoute = null;
|
1110
|
+
dataRoute = pr.dataRoute;
|
1111
|
+
}
|
1112
|
+
else if (isOmitted) {
|
1113
|
+
initialRevalidate = false;
|
1114
|
+
srcRoute = routeKey;
|
1115
|
+
dataRoute = prerenderManifest.omittedRoutes[routeKey].dataRoute;
|
1116
|
+
}
|
1117
|
+
else {
|
1118
|
+
const pr = prerenderManifest.staticRoutes[routeKey];
|
1119
|
+
({ initialRevalidate, srcRoute, dataRoute } = pr);
|
1120
|
+
}
|
1121
|
+
const outputPathPage = normalizeIndexOutput(path_1.default.posix.join(entryDirectory, routeFileNoExt), isServerMode);
|
1122
|
+
const outputPathPageOrig = path_1.default.posix.join(entryDirectory, origRouteFileNoExt);
|
1123
|
+
let lambda;
|
1124
|
+
let outputPathData = path_1.default.posix.join(entryDirectory, dataRoute);
|
1125
|
+
if (nonDynamicSsg || isFallback || isOmitted) {
|
1126
|
+
outputPathData = outputPathData.replace(new RegExp(`${(0, escape_string_regexp_1.default)(origRouteFileNoExt)}.json$`), `${routeFileNoExt}.json`);
|
1127
|
+
}
|
1128
|
+
if (isSharedLambdas) {
|
1129
|
+
const outputSrcPathPage = normalizeIndexOutput(path_1.default.join('/', srcRoute == null
|
1130
|
+
? outputPathPageOrig
|
1131
|
+
: path_1.default.join(entryDirectory, srcRoute === '/' ? '/index' : srcRoute)), isServerMode);
|
1132
|
+
const lambdaId = pageLambdaMap[outputSrcPathPage];
|
1133
|
+
lambda = lambdas[lambdaId];
|
1134
|
+
}
|
1135
|
+
else {
|
1136
|
+
const outputSrcPathPage = normalizeIndexOutput(srcRoute == null
|
1137
|
+
? outputPathPageOrig
|
1138
|
+
: path_1.default.posix.join(entryDirectory, srcRoute === '/' ? '/index' : srcRoute), isServerMode);
|
1139
|
+
lambda = lambdas[outputSrcPathPage];
|
1140
|
+
}
|
1141
|
+
if (!isNotFound && initialRevalidate === false) {
|
1142
|
+
if (htmlFsRef == null || jsonFsRef == null) {
|
1143
|
+
throw new build_utils_1.NowBuildError({
|
1144
|
+
code: 'NEXT_HTMLFSREF_JSONFSREF',
|
1145
|
+
message: 'invariant: htmlFsRef != null && jsonFsRef != null',
|
1146
|
+
});
|
1147
|
+
}
|
1148
|
+
// If revalidate isn't enabled we force the /404 route to be static
|
1149
|
+
// to match next start behavior otherwise getStaticProps would be
|
1150
|
+
// recalled for each 404 URL path since Prerender is cached based
|
1151
|
+
// on the URL path
|
1152
|
+
if (!canUsePreviewMode || (hasPages404 && routeKey === '/404')) {
|
1153
|
+
htmlFsRef.contentType = _1.htmlContentType;
|
1154
|
+
prerenders[outputPathPage] = htmlFsRef;
|
1155
|
+
prerenders[outputPathData] = jsonFsRef;
|
1156
|
+
}
|
1157
|
+
}
|
1158
|
+
const isNotFoundPreview = isCorrectNotFoundRoutes &&
|
1159
|
+
!initialRevalidate &&
|
1160
|
+
canUsePreviewMode &&
|
1161
|
+
isServerMode &&
|
1162
|
+
isNotFound;
|
1163
|
+
if (prerenders[outputPathPage] == null &&
|
1164
|
+
(!isNotFound || initialRevalidate || isNotFoundPreview)) {
|
1165
|
+
if (lambda == null) {
|
1166
|
+
throw new build_utils_1.NowBuildError({
|
1167
|
+
code: 'NEXT_MISSING_LAMBDA',
|
1168
|
+
message: `Unable to find lambda for route: ${routeFileNoExt}`,
|
1169
|
+
});
|
1170
|
+
}
|
1171
|
+
// `allowQuery` is an array of query parameter keys that are allowed for
|
1172
|
+
// a given path. All other query keys will be striped. We can automatically
|
1173
|
+
// detect this for prerender (ISR) pages by reading the routes manifest file.
|
1174
|
+
const pageKey = srcRoute || routeKey;
|
1175
|
+
const isDynamic = isDynamicRoute(pageKey);
|
1176
|
+
const route = routesManifest === null || routesManifest === void 0 ? void 0 : routesManifest.dynamicRoutes.find((r) => r.page === pageKey && !('isMiddleware' in r));
|
1177
|
+
const routeKeys = route === null || route === void 0 ? void 0 : route.routeKeys;
|
1178
|
+
// by default allowQuery should be undefined and only set when
|
1179
|
+
// we have sufficient information to set it
|
1180
|
+
let allowQuery;
|
1181
|
+
if (routeKeys) {
|
1182
|
+
// if we have routeKeys in the routes-manifest we use those
|
1183
|
+
// for allowQuery for dynamic routes
|
1184
|
+
allowQuery = Object.values(routeKeys);
|
1185
|
+
}
|
1186
|
+
else if (!isDynamic) {
|
1187
|
+
// for non-dynamic routes we use an empty array since
|
1188
|
+
// no query values bust the cache for non-dynamic prerenders
|
1189
|
+
allowQuery = [];
|
1190
|
+
}
|
1191
|
+
prerenders[outputPathPage] = new build_utils_1.Prerender({
|
1192
|
+
expiration: initialRevalidate,
|
1193
|
+
lambda,
|
1194
|
+
allowQuery,
|
1195
|
+
fallback: htmlFsRef,
|
1196
|
+
group: prerenderGroup,
|
1197
|
+
bypassToken: prerenderManifest.bypassToken,
|
1198
|
+
});
|
1199
|
+
prerenders[outputPathData] = new build_utils_1.Prerender({
|
1200
|
+
expiration: initialRevalidate,
|
1201
|
+
lambda,
|
1202
|
+
allowQuery,
|
1203
|
+
fallback: jsonFsRef,
|
1204
|
+
group: prerenderGroup,
|
1205
|
+
bypassToken: prerenderManifest.bypassToken,
|
1206
|
+
});
|
1207
|
+
++prerenderGroup;
|
1208
|
+
if ((routesManifest === null || routesManifest === void 0 ? void 0 : routesManifest.i18n) && isBlocking) {
|
1209
|
+
for (const locale of routesManifest.i18n.locales) {
|
1210
|
+
const localeRouteFileNoExt = addLocaleOrDefault(routeFileNoExt, routesManifest, locale);
|
1211
|
+
const localeOutputPathPage = normalizeIndexOutput(path_1.default.posix.join(entryDirectory, localeRouteFileNoExt), isServerMode);
|
1212
|
+
const localeOutputPathData = outputPathData.replace(new RegExp(`${(0, escape_string_regexp_1.default)(origRouteFileNoExt)}.json$`), `${localeRouteFileNoExt}${localeRouteFileNoExt !== origRouteFileNoExt &&
|
1213
|
+
origRouteFileNoExt === '/index'
|
1214
|
+
? '/index'
|
1215
|
+
: ''}.json`);
|
1216
|
+
const origPrerenderPage = prerenders[outputPathPage];
|
1217
|
+
const origPrerenderData = prerenders[outputPathData];
|
1218
|
+
prerenders[localeOutputPathPage] = {
|
1219
|
+
...origPrerenderPage,
|
1220
|
+
group: prerenderGroup,
|
1221
|
+
};
|
1222
|
+
prerenders[localeOutputPathData] = {
|
1223
|
+
...origPrerenderData,
|
1224
|
+
group: prerenderGroup,
|
1225
|
+
};
|
1226
|
+
++prerenderGroup;
|
1227
|
+
}
|
1228
|
+
}
|
1229
|
+
}
|
1230
|
+
if (((nonDynamicSsg && !isLocalePrefixed) || isFallback || isOmitted) &&
|
1231
|
+
(routesManifest === null || routesManifest === void 0 ? void 0 : routesManifest.i18n) &&
|
1232
|
+
!locale) {
|
1233
|
+
// load each locale
|
1234
|
+
for (const locale of routesManifest.i18n.locales) {
|
1235
|
+
if (locale === routesManifest.i18n.defaultLocale)
|
1236
|
+
continue;
|
1237
|
+
(0, exports.onPrerenderRoute)(prerenderRouteArgs)(routeKey, {
|
1238
|
+
isBlocking,
|
1239
|
+
isFallback,
|
1240
|
+
isOmitted,
|
1241
|
+
locale,
|
1242
|
+
});
|
1243
|
+
}
|
1244
|
+
}
|
1245
|
+
};
|
1246
|
+
exports.onPrerenderRoute = onPrerenderRoute;
|
1247
|
+
async function getStaticFiles(entryPath, entryDirectory, outputDirectory) {
|
1248
|
+
const collectLabel = 'Collected static files (public/, static/, .next/static)';
|
1249
|
+
console.time(collectLabel);
|
1250
|
+
const nextStaticFiles = await (0, build_utils_1.glob)('**', path_1.default.join(entryPath, outputDirectory, 'static'));
|
1251
|
+
const staticFolderFiles = await (0, build_utils_1.glob)('**', path_1.default.join(entryPath, 'static'));
|
1252
|
+
let publicFolderFiles = {};
|
1253
|
+
let publicFolderPath;
|
1254
|
+
if (await fs_extra_1.default.pathExists(path_1.default.join(entryPath, 'public'))) {
|
1255
|
+
publicFolderPath = path_1.default.join(entryPath, 'public');
|
1256
|
+
}
|
1257
|
+
else if (
|
1258
|
+
// check at the same level as the output directory also
|
1259
|
+
await fs_extra_1.default.pathExists(path_1.default.join(entryPath, outputDirectory, '../public'))) {
|
1260
|
+
publicFolderPath = path_1.default.join(entryPath, outputDirectory, '../public');
|
1261
|
+
}
|
1262
|
+
if (publicFolderPath) {
|
1263
|
+
(0, build_utils_1.debug)(`Using public folder at ${publicFolderPath}`);
|
1264
|
+
publicFolderFiles = await (0, build_utils_1.glob)('**/*', publicFolderPath);
|
1265
|
+
}
|
1266
|
+
else {
|
1267
|
+
(0, build_utils_1.debug)('No public folder found');
|
1268
|
+
}
|
1269
|
+
const staticFiles = {};
|
1270
|
+
const staticDirectoryFiles = {};
|
1271
|
+
const publicDirectoryFiles = {};
|
1272
|
+
for (const file of Object.keys(nextStaticFiles)) {
|
1273
|
+
staticFiles[path_1.default.join(entryDirectory, `_next/static/${file}`)] =
|
1274
|
+
nextStaticFiles[file];
|
1275
|
+
}
|
1276
|
+
for (const file of Object.keys(staticFolderFiles)) {
|
1277
|
+
staticDirectoryFiles[path_1.default.join(entryDirectory, 'static', file)] =
|
1278
|
+
staticFolderFiles[file];
|
1279
|
+
}
|
1280
|
+
for (const file of Object.keys(publicFolderFiles)) {
|
1281
|
+
publicDirectoryFiles[path_1.default.join(entryDirectory, file)] =
|
1282
|
+
publicFolderFiles[file];
|
1283
|
+
}
|
1284
|
+
console.timeEnd(collectLabel);
|
1285
|
+
return {
|
1286
|
+
staticFiles,
|
1287
|
+
staticDirectoryFiles,
|
1288
|
+
publicDirectoryFiles,
|
1289
|
+
};
|
1290
|
+
}
|
1291
|
+
exports.getStaticFiles = getStaticFiles;
|
1292
|
+
function normalizeIndexOutput(outputName, isServerMode) {
|
1293
|
+
if (outputName !== '/index' && isServerMode) {
|
1294
|
+
return outputName.replace(/\/index$/, '');
|
1295
|
+
}
|
1296
|
+
return outputName;
|
1297
|
+
}
|
1298
|
+
exports.normalizeIndexOutput = normalizeIndexOutput;
|
1299
|
+
/**
|
1300
|
+
* The path to next-server was changed in
|
1301
|
+
* https://github.com/vercel/next.js/pull/26756
|
1302
|
+
*/
|
1303
|
+
function getNextServerPath(nextVersion) {
|
1304
|
+
return semver_1.default.gte(nextVersion, 'v11.0.2-canary.4')
|
1305
|
+
? 'next/dist/server'
|
1306
|
+
: 'next/dist/next-server/server';
|
1307
|
+
}
|
1308
|
+
exports.getNextServerPath = getNextServerPath;
|
1309
|
+
// update to leverage
|
1310
|
+
function updateRouteSrc(route, index, manifestItems) {
|
1311
|
+
if (route.src) {
|
1312
|
+
route.src = manifestItems[index].regex;
|
1313
|
+
}
|
1314
|
+
return route;
|
1315
|
+
}
|
1316
|
+
exports.updateRouteSrc = updateRouteSrc;
|
1317
|
+
async function getPrivateOutputs(dir, entries) {
|
1318
|
+
const files = {};
|
1319
|
+
const routes = [];
|
1320
|
+
for (const [existingFile, outputFile] of Object.entries(entries)) {
|
1321
|
+
const fsPath = path_1.default.join(dir, existingFile);
|
1322
|
+
try {
|
1323
|
+
const { mode, size } = await (0, fs_extra_1.stat)(fsPath);
|
1324
|
+
if (size > 30 * 1024 * 1024) {
|
1325
|
+
throw new Error(`Exceeds maximum file size: ${size}`);
|
1326
|
+
}
|
1327
|
+
files[outputFile] = new build_utils_1.FileFsRef({ mode, fsPath });
|
1328
|
+
routes.push({
|
1329
|
+
src: `/${outputFile}`,
|
1330
|
+
dest: '/404',
|
1331
|
+
status: 404,
|
1332
|
+
continue: true,
|
1333
|
+
});
|
1334
|
+
}
|
1335
|
+
catch (error) {
|
1336
|
+
(0, build_utils_1.debug)(`Private file ${existingFile} had an error and will not be uploaded: ${error}`);
|
1337
|
+
}
|
1338
|
+
}
|
1339
|
+
return { files, routes };
|
1340
|
+
}
|
1341
|
+
exports.getPrivateOutputs = getPrivateOutputs;
|
1342
|
+
async function getMiddlewareBundle({ entryPath, outputDirectory, routesManifest, }) {
|
1343
|
+
const middlewareManifest = await getMiddlewareManifest(entryPath, outputDirectory);
|
1344
|
+
if (middlewareManifest && (middlewareManifest === null || middlewareManifest === void 0 ? void 0 : middlewareManifest.sortedMiddleware.length) > 0) {
|
1345
|
+
const workerConfigs = await Promise.all(middlewareManifest.sortedMiddleware.map(async (key) => {
|
1346
|
+
const middleware = middlewareManifest.middleware[key];
|
1347
|
+
try {
|
1348
|
+
const wrappedModuleSource = await (0, get_edge_function_source_1.getNextjsEdgeFunctionSource)(middleware.files, {
|
1349
|
+
name: middleware.name,
|
1350
|
+
staticRoutes: routesManifest.staticRoutes,
|
1351
|
+
dynamicRoutes: routesManifest.dynamicRoutes.filter(r => !('isMiddleware' in r)),
|
1352
|
+
nextConfig: {
|
1353
|
+
basePath: routesManifest.basePath,
|
1354
|
+
i18n: routesManifest.i18n,
|
1355
|
+
},
|
1356
|
+
}, path_1.default.resolve(entryPath, outputDirectory), middleware.wasm);
|
1357
|
+
return {
|
1358
|
+
page: middlewareManifest.middleware[key].page,
|
1359
|
+
edgeFunction: (() => {
|
1360
|
+
var _a;
|
1361
|
+
const { source, map } = wrappedModuleSource.sourceAndMap();
|
1362
|
+
const transformedMap = (0, sourcemapped_1.stringifySourceMap)(transformSourceMap(map));
|
1363
|
+
const wasmFiles = ((_a = middleware.wasm) !== null && _a !== void 0 ? _a : []).reduce((acc, { filePath, name }) => {
|
1364
|
+
const fullFilePath = path_1.default.join(entryPath, outputDirectory, filePath);
|
1365
|
+
acc[`wasm/${name}.wasm`] = new build_utils_1.FileFsRef({
|
1366
|
+
mode: 0o644,
|
1367
|
+
contentType: 'application/wasm',
|
1368
|
+
fsPath: fullFilePath,
|
1369
|
+
});
|
1370
|
+
return acc;
|
1371
|
+
}, {});
|
1372
|
+
return new build_utils_1.EdgeFunction({
|
1373
|
+
deploymentTarget: 'v8-worker',
|
1374
|
+
name: middleware.name,
|
1375
|
+
files: {
|
1376
|
+
'index.js': new build_utils_1.FileBlob({
|
1377
|
+
data: source,
|
1378
|
+
contentType: 'application/javascript',
|
1379
|
+
mode: 0o644,
|
1380
|
+
}),
|
1381
|
+
...(transformedMap && {
|
1382
|
+
'index.js.map': new build_utils_1.FileBlob({
|
1383
|
+
data: transformedMap,
|
1384
|
+
contentType: 'application/json',
|
1385
|
+
mode: 0o644,
|
1386
|
+
}),
|
1387
|
+
}),
|
1388
|
+
...wasmFiles,
|
1389
|
+
},
|
1390
|
+
entrypoint: 'index.js',
|
1391
|
+
envVarsInUse: middleware.env,
|
1392
|
+
});
|
1393
|
+
})(),
|
1394
|
+
routeSrc: getRouteSrc(middlewareManifest.middleware[key], routesManifest),
|
1395
|
+
};
|
1396
|
+
}
|
1397
|
+
catch (e) {
|
1398
|
+
e.message = `Can't build edge function ${key}: ${e.message}`;
|
1399
|
+
throw e;
|
1400
|
+
}
|
1401
|
+
}));
|
1402
|
+
const source = {
|
1403
|
+
staticRoutes: [],
|
1404
|
+
dynamicRouteMap: new Map(),
|
1405
|
+
edgeFunctions: {},
|
1406
|
+
middleware: [],
|
1407
|
+
};
|
1408
|
+
for (const worker of workerConfigs.values()) {
|
1409
|
+
const edgeFile = worker.edgeFunction.name;
|
1410
|
+
worker.edgeFunction.name = edgeFile.replace(/^pages\//, '');
|
1411
|
+
source.edgeFunctions[edgeFile] = worker.edgeFunction;
|
1412
|
+
const route = {
|
1413
|
+
continue: true,
|
1414
|
+
middlewarePath: edgeFile,
|
1415
|
+
src: worker.routeSrc,
|
1416
|
+
};
|
1417
|
+
if (routesManifest.version > 3 && isDynamicRoute(worker.page)) {
|
1418
|
+
source.dynamicRouteMap.set(worker.page, route);
|
1419
|
+
}
|
1420
|
+
else {
|
1421
|
+
source.staticRoutes.push(route);
|
1422
|
+
}
|
1423
|
+
}
|
1424
|
+
return source;
|
1425
|
+
}
|
1426
|
+
return {
|
1427
|
+
staticRoutes: [],
|
1428
|
+
dynamicRouteMap: new Map(),
|
1429
|
+
edgeFunctions: {},
|
1430
|
+
middleware: [],
|
1431
|
+
};
|
1432
|
+
}
|
1433
|
+
exports.getMiddlewareBundle = getMiddlewareBundle;
|
1434
|
+
/**
|
1435
|
+
* Attempts to read the middleware manifest from the pre-defined
|
1436
|
+
* location. If the manifest can't be found it will resolve to
|
1437
|
+
* undefined.
|
1438
|
+
*/
|
1439
|
+
async function getMiddlewareManifest(entryPath, outputDirectory) {
|
1440
|
+
const middlewareManifestPath = path_1.default.join(entryPath, outputDirectory, './server/middleware-manifest.json');
|
1441
|
+
const hasManifest = await fs_extra_1.default
|
1442
|
+
.access(middlewareManifestPath)
|
1443
|
+
.then(() => true)
|
1444
|
+
.catch(() => false);
|
1445
|
+
if (!hasManifest) {
|
1446
|
+
return;
|
1447
|
+
}
|
1448
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
1449
|
+
return require(middlewareManifestPath);
|
1450
|
+
}
|
1451
|
+
/**
|
1452
|
+
* For an object containing middleware info and a routes manifest this will
|
1453
|
+
* generate a string with the route that will activate the middleware on
|
1454
|
+
* Vercel Proxy.
|
1455
|
+
*
|
1456
|
+
* @param param0 The middleware info including regexp and page.
|
1457
|
+
* @param param1 The routes manifest
|
1458
|
+
* @returns A regexp string for the middleware route.
|
1459
|
+
*/
|
1460
|
+
function getRouteSrc({ regexp, page }, { basePath = '', i18n }) {
|
1461
|
+
if (page === '/') {
|
1462
|
+
return regexp.replace('_next', `${(basePath === null || basePath === void 0 ? void 0 : basePath.substring(1)) ? `${basePath === null || basePath === void 0 ? void 0 : basePath.substring(1)}/` : ''}_next`);
|
1463
|
+
}
|
1464
|
+
const locale = (i18n === null || i18n === void 0 ? void 0 : i18n.locales.length)
|
1465
|
+
? `(?:/(${i18n.locales
|
1466
|
+
.map(locale => (0, escape_string_regexp_1.default)(locale))
|
1467
|
+
.join('|')}))?`
|
1468
|
+
: '';
|
1469
|
+
return `(?:^${basePath}${locale}${regexp.substring(1)})`;
|
1470
|
+
}
|
1471
|
+
/**
|
1472
|
+
* Makes the sources more human-readable in the source map
|
1473
|
+
* by removing webpack-specific prefixes
|
1474
|
+
*/
|
1475
|
+
function transformSourceMap(sourcemap) {
|
1476
|
+
var _a;
|
1477
|
+
if (!sourcemap)
|
1478
|
+
return;
|
1479
|
+
const sources = (_a = sourcemap.sources) === null || _a === void 0 ? void 0 : _a.map(source => {
|
1480
|
+
return source.replace(/^webpack:\/\/?_N_E\/(?:\.\/)?/, '');
|
1481
|
+
}).map(source => {
|
1482
|
+
return source.startsWith('?') ? '[native code]' : source;
|
1483
|
+
});
|
1484
|
+
return { ...sourcemap, sources };
|
1485
|
+
}
|