UNPKG

next

Version:

The React Framework

819 lines (818 loc) • 91.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = build; var _env = require("@next/env"); var _chalk = _interopRequireDefault(require("next/dist/compiled/chalk")); var _crypto = _interopRequireDefault(require("crypto")); var _micromatch = require("next/dist/compiled/micromatch"); var _fs = require("fs"); var _jestWorker = require("next/dist/compiled/jest-worker"); var _worker = require("../lib/worker"); var _devalue = _interopRequireDefault(require("next/dist/compiled/devalue")); var _escapeRegexp = require("../shared/lib/escape-regexp"); var _findUp = _interopRequireDefault(require("next/dist/compiled/find-up")); var _indexCjs = require("next/dist/compiled/nanoid/index.cjs"); var _pathToRegexp = require("next/dist/compiled/path-to-regexp"); var _path = _interopRequireWildcard(require("path")); var _formatWebpackMessages = _interopRequireDefault(require("../client/dev/error-overlay/format-webpack-messages")); var _constants = require("../lib/constants"); var _fileExists = require("../lib/file-exists"); var _findPagesDir = require("../lib/find-pages-dir"); var _loadCustomRoutes = _interopRequireWildcard(require("../lib/load-custom-routes")); var _redirectStatus = require("../lib/redirect-status"); var _nonNullable = require("../lib/non-nullable"); var _recursiveDelete = require("../lib/recursive-delete"); var _verifyAndLint = require("../lib/verifyAndLint"); var _verifyPartytownSetup = require("../lib/verify-partytown-setup"); var _constants1 = require("../shared/lib/constants"); var _utils = require("../shared/lib/router/utils"); var _config = _interopRequireDefault(require("../server/config")); var _utils1 = require("../server/utils"); var _normalizePagePath = require("../shared/lib/page-path/normalize-page-path"); var _require = require("../server/require"); var ciEnvironment = _interopRequireWildcard(require("../telemetry/ci-info")); var _events = require("../telemetry/events"); var _storage = require("../telemetry/storage"); var _compiler = require("./compiler"); var _getPageStaticInfo = require("./analysis/get-page-static-info"); var _entries = require("./entries"); var _generateBuildId = require("./generate-build-id"); var _isWriteable = require("./is-writeable"); var Log = _interopRequireWildcard(require("./output/log")); var _spinner = _interopRequireDefault(require("./spinner")); var _trace = require("../trace"); var _utils2 = require("./utils"); var _webpackConfig = _interopRequireDefault(require("./webpack-config")); var _writeBuildId = require("./write-build-id"); var _normalizeLocalePath = require("../shared/lib/i18n/normalize-locale-path"); var _isError = _interopRequireDefault(require("../lib/is-error")); var _telemetryPlugin = require("./webpack/plugins/telemetry-plugin"); var _recursiveCopy = require("../lib/recursive-copy"); var _recursiveReaddir = require("../lib/recursive-readdir"); var _swc = require("./swc"); var _flightClientEntryPlugin = require("./webpack/plugins/flight-client-entry-plugin"); var _routeRegex = require("../shared/lib/router/utils/route-regex"); var _flatReaddir = require("../lib/flat-readdir"); var _swcPlugins = require("../telemetry/events/swc-plugins"); var _appPaths = require("../shared/lib/router/utils/app-paths"); async function build(dir, conf = null, reactProductionProfiling = false, debugOutput = false, runLint = true) { try { const nextBuildSpan = (0, _trace).trace("next-build", undefined, { version: "12.2.6" }); const buildResult = await nextBuildSpan.traceAsyncFn(async ()=>{ var ref8, ref1, ref2; // attempt to load global env values so they are available in next.config.js const { loadedEnvFiles } = nextBuildSpan.traceChild("load-dotenv").traceFn(()=>(0, _env).loadEnvConfig(dir, false, Log)); const config = await nextBuildSpan.traceChild("load-next-config").traceAsyncFn(()=>(0, _config).default(_constants1.PHASE_PRODUCTION_BUILD, dir, conf)); const distDir = _path.default.join(dir, config.distDir); (0, _trace).setGlobal("phase", _constants1.PHASE_PRODUCTION_BUILD); (0, _trace).setGlobal("distDir", distDir); // We enable concurrent features (Fizz-related rendering architecture) when // using React 18 or experimental. const hasReactRoot = !!process.env.__NEXT_REACT_ROOT; const hasServerComponents = hasReactRoot && !!config.experimental.serverComponents; const { target } = config; const buildId = await nextBuildSpan.traceChild("generate-buildid").traceAsyncFn(()=>(0, _generateBuildId).generateBuildId(config.generateBuildId, _indexCjs.nanoid)); const customRoutes = await nextBuildSpan.traceChild("load-custom-routes").traceAsyncFn(()=>(0, _loadCustomRoutes).default(config)); const { headers , rewrites , redirects } = customRoutes; const cacheDir = _path.default.join(distDir, "cache"); if (ciEnvironment.isCI && !ciEnvironment.hasNextSupport) { const hasCache = await (0, _fileExists).fileExists(cacheDir); if (!hasCache) { // Intentionally not piping to stderr in case people fail in CI when // stderr is detected. console.log(`${Log.prefixes.warn} No build cache found. Please configure build caching for faster rebuilds. Read more: https://nextjs.org/docs/messages/no-cache`); } } const telemetry = new _storage.Telemetry({ distDir }); (0, _trace).setGlobal("telemetry", telemetry); const publicDir = _path.default.join(dir, "public"); const { pages: pagesDir , appDir } = (0, _findPagesDir).findPagesDir(dir, config.experimental.appDir); const hasPublicDir = await (0, _fileExists).fileExists(publicDir); telemetry.record((0, _events).eventCliSession(dir, config, { webpackVersion: 5, cliCommand: "build", isSrcDir: _path.default.relative(dir, pagesDir).startsWith("src"), hasNowJson: !!await (0, _findUp).default("now.json", { cwd: dir }), isCustomServer: null })); (0, _events).eventNextPlugins(_path.default.resolve(dir)).then((events)=>telemetry.record(events)); (0, _swcPlugins).eventSwcPlugins(_path.default.resolve(dir), config).then((events)=>telemetry.record(events)); const ignoreTypeScriptErrors = Boolean(config.typescript.ignoreBuildErrors); const ignoreESLint = Boolean(config.eslint.ignoreDuringBuilds); const eslintCacheDir = _path.default.join(cacheDir, "eslint/"); const shouldLint = !ignoreESLint && runLint; if (ignoreTypeScriptErrors) { Log.info("Skipping validation of types"); } if (runLint && ignoreESLint) { // only print log when build requre lint while ignoreESLint is enabled Log.info("Skipping linting"); } let typeCheckingAndLintingSpinnerPrefixText; let typeCheckingAndLintingSpinner; if (!ignoreTypeScriptErrors && shouldLint) { typeCheckingAndLintingSpinnerPrefixText = "Linting and checking validity of types"; } else if (!ignoreTypeScriptErrors) { typeCheckingAndLintingSpinnerPrefixText = "Checking validity of types"; } else if (shouldLint) { typeCheckingAndLintingSpinnerPrefixText = "Linting"; } // we will not create a spinner if both ignoreTypeScriptErrors and ignoreESLint are // enabled, but we will still verifying project's tsconfig and dependencies. if (typeCheckingAndLintingSpinnerPrefixText) { typeCheckingAndLintingSpinner = (0, _spinner).default({ prefixText: `${Log.prefixes.info} ${typeCheckingAndLintingSpinnerPrefixText}` }); } const typeCheckStart = process.hrtime(); const [[verifyResult, typeCheckEnd]] = await Promise.all([ nextBuildSpan.traceChild("verify-typescript-setup").traceAsyncFn(()=>verifyTypeScriptSetup(dir, [ pagesDir, appDir ].filter(Boolean), !ignoreTypeScriptErrors, config.typescript.tsconfigPath, config.images.disableStaticImages, cacheDir, config.experimental.cpus, config.experimental.workerThreads).then((resolved)=>{ const checkEnd = process.hrtime(typeCheckStart); return [ resolved, checkEnd ]; })), shouldLint && nextBuildSpan.traceChild("verify-and-lint").traceAsyncFn(async ()=>{ var ref; await (0, _verifyAndLint).verifyAndLint(dir, eslintCacheDir, (ref = config.eslint) == null ? void 0 : ref.dirs, config.experimental.cpus, config.experimental.workerThreads, telemetry); }), ]); typeCheckingAndLintingSpinner == null ? void 0 : typeCheckingAndLintingSpinner.stopAndPersist(); if (!ignoreTypeScriptErrors && verifyResult) { var ref3, ref4, ref5; telemetry.record((0, _events).eventTypeCheckCompleted({ durationInSeconds: typeCheckEnd[0], typescriptVersion: verifyResult.version, inputFilesCount: (ref3 = verifyResult.result) == null ? void 0 : ref3.inputFilesCount, totalFilesCount: (ref4 = verifyResult.result) == null ? void 0 : ref4.totalFilesCount, incremental: (ref5 = verifyResult.result) == null ? void 0 : ref5.incremental })); } const buildLintEvent = { featureName: "build-lint", invocationCount: shouldLint ? 1 : 0 }; telemetry.record({ eventName: _events.EVENT_BUILD_FEATURE_USAGE, payload: buildLintEvent }); const buildSpinner = (0, _spinner).default({ prefixText: `${Log.prefixes.info} Creating an optimized production build` }); const isLikeServerless = (0, _utils1).isTargetLikeServerless(target); const pagesPaths = await nextBuildSpan.traceChild("collect-pages").traceAsyncFn(()=>(0, _recursiveReaddir).recursiveReadDir(pagesDir, new RegExp(`\\.(?:${config.pageExtensions.join("|")})$`))); let appPaths; if (appDir) { appPaths = await nextBuildSpan.traceChild("collect-app-paths").traceAsyncFn(()=>(0, _recursiveReaddir).recursiveReadDir(appDir, new RegExp(`page\\.(?:${config.pageExtensions.join("|")})$`))); } const middlewareDetectionRegExp = new RegExp(`^${_constants.MIDDLEWARE_FILENAME}\\.(?:${config.pageExtensions.join("|")})$`); const rootPaths = (await (0, _flatReaddir).flatReaddir((0, _path).join(pagesDir, ".."), middlewareDetectionRegExp)).map((absoluteFile)=>absoluteFile.replace(dir, "")); // needed for static exporting since we want to replace with HTML // files const allStaticPages = new Set(); let allPageInfos = new Map(); const previewProps = { previewModeId: _crypto.default.randomBytes(16).toString("hex"), previewModeSigningKey: _crypto.default.randomBytes(32).toString("hex"), previewModeEncryptionKey: _crypto.default.randomBytes(32).toString("hex") }; const mappedPages = nextBuildSpan.traceChild("create-pages-mapping").traceFn(()=>(0, _entries).createPagesMapping({ hasServerComponents, isDev: false, pageExtensions: config.pageExtensions, pagesType: "pages", pagePaths: pagesPaths })); let mappedAppPages; if (appPaths && appDir) { mappedAppPages = nextBuildSpan.traceChild("create-app-mapping").traceFn(()=>(0, _entries).createPagesMapping({ pagePaths: appPaths, hasServerComponents, isDev: false, pagesType: "app", pageExtensions: config.pageExtensions })); } let mappedRootPaths = {}; if (rootPaths.length > 0) { mappedRootPaths = (0, _entries).createPagesMapping({ hasServerComponents, isDev: false, pageExtensions: config.pageExtensions, pagePaths: rootPaths, pagesType: "root" }); } const entrypoints = await nextBuildSpan.traceChild("create-entrypoints").traceAsyncFn(()=>(0, _entries).createEntrypoints({ buildId, config, envFiles: loadedEnvFiles, isDev: false, pages: mappedPages, pagesDir, previewMode: previewProps, target, rootDir: dir, rootPaths: mappedRootPaths, appDir, appPaths: mappedAppPages, pageExtensions: config.pageExtensions })); const pageKeys = { pages: Object.keys(mappedPages), app: mappedAppPages ? Object.keys(mappedAppPages).map((key)=>(0, _appPaths).normalizeAppPath(key)) : undefined }; const conflictingPublicFiles = []; const hasPages404 = (ref8 = mappedPages["/404"]) == null ? void 0 : ref8.startsWith(_constants.PAGES_DIR_ALIAS); const hasCustomErrorPage = mappedPages["/_error"].startsWith(_constants.PAGES_DIR_ALIAS); if (hasPublicDir) { const hasPublicUnderScoreNextDir = await (0, _fileExists).fileExists(_path.default.join(publicDir, "_next")); if (hasPublicUnderScoreNextDir) { throw new Error(_constants.PUBLIC_DIR_MIDDLEWARE_CONFLICT); } } await nextBuildSpan.traceChild("public-dir-conflict-check").traceAsyncFn(async ()=>{ // Check if pages conflict with files in `public` // Only a page of public file can be served, not both. for(const page in mappedPages){ const hasPublicPageFile = await (0, _fileExists).fileExists(_path.default.join(publicDir, page === "/" ? "/index" : page), "file"); if (hasPublicPageFile) { conflictingPublicFiles.push(page); } } const numConflicting = conflictingPublicFiles.length; if (numConflicting) { throw new Error(`Conflicting public and page file${numConflicting === 1 ? " was" : "s were"} found. https://nextjs.org/docs/messages/conflicting-public-file-page\n${conflictingPublicFiles.join("\n")}`); } }); const nestedReservedPages = pageKeys.pages.filter((page)=>{ return page.match(/\/(_app|_document|_error)$/) && _path.default.dirname(page) !== "/"; }); if (nestedReservedPages.length) { Log.warn(`The following reserved Next.js pages were detected not directly under the pages directory:\n` + nestedReservedPages.join("\n") + `\nSee more info here: https://nextjs.org/docs/messages/nested-reserved-page\n`); } const restrictedRedirectPaths = [ "/_next" ].map((p)=>config.basePath ? `${config.basePath}${p}` : p); const buildCustomRoute = (r, type)=>{ const keys = []; const routeRegex = (0, _pathToRegexp).pathToRegexp(r.source, keys, { strict: true, sensitive: false, delimiter: "/" }); let regexSource = routeRegex.source; if (!r.internal) { regexSource = (0, _redirectStatus).modifyRouteRegex(routeRegex.source, type === "redirect" ? restrictedRedirectPaths : undefined); } return { ...r, ...type === "redirect" ? { statusCode: (0, _redirectStatus).getRedirectStatus(r), permanent: undefined } : {}, regex: (0, _loadCustomRoutes).normalizeRouteRegex(regexSource) }; }; const routesManifestPath = _path.default.join(distDir, _constants1.ROUTES_MANIFEST); const routesManifest = nextBuildSpan.traceChild("generate-routes-manifest").traceFn(()=>{ var _app; const sortedRoutes = (0, _utils).getSortedRoutes([ ...pageKeys.pages, ...(_app = pageKeys.app) != null ? _app : [], ]); const dynamicRoutes = []; const staticRoutes = []; for (const route of sortedRoutes){ if ((0, _utils).isDynamicRoute(route)) { dynamicRoutes.push(pageToRoute(route)); } else if (!(0, _utils2).isReservedPage(route)) { staticRoutes.push(pageToRoute(route)); } } return { version: 3, pages404: true, basePath: config.basePath, redirects: redirects.map((r)=>buildCustomRoute(r, "redirect")), headers: headers.map((r)=>buildCustomRoute(r, "header")), dynamicRoutes, staticRoutes, dataRoutes: [], i18n: config.i18n || undefined }; }); if (rewrites.beforeFiles.length === 0 && rewrites.fallback.length === 0) { routesManifest.rewrites = rewrites.afterFiles.map((r)=>buildCustomRoute(r, "rewrite")); } else { routesManifest.rewrites = { beforeFiles: rewrites.beforeFiles.map((r)=>buildCustomRoute(r, "rewrite")), afterFiles: rewrites.afterFiles.map((r)=>buildCustomRoute(r, "rewrite")), fallback: rewrites.fallback.map((r)=>buildCustomRoute(r, "rewrite")) }; } const combinedRewrites = [ ...rewrites.beforeFiles, ...rewrites.afterFiles, ...rewrites.fallback, ]; const distDirCreated = await nextBuildSpan.traceChild("create-dist-dir").traceAsyncFn(async ()=>{ try { await _fs.promises.mkdir(distDir, { recursive: true }); return true; } catch (err) { if ((0, _isError).default(err) && err.code === "EPERM") { return false; } throw err; } }); if (!distDirCreated || !await (0, _isWriteable).isWriteable(distDir)) { throw new Error("> Build directory is not writeable. https://nextjs.org/docs/messages/build-dir-not-writeable"); } if (config.cleanDistDir) { await (0, _recursiveDelete).recursiveDelete(distDir, /^cache/); } // Ensure commonjs handling is used for files in the distDir (generally .next) // Files outside of the distDir can be "type": "module" await _fs.promises.writeFile(_path.default.join(distDir, "package.json"), '{"type": "commonjs"}'); // We need to write the manifest with rewrites before build // so serverless can import the manifest await nextBuildSpan.traceChild("write-routes-manifest").traceAsyncFn(()=>_fs.promises.writeFile(routesManifestPath, JSON.stringify(routesManifest), "utf8")); const serverDir = isLikeServerless ? _constants1.SERVERLESS_DIRECTORY : _constants1.SERVER_DIRECTORY; const manifestPath = _path.default.join(distDir, serverDir, _constants1.PAGES_MANIFEST); const requiredServerFiles = nextBuildSpan.traceChild("generate-required-server-files").traceFn(()=>({ version: 1, config: { ...config, configFile: undefined, experimental: { ...config.experimental, trustHostHeader: ciEnvironment.hasNextSupport } }, appDir: dir, files: [ _constants1.ROUTES_MANIFEST, _path.default.relative(distDir, manifestPath), _constants1.BUILD_MANIFEST, _constants1.PRERENDER_MANIFEST, _path.default.join(_constants1.SERVER_DIRECTORY, _constants1.MIDDLEWARE_MANIFEST), ...hasServerComponents ? [ _path.default.join(_constants1.SERVER_DIRECTORY, _constants1.FLIGHT_MANIFEST + ".js"), _path.default.join(_constants1.SERVER_DIRECTORY, _constants1.FLIGHT_MANIFEST + ".json"), ] : [], _constants1.REACT_LOADABLE_MANIFEST, config.optimizeFonts ? _path.default.join(serverDir, _constants1.FONT_MANIFEST) : null, _constants1.BUILD_ID_FILE, appDir ? _path.default.join(serverDir, _constants1.APP_PATHS_MANIFEST) : null, ].filter(_nonNullable.nonNullable).map((file)=>_path.default.join(config.distDir, file)), ignore: [] })); let result = { warnings: [], errors: [], stats: [] }; let webpackBuildStart; let telemetryPlugin; await (async ()=>{ var ref; // IIFE to isolate locals and avoid retaining memory too long const runWebpackSpan = nextBuildSpan.traceChild("run-webpack-compiler"); const commonWebpackOptions = { buildId, config, hasReactRoot, pagesDir, reactProductionProfiling, rewrites, runWebpackSpan, target, appDir, middlewareRegex: entrypoints.middlewareRegex }; const configs = await runWebpackSpan.traceChild("generate-webpack-config").traceAsyncFn(()=>Promise.all([ (0, _webpackConfig).default(dir, { ...commonWebpackOptions, compilerType: "client", entrypoints: entrypoints.client }), (0, _webpackConfig).default(dir, { ...commonWebpackOptions, compilerType: "server", entrypoints: entrypoints.server }), (0, _webpackConfig).default(dir, { ...commonWebpackOptions, compilerType: "edge-server", entrypoints: entrypoints.edgeServer }), ])); const clientConfig = configs[0]; if (clientConfig.optimization && (clientConfig.optimization.minimize !== true || clientConfig.optimization.minimizer && clientConfig.optimization.minimizer.length === 0)) { Log.warn(`Production code optimization has been disabled in your project. Read more: https://nextjs.org/docs/messages/minification-disabled`); } webpackBuildStart = process.hrtime(); // We run client and server compilation separately to optimize for memory usage await runWebpackSpan.traceAsyncFn(async ()=>{ // If we are under the serverless build, we will have to run the client // compiler first because the server compiler depends on the manifest // files that are created by the client compiler. // Otherwise, we run the server compilers first and then the client // compiler to track the boundary of server/client components. let clientResult = null; let serverResult = null; let edgeServerResult = null; if (isLikeServerless) { if (config.experimental.serverComponents) { throw new Error("Server Components are not supported in serverless mode."); } // Build client first clientResult = await (0, _compiler).runCompiler(clientConfig, { runWebpackSpan }); // Only continue if there were no errors if (!clientResult.errors.length) { serverResult = await (0, _compiler).runCompiler(configs[1], { runWebpackSpan }); edgeServerResult = configs[2] ? await (0, _compiler).runCompiler(configs[2], { runWebpackSpan }) : null; } } else { // During the server compilations, entries of client components will be // injected to this set and then will be consumed by the client compiler. _flightClientEntryPlugin.injectedClientEntries.clear(); serverResult = await (0, _compiler).runCompiler(configs[1], { runWebpackSpan }); edgeServerResult = configs[2] ? await (0, _compiler).runCompiler(configs[2], { runWebpackSpan }) : null; // Only continue if there were no errors if (!serverResult.errors.length && !(edgeServerResult == null ? void 0 : edgeServerResult.errors.length)) { _flightClientEntryPlugin.injectedClientEntries.forEach((value, key)=>{ clientConfig.entry[key] = value; }); clientResult = await (0, _compiler).runCompiler(clientConfig, { runWebpackSpan }); } } result = { warnings: [].concat(clientResult == null ? void 0 : clientResult.warnings, serverResult == null ? void 0 : serverResult.warnings, edgeServerResult == null ? void 0 : edgeServerResult.warnings).filter(_nonNullable.nonNullable), errors: [].concat(clientResult == null ? void 0 : clientResult.errors, serverResult == null ? void 0 : serverResult.errors, edgeServerResult == null ? void 0 : edgeServerResult.errors).filter(_nonNullable.nonNullable), stats: [ clientResult == null ? void 0 : clientResult.stats, serverResult == null ? void 0 : serverResult.stats, edgeServerResult == null ? void 0 : edgeServerResult.stats, ] }; }); result = nextBuildSpan.traceChild("format-webpack-messages").traceFn(()=>(0, _formatWebpackMessages).default(result, true)); telemetryPlugin = (ref = clientConfig.plugins) == null ? void 0 : ref.find(isTelemetryPlugin); })(); const webpackBuildEnd = process.hrtime(webpackBuildStart); if (buildSpinner) { buildSpinner.stopAndPersist(); } if (result.errors.length > 0) { // Only keep the first few errors. Others are often indicative // of the same problem, but confuse the reader with noise. if (result.errors.length > 5) { result.errors.length = 5; } let error = result.errors.filter(Boolean).join("\n\n"); console.error(_chalk.default.red("Failed to compile.\n")); if (error.indexOf("private-next-pages") > -1 && error.indexOf("does not contain a default export") > -1) { const page_name_regex = /'private-next-pages\/(?<page_name>[^']*)'/; const parsed = page_name_regex.exec(error); const page_name = parsed && parsed.groups && parsed.groups.page_name; throw new Error(`webpack build failed: found page without a React Component as default export in pages/${page_name}\n\nSee https://nextjs.org/docs/messages/page-without-valid-component for more info.`); } console.error(error); console.error(); if (error.indexOf("private-next-pages") > -1 || error.indexOf("__next_polyfill__") > -1) { const err = new Error("webpack config.resolve.alias was incorrectly overridden. https://nextjs.org/docs/messages/invalid-resolve-alias"); err.code = "INVALID_RESOLVE_ALIAS"; throw err; } const err = new Error("Build failed because of webpack errors"); err.code = "WEBPACK_ERRORS"; throw err; } else { telemetry.record((0, _events).eventBuildCompleted(pagesPaths, { durationInSeconds: webpackBuildEnd[0] })); if (result.warnings.length > 0) { Log.warn("Compiled with warnings\n"); console.warn(result.warnings.filter(Boolean).join("\n\n")); console.warn(); } else { Log.info("Compiled successfully"); } } const postCompileSpinner = (0, _spinner).default({ prefixText: `${Log.prefixes.info} Collecting page data` }); const buildManifestPath = _path.default.join(distDir, _constants1.BUILD_MANIFEST); const appBuildManifestPath = _path.default.join(distDir, _constants1.APP_BUILD_MANIFEST); const ssgPages = new Set(); const ssgStaticFallbackPages = new Set(); const ssgBlockingFallbackPages = new Set(); const staticPages = new Set(); const invalidPages = new Set(); const hybridAmpPages = new Set(); const serverPropsPages = new Set(); const additionalSsgPaths = new Map(); const additionalSsgPathsEncoded = new Map(); const pageTraceIncludes = new Map(); const pageTraceExcludes = new Map(); const pageInfos = new Map(); const pagesManifest = JSON.parse(await _fs.promises.readFile(manifestPath, "utf8")); const buildManifest = JSON.parse(await _fs.promises.readFile(buildManifestPath, "utf8")); const appBuildManifest = appDir ? JSON.parse(await _fs.promises.readFile(appBuildManifestPath, "utf8")) : undefined; const timeout = config.staticPageGenerationTimeout || 0; const sharedPool = config.experimental.sharedPool || false; const staticWorker = sharedPool ? require.resolve("./worker") : require.resolve("./utils"); let infoPrinted = false; process.env.NEXT_PHASE = _constants1.PHASE_PRODUCTION_BUILD; const staticWorkers = new _worker.Worker(staticWorker, { timeout: timeout * 1000, onRestart: (method, [arg], attempts)=>{ if (method === "exportPage") { const { path: pagePath } = arg; if (attempts >= 3) { throw new Error(`Static page generation for ${pagePath} is still timing out after 3 attempts. See more info here https://nextjs.org/docs/messages/static-page-generation-timeout`); } Log.warn(`Restarted static page generation for ${pagePath} because it took more than ${timeout} seconds`); } else { const pagePath = arg; if (attempts >= 2) { throw new Error(`Collecting page data for ${pagePath} is still timing out after 2 attempts. See more info here https://nextjs.org/docs/messages/page-data-collection-timeout`); } Log.warn(`Restarted collecting page data for ${pagePath} because it took more than ${timeout} seconds`); } if (!infoPrinted) { Log.warn("See more info here https://nextjs.org/docs/messages/static-page-generation-timeout"); infoPrinted = true; } }, numWorkers: config.experimental.cpus, enableWorkerThreads: config.experimental.workerThreads, exposedMethods: sharedPool ? [ "hasCustomGetInitialProps", "isPageStatic", "getNamedExports", "exportPage", ] : [ "hasCustomGetInitialProps", "isPageStatic", "getNamedExports" ] }); const analysisBegin = process.hrtime(); const staticCheckSpan = nextBuildSpan.traceChild("static-check"); const { customAppGetInitialProps , namedExports , isNextImageImported: isNextImageImported1 , hasSsrAmpPages: hasSsrAmpPages1 , hasNonStaticErrorPage , } = await staticCheckSpan.traceAsyncFn(async ()=>{ const { configFileName , publicRuntimeConfig , serverRuntimeConfig } = config; const runtimeEnvConfig = { publicRuntimeConfig, serverRuntimeConfig }; const nonStaticErrorPageSpan = staticCheckSpan.traceChild("check-static-error-page"); const errorPageHasCustomGetInitialProps = nonStaticErrorPageSpan.traceAsyncFn(async ()=>hasCustomErrorPage && await staticWorkers.hasCustomGetInitialProps("/_error", distDir, isLikeServerless, runtimeEnvConfig, false)); const errorPageStaticResult = nonStaticErrorPageSpan.traceAsyncFn(async ()=>{ var ref, ref9; return hasCustomErrorPage && staticWorkers.isPageStatic("/_error", distDir, isLikeServerless, configFileName, runtimeEnvConfig, config.httpAgentOptions, (ref = config.i18n) == null ? void 0 : ref.locales, (ref9 = config.i18n) == null ? void 0 : ref9.defaultLocale); }); // we don't output _app in serverless mode so use _app export // from _error instead const appPageToCheck = isLikeServerless ? "/_error" : "/_app"; const customAppGetInitialPropsPromise = staticWorkers.hasCustomGetInitialProps(appPageToCheck, distDir, isLikeServerless, runtimeEnvConfig, true); const namedExportsPromise = staticWorkers.getNamedExports(appPageToCheck, distDir, isLikeServerless, runtimeEnvConfig); // eslint-disable-next-line no-shadow let isNextImageImported; // eslint-disable-next-line no-shadow let hasSsrAmpPages = false; const computedManifestData = await (0, _utils2).computeFromManifest({ build: buildManifest, app: appBuildManifest }, distDir, config.experimental.gzipSize); await Promise.all(Object.entries(pageKeys).reduce((acc, [key, files])=>{ if (!files) { return acc; } const pageType = key; for (const page of files){ acc.push({ pageType, page }); } return acc; }, []).map(({ pageType , page })=>{ const checkPageSpan = staticCheckSpan.traceChild("check-page", { page }); return checkPageSpan.traceAsyncFn(async ()=>{ const actualPage = (0, _normalizePagePath).normalizePagePath(page); const [selfSize, allSize] = await (0, _utils2).getJsPageSizeInKb(pageType, actualPage, distDir, buildManifest, appBuildManifest, config.experimental.gzipSize, computedManifestData); let isSsg = false; let isStatic = false; let isServerComponent = false; let isHybridAmp = false; let ssgPageRoutes = null; const pagePath = pageType === "pages" ? pagesPaths.find((p)=>p.startsWith(actualPage + ".") || p.startsWith(actualPage + "/index.")) : appPaths == null ? void 0 : appPaths.find((p)=>p.startsWith(actualPage + "/page.")); const pageRuntime = pageType === "pages" && pagePath ? (await (0, _getPageStaticInfo).getPageStaticInfo({ pageFilePath: (0, _path).join(pagesDir, pagePath), nextConfig: config })).runtime : undefined; if (hasServerComponents && pagePath) { if ((0, _utils2).isServerComponentPage(config, pagePath)) { isServerComponent = true; } } if (// Only calculate page static information if the page is not an // app page. pageType !== "app" && !(0, _utils2).isReservedPage(page) && // We currently don't support static optimization in the Edge runtime. pageRuntime !== _constants.SERVER_RUNTIME.edge) { try { let isPageStaticSpan = checkPageSpan.traceChild("is-page-static"); let workerResult = await isPageStaticSpan.traceAsyncFn(()=>{ var ref, ref10; return staticWorkers.isPageStatic(page, distDir, isLikeServerless, configFileName, runtimeEnvConfig, config.httpAgentOptions, (ref = config.i18n) == null ? void 0 : ref.locales, (ref10 = config.i18n) == null ? void 0 : ref10.defaultLocale, isPageStaticSpan.id); }); if (config.outputFileTracing) { pageTraceIncludes.set(page, workerResult.traceIncludes || []); pageTraceExcludes.set(page, workerResult.traceExcludes || []); } if (workerResult.isStatic === false && (workerResult.isHybridAmp || workerResult.isAmpOnly)) { hasSsrAmpPages = true; } if (workerResult.isHybridAmp) { isHybridAmp = true; hybridAmpPages.add(page); } if (workerResult.isNextImageImported) { isNextImageImported = true; } if (workerResult.hasStaticProps) { ssgPages.add(page); isSsg = true; if (workerResult.prerenderRoutes && workerResult.encodedPrerenderRoutes) { additionalSsgPaths.set(page, workerResult.prerenderRoutes); additionalSsgPathsEncoded.set(page, workerResult.encodedPrerenderRoutes); ssgPageRoutes = workerResult.prerenderRoutes; } if (workerResult.prerenderFallback === "blocking") { ssgBlockingFallbackPages.add(page); } else if (workerResult.prerenderFallback === true) { ssgStaticFallbackPages.add(page); } } else if (workerResult.hasServerProps) { serverPropsPages.add(page); } else if (workerResult.isStatic && !isServerComponent && await customAppGetInitialPropsPromise === false) { staticPages.add(page); isStatic = true; } else if (isServerComponent) { // This is a static server component page that doesn't have // gSP or gSSP. We still treat it as a SSG page. ssgPages.add(page); isSsg = true; } if (hasPages404 && page === "/404") { if (!workerResult.isStatic && !workerResult.hasStaticProps) { throw new Error(`\`pages/404\` ${_constants.STATIC_STATUS_PAGE_GET_INITIAL_PROPS_ERROR}`); } // we need to ensure the 404 lambda is present since we use // it when _app has getInitialProps if (await customAppGetInitialPropsPromise && !workerResult.hasStaticProps) { staticPages.delete(page); } } if (_constants1.STATIC_STATUS_PAGES.includes(page) && !workerResult.isStatic && !workerResult.hasStaticProps) { throw new Error(`\`pages${page}\` ${_constants.STATIC_STATUS_PAGE_GET_INITIAL_PROPS_ERROR}`); } } catch (err) { if (!(0, _isError).default(err) || err.message !== "INVALID_DEFAULT_EXPORT") throw err; invalidPages.add(page); } } pageInfos.set(page, { size: selfSize, totalSize: allSize, static: isStatic, isSsg, isHybridAmp, ssgPageRoutes, initialRevalidateSeconds: false, runtime: pageRuntime, pageDuration: undefined, ssgPageDurations: undefined }); }); })); const errorPageResult = await errorPageStaticResult; const nonStaticErrorPage = await errorPageHasCustomGetInitialProps || errorPageResult && errorPageResult.hasServerProps; const returnValue = { customAppGetInitialProps: await customAppGetInitialPropsPromise, namedExports: await namedExportsPromise, isNextImageImported, hasSsrAmpPages, hasNonStaticErrorPage: nonStaticErrorPage }; if (!sharedPool) staticWorkers.end(); return returnValue; }); if (customAppGetInitialProps) { console.warn(_chalk.default.bold.yellow(`Warning: `) + _chalk.default.yellow(`You have opted-out of Automatic Static Optimization due to \`getInitialProps\` in \`pages/_app\`. This does not opt-out pages with \`getStaticProps\``)); console.warn("Read more: https://nextjs.org/docs/messages/opt-out-auto-static-optimization\n"); } if (!hasSsrAmpPages1) { requiredServerFiles.ignore.push(_path.default.relative(dir, _path.default.join(_path.default.dirname(require.resolve("next/dist/compiled/@ampproject/toolbox-optimizer")), "**/*"))); } if (config.outputFileTracing) { const { nodeFileTrace } = require("next/dist/compiled/@vercel/nft"); const includeExcludeSpan = nextBuildSpan.traceChild("apply-include-excludes"); await includeExcludeSpan.traceAsyncFn(async ()=>{ const globOrig = require("next/dist/compiled/glob"); const glob = (pattern)=>{ return new Promise((resolve, reject)=>{ globOrig(pattern, { cwd: dir }, (err, files)=>{ if (err) { return reject(err); } resolve(files); }); }); }; for (let page of pageKeys.pages){ await includeExcludeSpan.traceChild("include-exclude", { page }).traceAsyncFn(async ()=>{ const includeGlobs = pageTraceIncludes.get(page); const excludeGlobs = pageTraceExcludes.get(page); page = (0, _normalizePagePath).normalizePagePath(page); if (!(includeGlobs == null ? void 0 : includeGlobs.length) && !(excludeGlobs == null ? void 0 : excludeGlobs.length)) { return; } const traceFile = _path.default.join(distDir, "server/pages", `${page}.js.nft.json`); const pageDir = _path.default.dirname(traceFile); const traceContent = JSON.parse(await _fs.promises.readFile(traceFile, "utf8")); let includes = []; if (includeGlobs == null ? void 0 : includeGlobs.length) { for (const includeGlob of includeGlobs){ const results = await glob(includeGlob); includes.push(...results.map((file)=>{ return _path.default.relative(pageDir, _path.default.join(dir, file)); })); } } const combined = new Set([ ...traceContent.files, ...includes ]); if (excludeGlobs == null ? void 0 : excludeGlobs.length) { const resolvedGlobs = excludeGlobs.map((exclude)=>_path.default.join(dir, exclude)); combined.forEach((file)=>{ if ((0, _micromatch).isMatch(_path.default.join(pageDir, file), resolvedGlobs)) { combined.delete(file); } }); } await _fs.promises.writeFile(traceFile, JSON.stringify({ version: traceContent.version, files: [ ...combined ] })); }); } }); // TODO: move this inside of webpack so it can be cached // between builds. Should only need to be re-run on lockfile change await nextBuildSpan.traceChild("trace-next-server").traceAsyncFn(async ()=>{ let cacheKey; // consider all lockFiles in tree in case user accidentally // has both package-lock.json and yarn.lock const lockFiles = (await Promise.all([ "package-lock.json", "yarn.lock",