1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", {
|
3 | value: true
|
4 | });
|
5 | exports.collectPages = collectPages;
|
6 | exports.printTreeView = printTreeView;
|
7 | exports.printCustomRoutes = printCustomRoutes;
|
8 | exports.computeFromManifest = computeFromManifest;
|
9 | exports.difference = difference;
|
10 | exports.getJsPageSizeInKb = getJsPageSizeInKb;
|
11 | exports.buildStaticPaths = buildStaticPaths;
|
12 | exports.isPageStatic = isPageStatic;
|
13 | exports.hasCustomGetInitialProps = hasCustomGetInitialProps;
|
14 | exports.getNamedExports = getNamedExports;
|
15 | exports.detectConflictingPaths = detectConflictingPaths;
|
16 | exports.getRawPageExtensions = getRawPageExtensions;
|
17 | exports.isFlightPage = isFlightPage;
|
18 | exports.getUnresolvedModuleFromError = getUnresolvedModuleFromError;
|
19 | exports.copyTracedFiles = copyTracedFiles;
|
20 | exports.isReservedPage = isReservedPage;
|
21 | exports.isCustomErrorPage = isCustomErrorPage;
|
22 | require("../server/node-polyfill-fetch");
|
23 | var _chalk = _interopRequireDefault(require("next/dist/compiled/chalk"));
|
24 | var _gzipSize = _interopRequireDefault(require("next/dist/compiled/gzip-size"));
|
25 | var _textTable = _interopRequireDefault(require("next/dist/compiled/text-table"));
|
26 | var _path = _interopRequireDefault(require("path"));
|
27 | var _fs = require("fs");
|
28 | var _reactIs = require("next/dist/compiled/react-is");
|
29 | var _stripAnsi = _interopRequireDefault(require("next/dist/compiled/strip-ansi"));
|
30 | var _constants = require("../lib/constants");
|
31 | var _prettyBytes = _interopRequireDefault(require("../lib/pretty-bytes"));
|
32 | var _recursiveReaddir = require("../lib/recursive-readdir");
|
33 | var _utils = require("../shared/lib/router/utils");
|
34 | var _isDynamic = require("../shared/lib/router/utils/is-dynamic");
|
35 | var _escapePathDelimiters = _interopRequireDefault(require("../shared/lib/router/utils/escape-path-delimiters"));
|
36 | var _findPageFile = require("../server/lib/find-page-file");
|
37 | var _normalizePagePath = require("../server/normalize-page-path");
|
38 | var _normalizeTrailingSlash = require("../client/normalize-trailing-slash");
|
39 | var _normalizeLocalePath = require("../shared/lib/i18n/normalize-locale-path");
|
40 | var Log = _interopRequireWildcard(require("./output/log"));
|
41 | var _loadComponents = require("../server/load-components");
|
42 | var _trace = require("../trace");
|
43 | var _config = require("../server/config");
|
44 | var _isError = _interopRequireDefault(require("../lib/is-error"));
|
45 | var _recursiveDelete = require("../lib/recursive-delete");
|
46 | var _asyncSema = require("next/dist/compiled/async-sema");
|
47 | function _interopRequireDefault(obj) {
|
48 | return obj && obj.__esModule ? obj : {
|
49 | default: obj
|
50 | };
|
51 | }
|
52 | function _interopRequireWildcard(obj) {
|
53 | if (obj && obj.__esModule) {
|
54 | return obj;
|
55 | } else {
|
56 | var newObj = {};
|
57 | if (obj != null) {
|
58 | for(var key in obj){
|
59 | if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
60 | var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {};
|
61 | if (desc.get || desc.set) {
|
62 | Object.defineProperty(newObj, key, desc);
|
63 | } else {
|
64 | newObj[key] = obj[key];
|
65 | }
|
66 | }
|
67 | }
|
68 | }
|
69 | newObj.default = obj;
|
70 | return newObj;
|
71 | }
|
72 | }
|
73 | const { builtinModules } = require('module');
|
74 | const RESERVED_PAGE = /^\/(_app|_error|_document|api(\/|$))/;
|
75 | const fileGzipStats = {};
|
76 | const fsStatGzip = (file)=>{
|
77 | const cached = fileGzipStats[file];
|
78 | if (cached) return cached;
|
79 | return fileGzipStats[file] = _gzipSize.default.file(file);
|
80 | };
|
81 | const fileSize = async (file)=>(await _fs.promises.stat(file)).size
|
82 | ;
|
83 | const fileStats = {};
|
84 | const fsStat = (file)=>{
|
85 | const cached = fileStats[file];
|
86 | if (cached) return cached;
|
87 | return fileStats[file] = fileSize(file);
|
88 | };
|
89 | function collectPages(directory, pageExtensions) {
|
90 | return (0, _recursiveReaddir).recursiveReadDir(directory, new RegExp(`\\.(?:${pageExtensions.join('|')})$`));
|
91 | }
|
92 | async function printTreeView(list, pageInfos, serverless, { distPath , buildId , pagesDir , pageExtensions , buildManifest , useStatic404 , gzipSize =true }) {
|
93 | const getPrettySize = (_size)=>{
|
94 | const size = (0, _prettyBytes).default(_size);
|
95 |
|
96 | if (_size < 130 * 1000) return _chalk.default.green(size);
|
97 |
|
98 | if (_size < 170 * 1000) return _chalk.default.yellow(size);
|
99 |
|
100 | return _chalk.default.red.bold(size);
|
101 | };
|
102 | const MIN_DURATION = 300;
|
103 | const getPrettyDuration = (_duration)=>{
|
104 | const duration = `${_duration} ms`;
|
105 |
|
106 | if (_duration < 1000) return _chalk.default.green(duration);
|
107 |
|
108 | if (_duration < 2000) return _chalk.default.yellow(duration);
|
109 |
|
110 | return _chalk.default.red.bold(duration);
|
111 | };
|
112 | const getCleanName = (fileName)=>fileName
|
113 | .replace(/^static\//, '')
|
114 | .replace(/^<buildId>/, 'static')
|
115 | .replace(/(?:^|[.-])([0-9a-z]{6})[0-9a-z]{14}(?=\.)/, '.$1')
|
116 | ;
|
117 | const messages = [
|
118 | [
|
119 | 'Page',
|
120 | 'Size',
|
121 | 'First Load JS'
|
122 | ].map((entry)=>_chalk.default.underline(entry)
|
123 | ),
|
124 | ];
|
125 | const hasCustomApp = await (0, _findPageFile).findPageFile(pagesDir, '/_app', pageExtensions);
|
126 | pageInfos.set('/404', {
|
127 | ...pageInfos.get('/404') || pageInfos.get('/_error'),
|
128 | static: useStatic404
|
129 | });
|
130 | if (!list.includes('/404')) {
|
131 | list = [
|
132 | ...list,
|
133 | '/404'
|
134 | ];
|
135 | }
|
136 | const sizeData = await computeFromManifest(buildManifest, distPath, gzipSize, pageInfos);
|
137 | const usedSymbols = new Set();
|
138 | const pageList = list.slice().filter((e)=>!(e === '/_document' || e === '/_error' || !hasCustomApp && e === '/_app')
|
139 | ).sort((a, b)=>a.localeCompare(b)
|
140 | );
|
141 | pageList.forEach((item, i, arr)=>{
|
142 | var ref, ref1, ref2;
|
143 | const border = i === 0 ? arr.length === 1 ? '─' : '┌' : i === arr.length - 1 ? '└' : '├';
|
144 | const pageInfo = pageInfos.get(item);
|
145 | const ampFirst = buildManifest.ampFirstPages.includes(item);
|
146 | const totalDuration = ((pageInfo === null || pageInfo === void 0 ? void 0 : pageInfo.pageDuration) || 0) + ((pageInfo === null || pageInfo === void 0 ? void 0 : (ref = pageInfo.ssgPageDurations) === null || ref === void 0 ? void 0 : ref.reduce((a, b)=>a + (b || 0)
|
147 | , 0)) || 0);
|
148 | const symbol = item === '/_app' ? ' ' : item.endsWith('/_middleware') ? 'ƒ' : (pageInfo === null || pageInfo === void 0 ? void 0 : pageInfo.static) ? '○' : (pageInfo === null || pageInfo === void 0 ? void 0 : pageInfo.isSsg) ? '●' : (pageInfo === null || pageInfo === void 0 ? void 0 : pageInfo.runtime) === 'edge' ? 'ℇ' : 'λ';
|
149 | usedSymbols.add(symbol);
|
150 | if (pageInfo === null || pageInfo === void 0 ? void 0 : pageInfo.initialRevalidateSeconds) usedSymbols.add('ISR');
|
151 | messages.push([
|
152 | `${border} ${symbol} ${(pageInfo === null || pageInfo === void 0 ? void 0 : pageInfo.initialRevalidateSeconds) ? `${item} (ISR: ${pageInfo === null || pageInfo === void 0 ? void 0 : pageInfo.initialRevalidateSeconds} Seconds)` : item}${totalDuration > MIN_DURATION ? ` (${getPrettyDuration(totalDuration)})` : ''}`,
|
153 | pageInfo ? ampFirst ? _chalk.default.cyan('AMP') : pageInfo.size >= 0 ? (0, _prettyBytes).default(pageInfo.size) : '' : '',
|
154 | pageInfo ? ampFirst ? _chalk.default.cyan('AMP') : pageInfo.size >= 0 ? getPrettySize(pageInfo.totalSize) : '' : '',
|
155 | ]);
|
156 | const uniqueCssFiles = ((ref1 = buildManifest.pages[item]) === null || ref1 === void 0 ? void 0 : ref1.filter((file)=>file.endsWith('.css') && sizeData.uniqueFiles.includes(file)
|
157 | )) || [];
|
158 | if (uniqueCssFiles.length > 0) {
|
159 | const contSymbol = i === arr.length - 1 ? ' ' : '├';
|
160 | uniqueCssFiles.forEach((file, index, { length })=>{
|
161 | const innerSymbol = index === length - 1 ? '└' : '├';
|
162 | messages.push([
|
163 | `${contSymbol} ${innerSymbol} ${getCleanName(file)}`,
|
164 | (0, _prettyBytes).default(sizeData.sizeUniqueFiles[file]),
|
165 | '',
|
166 | ]);
|
167 | });
|
168 | }
|
169 | if (pageInfo === null || pageInfo === void 0 ? void 0 : (ref2 = pageInfo.ssgPageRoutes) === null || ref2 === void 0 ? void 0 : ref2.length) {
|
170 | const totalRoutes = pageInfo.ssgPageRoutes.length;
|
171 | const contSymbol = i === arr.length - 1 ? ' ' : '├';
|
172 | let routes;
|
173 | if (pageInfo.ssgPageDurations && pageInfo.ssgPageDurations.some((d)=>d > MIN_DURATION
|
174 | )) {
|
175 | const previewPages = totalRoutes === 8 ? 8 : Math.min(totalRoutes, 7);
|
176 | const routesWithDuration = pageInfo.ssgPageRoutes.map((route, idx)=>({
|
177 | route,
|
178 | duration: pageInfo.ssgPageDurations[idx] || 0
|
179 | })
|
180 | ).sort(({ duration: a }, { duration: b })=>
|
181 |
|
182 | a <= MIN_DURATION && b <= MIN_DURATION ? 0 : b - a
|
183 | );
|
184 | routes = routesWithDuration.slice(0, previewPages);
|
185 | const remainingRoutes = routesWithDuration.slice(previewPages);
|
186 | if (remainingRoutes.length) {
|
187 | const remaining = remainingRoutes.length;
|
188 | const avgDuration = Math.round(remainingRoutes.reduce((total, { duration })=>total + duration
|
189 | , 0) / remainingRoutes.length);
|
190 | routes.push({
|
191 | route: `[+${remaining} more paths]`,
|
192 | duration: 0,
|
193 | avgDuration
|
194 | });
|
195 | }
|
196 | } else {
|
197 | const previewPages = totalRoutes === 4 ? 4 : Math.min(totalRoutes, 3);
|
198 | routes = pageInfo.ssgPageRoutes.slice(0, previewPages).map((route)=>({
|
199 | route,
|
200 | duration: 0
|
201 | })
|
202 | );
|
203 | if (totalRoutes > previewPages) {
|
204 | const remaining = totalRoutes - previewPages;
|
205 | routes.push({
|
206 | route: `[+${remaining} more paths]`,
|
207 | duration: 0
|
208 | });
|
209 | }
|
210 | }
|
211 | routes.forEach(({ route , duration , avgDuration }, index, { length })=>{
|
212 | const innerSymbol = index === length - 1 ? '└' : '├';
|
213 | messages.push([
|
214 | `${contSymbol} ${innerSymbol} ${route}${duration > MIN_DURATION ? ` (${getPrettyDuration(duration)})` : ''}${avgDuration && avgDuration > MIN_DURATION ? ` (avg ${getPrettyDuration(avgDuration)})` : ''}`,
|
215 | '',
|
216 | '',
|
217 | ]);
|
218 | });
|
219 | }
|
220 | });
|
221 | const sharedFilesSize = sizeData.sizeCommonFiles;
|
222 | const sharedFiles = sizeData.sizeCommonFile;
|
223 | messages.push([
|
224 | '+ First Load JS shared by all',
|
225 | getPrettySize(sharedFilesSize),
|
226 | '',
|
227 | ]);
|
228 | const sharedFileKeys = Object.keys(sharedFiles);
|
229 | const sharedCssFiles = [];
|
230 | [
|
231 | ...sharedFileKeys.filter((file)=>{
|
232 | if (file.endsWith('.css')) {
|
233 | sharedCssFiles.push(file);
|
234 | return false;
|
235 | }
|
236 | return true;
|
237 | }).map((e)=>e.replace(buildId, '<buildId>')
|
238 | ).sort(),
|
239 | ...sharedCssFiles.map((e)=>e.replace(buildId, '<buildId>')
|
240 | ).sort(),
|
241 | ].forEach((fileName, index, { length })=>{
|
242 | const innerSymbol = index === length - 1 ? '└' : '├';
|
243 | const originalName = fileName.replace('<buildId>', buildId);
|
244 | const cleanName = getCleanName(fileName);
|
245 | messages.push([
|
246 | ` ${innerSymbol} ${cleanName}`,
|
247 | (0, _prettyBytes).default(sharedFiles[originalName]),
|
248 | '',
|
249 | ]);
|
250 | });
|
251 | console.log((0, _textTable).default(messages, {
|
252 | align: [
|
253 | 'l',
|
254 | 'l',
|
255 | 'r'
|
256 | ],
|
257 | stringLength: (str)=>(0, _stripAnsi).default(str).length
|
258 | }));
|
259 | console.log();
|
260 | console.log((0, _textTable).default([
|
261 | usedSymbols.has('ƒ') && [
|
262 | 'ƒ',
|
263 | '(Middleware)',
|
264 | `intercepts requests (uses ${_chalk.default.cyan('_middleware')})`,
|
265 | ],
|
266 | usedSymbols.has('ℇ') && [
|
267 | 'ℇ',
|
268 | '(Streaming)',
|
269 | `server-side renders with streaming (uses React 18 SSR streaming or Server Components)`,
|
270 | ],
|
271 | usedSymbols.has('λ') && [
|
272 | 'λ',
|
273 | serverless ? '(Lambda)' : '(Server)',
|
274 | `server-side renders at runtime (uses ${_chalk.default.cyan('getInitialProps')} or ${_chalk.default.cyan('getServerSideProps')})`,
|
275 | ],
|
276 | usedSymbols.has('○') && [
|
277 | '○',
|
278 | '(Static)',
|
279 | 'automatically rendered as static HTML (uses no initial props)',
|
280 | ],
|
281 | usedSymbols.has('●') && [
|
282 | '●',
|
283 | '(SSG)',
|
284 | `automatically generated as static HTML + JSON (uses ${_chalk.default.cyan('getStaticProps')})`,
|
285 | ],
|
286 | usedSymbols.has('ISR') && [
|
287 | '',
|
288 | '(ISR)',
|
289 | `incremental static regeneration (uses revalidate in ${_chalk.default.cyan('getStaticProps')})`,
|
290 | ],
|
291 | ].filter((x)=>x
|
292 | ), {
|
293 | align: [
|
294 | 'l',
|
295 | 'l',
|
296 | 'l'
|
297 | ],
|
298 | stringLength: (str)=>(0, _stripAnsi).default(str).length
|
299 | }));
|
300 | console.log();
|
301 | }
|
302 | function printCustomRoutes({ redirects , rewrites , headers }) {
|
303 | const printRoutes = (routes, type)=>{
|
304 | const isRedirects = type === 'Redirects';
|
305 | const isHeaders = type === 'Headers';
|
306 | console.log(_chalk.default.underline(type));
|
307 | console.log();
|
308 | |
309 |
|
310 |
|
311 |
|
312 | const routesStr = routes.map((route)=>{
|
313 | let routeStr = `┌ source: ${route.source}\n`;
|
314 | if (!isHeaders) {
|
315 | const r = route;
|
316 | routeStr += `${isRedirects ? '├' : '└'} destination: ${r.destination}\n`;
|
317 | }
|
318 | if (isRedirects) {
|
319 | const r = route;
|
320 | routeStr += `└ ${r.statusCode ? `status: ${r.statusCode}` : `permanent: ${r.permanent}`}\n`;
|
321 | }
|
322 | if (isHeaders) {
|
323 | const r = route;
|
324 | routeStr += `└ headers:\n`;
|
325 | for(let i = 0; i < r.headers.length; i++){
|
326 | const header = r.headers[i];
|
327 | const last = i === headers.length - 1;
|
328 | routeStr += ` ${last ? '└' : '├'} ${header.key}: ${header.value}\n`;
|
329 | }
|
330 | }
|
331 | return routeStr;
|
332 | }).join('\n');
|
333 | console.log(routesStr, '\n');
|
334 | };
|
335 | if (redirects.length) {
|
336 | printRoutes(redirects, 'Redirects');
|
337 | }
|
338 | if (headers.length) {
|
339 | printRoutes(headers, 'Headers');
|
340 | }
|
341 | const combinedRewrites = [
|
342 | ...rewrites.beforeFiles,
|
343 | ...rewrites.afterFiles,
|
344 | ...rewrites.fallback,
|
345 | ];
|
346 | if (combinedRewrites.length) {
|
347 | printRoutes(combinedRewrites, 'Rewrites');
|
348 | }
|
349 | }
|
350 | let cachedBuildManifest;
|
351 | let lastCompute;
|
352 | let lastComputePageInfo;
|
353 | async function computeFromManifest(manifest, distPath, gzipSize = true, pageInfos) {
|
354 | if (Object.is(cachedBuildManifest, manifest) && lastComputePageInfo === !!pageInfos) {
|
355 | return lastCompute;
|
356 | }
|
357 | let expected = 0;
|
358 | const files = new Map();
|
359 | Object.keys(manifest.pages).forEach((key)=>{
|
360 | if (pageInfos) {
|
361 | const pageInfo = pageInfos.get(key);
|
362 |
|
363 |
|
364 | if (pageInfo === null || pageInfo === void 0 ? void 0 : pageInfo.isHybridAmp) {
|
365 | return;
|
366 | }
|
367 | }
|
368 | ++expected;
|
369 | manifest.pages[key].forEach((file)=>{
|
370 | if (key === '/_app') {
|
371 | files.set(file, Infinity);
|
372 | } else if (files.has(file)) {
|
373 | files.set(file, files.get(file) + 1);
|
374 | } else {
|
375 | files.set(file, 1);
|
376 | }
|
377 | });
|
378 | });
|
379 | const getSize = gzipSize ? fsStatGzip : fsStat;
|
380 | const commonFiles = [
|
381 | ...files.entries()
|
382 | ].filter(([, len])=>len === expected || len === Infinity
|
383 | ).map(([f])=>f
|
384 | );
|
385 | const uniqueFiles = [
|
386 | ...files.entries()
|
387 | ].filter(([, len])=>len === 1
|
388 | ).map(([f])=>f
|
389 | );
|
390 | let stats;
|
391 | try {
|
392 | stats = await Promise.all(commonFiles.map(async (f)=>[
|
393 | f,
|
394 | await getSize(_path.default.join(distPath, f))
|
395 | ]
|
396 | ));
|
397 | } catch (_) {
|
398 | stats = [];
|
399 | }
|
400 | let uniqueStats;
|
401 | try {
|
402 | uniqueStats = await Promise.all(uniqueFiles.map(async (f)=>[
|
403 | f,
|
404 | await getSize(_path.default.join(distPath, f))
|
405 | ]
|
406 | ));
|
407 | } catch (_1) {
|
408 | uniqueStats = [];
|
409 | }
|
410 | lastCompute = {
|
411 | commonFiles,
|
412 | uniqueFiles,
|
413 | sizeUniqueFiles: uniqueStats.reduce((obj, n)=>Object.assign(obj, {
|
414 | [n[0]]: n[1]
|
415 | })
|
416 | , {}),
|
417 | sizeCommonFile: stats.reduce((obj, n)=>Object.assign(obj, {
|
418 | [n[0]]: n[1]
|
419 | })
|
420 | , {}),
|
421 | sizeCommonFiles: stats.reduce((size, [f, stat])=>{
|
422 | if (f.endsWith('.css')) return size;
|
423 | return size + stat;
|
424 | }, 0)
|
425 | };
|
426 | cachedBuildManifest = manifest;
|
427 | lastComputePageInfo = !!pageInfos;
|
428 | return lastCompute;
|
429 | }
|
430 | function difference(main, sub) {
|
431 | const a = new Set(main);
|
432 | const b = new Set(sub);
|
433 | return [
|
434 | ...a
|
435 | ].filter((x)=>!b.has(x)
|
436 | );
|
437 | }
|
438 | function intersect(main, sub) {
|
439 | const a = new Set(main);
|
440 | const b = new Set(sub);
|
441 | return [
|
442 | ...new Set([
|
443 | ...a
|
444 | ].filter((x)=>b.has(x)
|
445 | ))
|
446 | ];
|
447 | }
|
448 | function sum(a) {
|
449 | return a.reduce((size, stat)=>size + stat
|
450 | , 0);
|
451 | }
|
452 | async function getJsPageSizeInKb(page, distPath, buildManifest, gzipSize = true, computedManifestData) {
|
453 | const data = computedManifestData || await computeFromManifest(buildManifest, distPath, gzipSize);
|
454 | const fnFilterJs = (entry)=>entry.endsWith('.js')
|
455 | ;
|
456 | const pageFiles = (buildManifest.pages[(0, _normalizePagePath).denormalizePagePath(page)] || []).filter(fnFilterJs);
|
457 | const appFiles = (buildManifest.pages['/_app'] || []).filter(fnFilterJs);
|
458 | const fnMapRealPath = (dep)=>`${distPath}/${dep}`
|
459 | ;
|
460 | const allFilesReal = [
|
461 | ...new Set([
|
462 | ...pageFiles,
|
463 | ...appFiles
|
464 | ])
|
465 | ].map(fnMapRealPath);
|
466 | const selfFilesReal = difference(intersect(pageFiles, data.uniqueFiles), data.commonFiles).map(fnMapRealPath);
|
467 | const getSize = gzipSize ? fsStatGzip : fsStat;
|
468 | try {
|
469 |
|
470 |
|
471 | const allFilesSize = sum(await Promise.all(allFilesReal.map(getSize)));
|
472 | const selfFilesSize = sum(await Promise.all(selfFilesReal.map(getSize)));
|
473 | return [
|
474 | selfFilesSize,
|
475 | allFilesSize
|
476 | ];
|
477 | } catch (_) {}
|
478 | return [
|
479 | -1,
|
480 | -1
|
481 | ];
|
482 | }
|
483 | async function buildStaticPaths(page, getStaticPaths, configFileName, locales, defaultLocale) {
|
484 | const prerenderPaths = new Set();
|
485 | const encodedPrerenderPaths = new Set();
|
486 | const _routeRegex = (0, _utils).getRouteRegex(page);
|
487 | const _routeMatcher = (0, _utils).getRouteMatcher(_routeRegex);
|
488 |
|
489 | const _validParamKeys = Object.keys(_routeMatcher(page));
|
490 | const staticPathsResult = await getStaticPaths({
|
491 | locales,
|
492 | defaultLocale
|
493 | });
|
494 | const expectedReturnVal = `Expected: { paths: [], fallback: boolean }\n` + `See here for more info: https://nextjs.org/docs/messages/invalid-getstaticpaths-value`;
|
495 | if (!staticPathsResult || typeof staticPathsResult !== 'object' || Array.isArray(staticPathsResult)) {
|
496 | throw new Error(`Invalid value returned from getStaticPaths in ${page}. Received ${typeof staticPathsResult} ${expectedReturnVal}`);
|
497 | }
|
498 | const invalidStaticPathKeys = Object.keys(staticPathsResult).filter((key)=>!(key === 'paths' || key === 'fallback')
|
499 | );
|
500 | if (invalidStaticPathKeys.length > 0) {
|
501 | throw new Error(`Extra keys returned from getStaticPaths in ${page} (${invalidStaticPathKeys.join(', ')}) ${expectedReturnVal}`);
|
502 | }
|
503 | if (!(typeof staticPathsResult.fallback === 'boolean' || staticPathsResult.fallback === 'blocking')) {
|
504 | throw new Error(`The \`fallback\` key must be returned from getStaticPaths in ${page}.\n` + expectedReturnVal);
|
505 | }
|
506 | const toPrerender = staticPathsResult.paths;
|
507 | if (!Array.isArray(toPrerender)) {
|
508 | throw new Error(`Invalid \`paths\` value returned from getStaticPaths in ${page}.\n` + `\`paths\` must be an array of strings or objects of shape { params: [key: string]: string }`);
|
509 | }
|
510 | toPrerender.forEach((entry)=>{
|
511 |
|
512 |
|
513 | if (typeof entry === 'string') {
|
514 | entry = (0, _normalizeTrailingSlash).removePathTrailingSlash(entry);
|
515 | const localePathResult = (0, _normalizeLocalePath).normalizeLocalePath(entry, locales);
|
516 | let cleanedEntry = entry;
|
517 | if (localePathResult.detectedLocale) {
|
518 | cleanedEntry = entry.slice(localePathResult.detectedLocale.length + 1);
|
519 | } else if (defaultLocale) {
|
520 | entry = `/${defaultLocale}${entry}`;
|
521 | }
|
522 | const result = _routeMatcher(cleanedEntry);
|
523 | if (!result) {
|
524 | throw new Error(`The provided path \`${cleanedEntry}\` does not match the page: \`${page}\`.`);
|
525 | }
|
526 |
|
527 |
|
528 |
|
529 | prerenderPaths.add(entry.split('/').map((segment)=>(0, _escapePathDelimiters).default(decodeURIComponent(segment), true)
|
530 | ).join('/'));
|
531 | encodedPrerenderPaths.add(entry);
|
532 | } else {
|
533 | const invalidKeys = Object.keys(entry).filter((key)=>key !== 'params' && key !== 'locale'
|
534 | );
|
535 | if (invalidKeys.length) {
|
536 | throw new Error(`Additional keys were returned from \`getStaticPaths\` in page "${page}". ` + `URL Parameters intended for this dynamic route must be nested under the \`params\` key, i.e.:` + `\n\n\treturn { params: { ${_validParamKeys.map((k)=>`${k}: ...`
|
537 | ).join(', ')} } }` + `\n\nKeys that need to be moved: ${invalidKeys.join(', ')}.\n`);
|
538 | }
|
539 | const { params ={} } = entry;
|
540 | let builtPage = page;
|
541 | let encodedBuiltPage = page;
|
542 | _validParamKeys.forEach((validParamKey)=>{
|
543 | const { repeat , optional } = _routeRegex.groups[validParamKey];
|
544 | let paramValue = params[validParamKey];
|
545 | if (optional && params.hasOwnProperty(validParamKey) && (paramValue === null || paramValue === undefined || paramValue === false)) {
|
546 | paramValue = [];
|
547 | }
|
548 | if (repeat && !Array.isArray(paramValue) || !repeat && typeof paramValue !== 'string') {
|
549 | throw new Error(`A required parameter (${validParamKey}) was not provided as ${repeat ? 'an array' : 'a string'} in getStaticPaths for ${page}`);
|
550 | }
|
551 | let replaced = `[${repeat ? '...' : ''}${validParamKey}]`;
|
552 | if (optional) {
|
553 | replaced = `[${replaced}]`;
|
554 | }
|
555 | builtPage = builtPage.replace(replaced, repeat ? paramValue.map((segment)=>(0, _escapePathDelimiters).default(segment, true)
|
556 | ).join('/') : (0, _escapePathDelimiters).default(paramValue, true)).replace(/(?!^)\/$/, '');
|
557 | encodedBuiltPage = encodedBuiltPage.replace(replaced, repeat ? paramValue.map(encodeURIComponent).join('/') : encodeURIComponent(paramValue)).replace(/(?!^)\/$/, '');
|
558 | });
|
559 | if (entry.locale && !(locales === null || locales === void 0 ? void 0 : locales.includes(entry.locale))) {
|
560 | throw new Error(`Invalid locale returned from getStaticPaths for ${page}, the locale ${entry.locale} is not specified in ${configFileName}`);
|
561 | }
|
562 | const curLocale = entry.locale || defaultLocale || '';
|
563 | prerenderPaths.add(`${curLocale ? `/${curLocale}` : ''}${curLocale && builtPage === '/' ? '' : builtPage}`);
|
564 | encodedPrerenderPaths.add(`${curLocale ? `/${curLocale}` : ''}${curLocale && encodedBuiltPage === '/' ? '' : encodedBuiltPage}`);
|
565 | }
|
566 | });
|
567 | return {
|
568 | paths: [
|
569 | ...prerenderPaths
|
570 | ],
|
571 | fallback: staticPathsResult.fallback,
|
572 | encodedPaths: [
|
573 | ...encodedPrerenderPaths
|
574 | ]
|
575 | };
|
576 | }
|
577 | async function isPageStatic(page, distDir, serverless, configFileName, runtimeEnvConfig, httpAgentOptions, locales, defaultLocale, parentId) {
|
578 | const isPageStaticSpan = (0, _trace).trace('is-page-static-utils', parentId);
|
579 | return isPageStaticSpan.traceAsyncFn(async ()=>{
|
580 | try {
|
581 | require('../shared/lib/runtime-config').setConfig(runtimeEnvConfig);
|
582 | (0, _config).setHttpAgentOptions(httpAgentOptions);
|
583 | const mod = await (0, _loadComponents).loadComponents(distDir, page, serverless);
|
584 | const Comp = mod.Component;
|
585 | if (!Comp || !(0, _reactIs).isValidElementType(Comp) || typeof Comp === 'string') {
|
586 | throw new Error('INVALID_DEFAULT_EXPORT');
|
587 | }
|
588 | const hasFlightData = !!mod.__next_rsc__;
|
589 | const hasGetInitialProps = !!Comp.getInitialProps;
|
590 | const hasStaticProps = !!mod.getStaticProps;
|
591 | const hasStaticPaths = !!mod.getStaticPaths;
|
592 | const hasServerProps = !!mod.getServerSideProps;
|
593 | const hasLegacyServerProps = !!await mod.ComponentMod.unstable_getServerProps;
|
594 | const hasLegacyStaticProps = !!await mod.ComponentMod.unstable_getStaticProps;
|
595 | const hasLegacyStaticPaths = !!await mod.ComponentMod.unstable_getStaticPaths;
|
596 | const hasLegacyStaticParams = !!await mod.ComponentMod.unstable_getStaticParams;
|
597 | if (hasLegacyStaticParams) {
|
598 | throw new Error(`unstable_getStaticParams was replaced with getStaticPaths. Please update your code.`);
|
599 | }
|
600 | if (hasLegacyStaticPaths) {
|
601 | throw new Error(`unstable_getStaticPaths was replaced with getStaticPaths. Please update your code.`);
|
602 | }
|
603 | if (hasLegacyStaticProps) {
|
604 | throw new Error(`unstable_getStaticProps was replaced with getStaticProps. Please update your code.`);
|
605 | }
|
606 | if (hasLegacyServerProps) {
|
607 | throw new Error(`unstable_getServerProps was replaced with getServerSideProps. Please update your code.`);
|
608 | }
|
609 |
|
610 |
|
611 | if (hasGetInitialProps && hasStaticProps) {
|
612 | throw new Error(_constants.SSG_GET_INITIAL_PROPS_CONFLICT);
|
613 | }
|
614 | if (hasGetInitialProps && hasServerProps) {
|
615 | throw new Error(_constants.SERVER_PROPS_GET_INIT_PROPS_CONFLICT);
|
616 | }
|
617 | if (hasStaticProps && hasServerProps) {
|
618 | throw new Error(_constants.SERVER_PROPS_SSG_CONFLICT);
|
619 | }
|
620 | const pageIsDynamic = (0, _isDynamic).isDynamicRoute(page);
|
621 |
|
622 | if (hasStaticProps && hasStaticPaths && !pageIsDynamic) {
|
623 | throw new Error(`getStaticPaths can only be used with dynamic pages, not '${page}'.` + `\nLearn more: https://nextjs.org/docs/routing/dynamic-routes`);
|
624 | }
|
625 | if (hasStaticProps && pageIsDynamic && !hasStaticPaths) {
|
626 | throw new Error(`getStaticPaths is required for dynamic SSG pages and is missing for '${page}'.` + `\nRead more: https://nextjs.org/docs/messages/invalid-getstaticpaths-value`);
|
627 | }
|
628 | let prerenderRoutes;
|
629 | let encodedPrerenderRoutes;
|
630 | let prerenderFallback;
|
631 | if (hasStaticProps && hasStaticPaths) {
|
632 | ({ paths: prerenderRoutes , fallback: prerenderFallback , encodedPaths: encodedPrerenderRoutes , } = await buildStaticPaths(page, mod.getStaticPaths, configFileName, locales, defaultLocale));
|
633 | }
|
634 | const isNextImageImported = global.__NEXT_IMAGE_IMPORTED;
|
635 | const config = mod.pageConfig;
|
636 | return {
|
637 | isStatic: !hasStaticProps && !hasGetInitialProps && !hasServerProps && !hasFlightData,
|
638 | isHybridAmp: config.amp === 'hybrid',
|
639 | isAmpOnly: config.amp === true,
|
640 | prerenderRoutes,
|
641 | prerenderFallback,
|
642 | encodedPrerenderRoutes,
|
643 | hasStaticProps,
|
644 | hasServerProps,
|
645 | hasFlightData,
|
646 | isNextImageImported,
|
647 | traceIncludes: config.unstable_includeFiles || [],
|
648 | traceExcludes: config.unstable_excludeFiles || []
|
649 | };
|
650 | } catch (err) {
|
651 | if ((0, _isError).default(err) && err.code === 'MODULE_NOT_FOUND') return {};
|
652 | throw err;
|
653 | }
|
654 | });
|
655 | }
|
656 | async function hasCustomGetInitialProps(page, distDir, isLikeServerless, runtimeEnvConfig, checkingApp) {
|
657 | require('../shared/lib/runtime-config').setConfig(runtimeEnvConfig);
|
658 | const components = await (0, _loadComponents).loadComponents(distDir, page, isLikeServerless);
|
659 | let mod = components.ComponentMod;
|
660 | if (checkingApp) {
|
661 | mod = await mod._app || mod.default || mod;
|
662 | } else {
|
663 | mod = mod.default || mod;
|
664 | }
|
665 | mod = await mod;
|
666 | return mod.getInitialProps !== mod.origGetInitialProps;
|
667 | }
|
668 | async function getNamedExports(page, distDir, isLikeServerless, runtimeEnvConfig) {
|
669 | require('../shared/lib/runtime-config').setConfig(runtimeEnvConfig);
|
670 | const components = await (0, _loadComponents).loadComponents(distDir, page, isLikeServerless);
|
671 | let mod = components.ComponentMod;
|
672 | return Object.keys(mod);
|
673 | }
|
674 | function detectConflictingPaths(combinedPages, ssgPages, additionalSsgPaths) {
|
675 | const conflictingPaths = new Map();
|
676 | const dynamicSsgPages = [
|
677 | ...ssgPages
|
678 | ].filter((page)=>(0, _isDynamic).isDynamicRoute(page)
|
679 | );
|
680 | additionalSsgPaths.forEach((paths, pathsPage)=>{
|
681 | paths.forEach((curPath)=>{
|
682 | const lowerPath = curPath.toLowerCase();
|
683 | let conflictingPage = combinedPages.find((page)=>page.toLowerCase() === lowerPath
|
684 | );
|
685 | if (conflictingPage) {
|
686 | conflictingPaths.set(lowerPath, [
|
687 | {
|
688 | path: curPath,
|
689 | page: pathsPage
|
690 | },
|
691 | {
|
692 | path: conflictingPage,
|
693 | page: conflictingPage
|
694 | },
|
695 | ]);
|
696 | } else {
|
697 | let conflictingPath;
|
698 | conflictingPage = dynamicSsgPages.find((page)=>{
|
699 | var ref;
|
700 | if (page === pathsPage) return false;
|
701 | conflictingPath = (ref = additionalSsgPaths.get(page)) === null || ref === void 0 ? void 0 : ref.find((compPath)=>compPath.toLowerCase() === lowerPath
|
702 | );
|
703 | return conflictingPath;
|
704 | });
|
705 | if (conflictingPage && conflictingPath) {
|
706 | conflictingPaths.set(lowerPath, [
|
707 | {
|
708 | path: curPath,
|
709 | page: pathsPage
|
710 | },
|
711 | {
|
712 | path: conflictingPath,
|
713 | page: conflictingPage
|
714 | },
|
715 | ]);
|
716 | }
|
717 | }
|
718 | });
|
719 | });
|
720 | if (conflictingPaths.size > 0) {
|
721 | let conflictingPathsOutput = '';
|
722 | conflictingPaths.forEach((pathItems)=>{
|
723 | pathItems.forEach((pathItem, idx)=>{
|
724 | const isDynamic = pathItem.page !== pathItem.path;
|
725 | if (idx > 0) {
|
726 | conflictingPathsOutput += 'conflicts with ';
|
727 | }
|
728 | conflictingPathsOutput += `path: "${pathItem.path}"${isDynamic ? ` from page: "${pathItem.page}" ` : ' '}`;
|
729 | });
|
730 | conflictingPathsOutput += '\n';
|
731 | });
|
732 | Log.error('Conflicting paths returned from getStaticPaths, paths must be unique per page.\n' + 'See more info here: https://nextjs.org/docs/messages/conflicting-ssg-paths\n\n' + conflictingPathsOutput);
|
733 | process.exit(1);
|
734 | }
|
735 | }
|
736 | function getRawPageExtensions(pageExtensions) {
|
737 | return pageExtensions.filter((ext)=>!ext.startsWith('client.') && !ext.startsWith('server.')
|
738 | );
|
739 | }
|
740 | function isFlightPage(nextConfig, filePath) {
|
741 | if (!nextConfig.experimental.serverComponents) {
|
742 | return false;
|
743 | }
|
744 | const rawPageExtensions = getRawPageExtensions(nextConfig.pageExtensions || []);
|
745 | return rawPageExtensions.some((ext)=>{
|
746 | return filePath.endsWith(`.server.${ext}`);
|
747 | });
|
748 | }
|
749 | function getUnresolvedModuleFromError(error) {
|
750 | const moduleErrorRegex = new RegExp(`Module not found: Can't resolve '(\\w+)'`);
|
751 | const [, moduleName] = error.match(moduleErrorRegex) || [];
|
752 | return builtinModules.find((item)=>item === moduleName
|
753 | );
|
754 | }
|
755 | async function copyTracedFiles(dir, distDir, pageKeys, tracingRoot, serverConfig, middlewareManifest) {
|
756 | const outputPath = _path.default.join(distDir, 'standalone');
|
757 | const copiedFiles = new Set();
|
758 | await (0, _recursiveDelete).recursiveDelete(outputPath);
|
759 | async function handleTraceFiles(traceFilePath) {
|
760 | const traceData = JSON.parse(await _fs.promises.readFile(traceFilePath, 'utf8'));
|
761 | const copySema = new _asyncSema.Sema(10, {
|
762 | capacity: traceData.files.length
|
763 | });
|
764 | const traceFileDir = _path.default.dirname(traceFilePath);
|
765 | await Promise.all(traceData.files.map(async (relativeFile)=>{
|
766 | await copySema.acquire();
|
767 | const tracedFilePath = _path.default.join(traceFileDir, relativeFile);
|
768 | const fileOutputPath = _path.default.join(outputPath, _path.default.relative(tracingRoot, tracedFilePath));
|
769 | if (!copiedFiles.has(fileOutputPath)) {
|
770 | copiedFiles.add(fileOutputPath);
|
771 | await _fs.promises.mkdir(_path.default.dirname(fileOutputPath), {
|
772 | recursive: true
|
773 | });
|
774 | const symlink = await _fs.promises.readlink(tracedFilePath).catch(()=>null
|
775 | );
|
776 | if (symlink) {
|
777 | console.log('symlink', _path.default.relative(tracingRoot, symlink));
|
778 | await _fs.promises.symlink(_path.default.relative(tracingRoot, symlink), fileOutputPath);
|
779 | } else {
|
780 | await _fs.promises.copyFile(tracedFilePath, fileOutputPath);
|
781 | }
|
782 | }
|
783 | await copySema.release();
|
784 | }));
|
785 | }
|
786 | for (const page of pageKeys){
|
787 | if (_constants.MIDDLEWARE_ROUTE.test(page)) {
|
788 | const { files } = middlewareManifest.middleware[page.replace(/\/_middleware$/, '') || '/'];
|
789 | for (const file of files){
|
790 | const originalPath = _path.default.join(distDir, file);
|
791 | const fileOutputPath = _path.default.join(outputPath, _path.default.relative(tracingRoot, distDir), file);
|
792 | await _fs.promises.mkdir(_path.default.dirname(fileOutputPath), {
|
793 | recursive: true
|
794 | });
|
795 | await _fs.promises.copyFile(originalPath, fileOutputPath);
|
796 | }
|
797 | continue;
|
798 | }
|
799 | const pageFile = _path.default.join(distDir, 'server', 'pages', `${(0, _normalizePagePath).normalizePagePath(page)}.js`);
|
800 | const pageTraceFile = `${pageFile}.nft.json`;
|
801 | await handleTraceFiles(pageTraceFile);
|
802 | }
|
803 | await handleTraceFiles(_path.default.join(distDir, 'next-server.js.nft.json'));
|
804 | const serverOutputPath = _path.default.join(outputPath, _path.default.relative(tracingRoot, dir), 'server.js');
|
805 | await _fs.promises.writeFile(serverOutputPath, `
|
806 | process.env.NODE_ENV = 'production'
|
807 | process.chdir(__dirname)
|
808 | const NextServer = require('next/dist/server/next-server').default
|
809 | const http = require('http')
|
810 | const path = require('path')
|
811 |
|
812 | // Make sure commands gracefully respect termination signals (e.g. from Docker)
|
813 | process.on('SIGTERM', () => process.exit(0))
|
814 | process.on('SIGINT', () => process.exit(0))
|
815 |
|
816 | let handler
|
817 |
|
818 | const server = http.createServer(async (req, res) => {
|
819 | try {
|
820 | await handler(req, res)
|
821 | } catch (err) {
|
822 | console.error(err);
|
823 | res.statusCode = 500
|
824 | res.end('internal server error')
|
825 | }
|
826 | })
|
827 | const currentPort = parseInt(process.env.PORT, 10) || 3000
|
828 |
|
829 | server.listen(currentPort, (err) => {
|
830 | if (err) {
|
831 | console.error("Failed to start server", err)
|
832 | process.exit(1)
|
833 | }
|
834 | const addr = server.address()
|
835 | const nextServer = new NextServer({
|
836 | hostname: 'localhost',
|
837 | port: currentPort,
|
838 | dir: path.join(__dirname),
|
839 | dev: false,
|
840 | conf: ${JSON.stringify({
|
841 | ...serverConfig,
|
842 | distDir: `./${_path.default.relative(dir, distDir)}`
|
843 | })},
|
844 | })
|
845 | handler = nextServer.getRequestHandler()
|
846 |
|
847 | console.log("Listening on port", currentPort)
|
848 | })
|
849 | `);
|
850 | }
|
851 | function isReservedPage(page) {
|
852 | return RESERVED_PAGE.test(page);
|
853 | }
|
854 | function isCustomErrorPage(page) {
|
855 | return page === '/404' || page === '/500';
|
856 | }
|
857 |
|
858 |
|
\ | No newline at end of file |