2020-12-21 20:26:00 +01:00
import { loadEnvConfig } from '@next/env'
2021-12-21 16:13:45 +01:00
import chalk from 'next/dist/compiled/chalk'
2020-02-12 02:16:42 +01:00
import crypto from 'crypto'
2021-10-22 20:55:45 +02:00
import { isMatch } from 'next/dist/compiled/micromatch'
2020-05-02 06:10:19 +02:00
import { promises , writeFileSync } from 'fs'
2021-07-16 11:21:44 +02:00
import { Worker } from '../lib/worker'
2020-03-29 01:18:22 +01:00
import devalue from 'next/dist/compiled/devalue'
2022-01-03 18:41:50 +01:00
import { escapeStringRegexp } from '../shared/lib/escape-regexp'
2020-03-29 18:21:53 +02:00
import findUp from 'next/dist/compiled/find-up'
2020-12-29 21:10:08 +01:00
import { nanoid } from 'next/dist/compiled/nanoid/index.cjs'
2020-03-29 19:17:06 +02:00
import { pathToRegexp } from 'next/dist/compiled/path-to-regexp'
2022-01-27 23:22:20 +01:00
import path , { join } from 'path'
2019-10-01 04:08:01 +02:00
import formatWebpackMessages from '../client/dev/error-overlay/format-webpack-messages'
2020-02-01 15:47:42 +01:00
import {
2021-02-22 17:29:50 +01:00
STATIC_STATUS_PAGE_GET_INITIAL_PROPS_ERROR ,
2020-02-04 19:55:43 +01:00
PUBLIC_DIR_MIDDLEWARE_CONFLICT ,
2021-10-20 19:52:11 +02:00
MIDDLEWARE_ROUTE ,
2020-02-01 15:47:42 +01:00
} from '../lib/constants'
2020-06-10 22:35:34 +02:00
import { fileExists } from '../lib/file-exists'
2019-10-01 04:08:01 +02:00
import { findPagesDir } from '../lib/find-pages-dir'
2020-06-10 22:35:34 +02:00
import loadCustomRoutes , {
2021-03-26 16:19:48 +01:00
CustomRoutes ,
2020-06-10 22:35:34 +02:00
getRedirectStatus ,
2021-07-13 21:38:14 +02:00
modifyRouteRegex ,
2020-07-08 20:45:53 +02:00
normalizeRouteRegex ,
2020-06-10 22:35:34 +02:00
Redirect ,
2021-03-26 16:19:48 +01:00
Rewrite ,
2020-06-10 22:35:34 +02:00
RouteType ,
} from '../lib/load-custom-routes'
2020-12-21 20:26:00 +01:00
import { nonNullable } from '../lib/non-nullable'
2019-10-01 04:08:01 +02:00
import { recursiveDelete } from '../lib/recursive-delete'
2021-04-30 13:09:07 +02:00
import { verifyAndLint } from '../lib/verifyAndLint'
2019-10-01 04:08:01 +02:00
import { verifyTypeScriptSetup } from '../lib/verifyTypeScriptSetup'
2019-04-24 11:04:36 +02:00
import {
2020-12-16 21:46:55 +01:00
BUILD_ID_FILE ,
2019-09-19 18:16:51 +02:00
BUILD_MANIFEST ,
2020-03-02 18:14:40 +01:00
CLIENT_STATIC_FILES_PATH ,
2019-12-13 20:30:22 +01:00
EXPORT_DETAIL ,
EXPORT_MARKER ,
2020-12-16 21:46:55 +01:00
FONT_MANIFEST ,
2020-10-16 13:10:01 +02:00
IMAGES_MANIFEST ,
2019-10-01 04:08:01 +02:00
PAGES_MANIFEST ,
2019-04-24 11:04:36 +02:00
PHASE_PRODUCTION_BUILD ,
2019-08-06 22:26:01 +02:00
PRERENDER_MANIFEST ,
2021-10-26 18:50:56 +02:00
MIDDLEWARE_FLIGHT_MANIFEST ,
2020-12-16 21:46:55 +01:00
REACT_LOADABLE_MANIFEST ,
2019-11-15 08:19:41 +01:00
ROUTES_MANIFEST ,
2019-08-06 00:26:20 +02:00
SERVERLESS_DIRECTORY ,
2019-12-12 17:20:24 +01:00
SERVER_DIRECTORY ,
2020-12-16 21:46:55 +01:00
SERVER_FILES_MANIFEST ,
2021-02-22 17:29:50 +01:00
STATIC_STATUS_PAGES ,
2021-10-20 19:52:11 +02:00
MIDDLEWARE_MANIFEST ,
2021-06-30 11:43:31 +02:00
} from '../shared/lib/constants'
2019-11-09 01:51:19 +01:00
import {
getRouteRegex ,
getSortedRoutes ,
2019-11-15 08:19:41 +01:00
isDynamicRoute ,
2021-06-30 11:43:31 +02:00
} from '../shared/lib/router/utils'
2021-06-30 13:44:40 +02:00
import { __ApiPreviewProps } from '../server/api-utils'
2022-01-20 22:25:44 +01:00
import loadConfig from '../server/config'
import { isTargetLikeServerless } from '../server/utils'
2021-06-30 13:44:40 +02:00
import { BuildManifest } from '../server/get-page-files'
import { normalizePagePath } from '../server/normalize-page-path'
import { getPagePath } from '../server/require'
2020-04-08 22:20:28 +02:00
import * as ciEnvironment from '../telemetry/ci-info'
2019-08-29 18:43:06 +02:00
import {
2020-02-04 19:55:43 +01:00
eventBuildCompleted ,
2019-10-10 19:18:07 +02:00
eventBuildOptimize ,
2020-02-14 21:42:44 +01:00
eventCliSession ,
2021-10-05 21:31:48 +02:00
eventBuildFeatureUsage ,
2019-10-10 19:18:07 +02:00
eventNextPlugins ,
2021-05-04 10:41:01 +02:00
eventTypeCheckCompleted ,
2021-10-11 23:15:18 +02:00
EVENT_BUILD_FEATURE_USAGE ,
EventBuildFeatureUsage ,
2019-08-29 18:43:06 +02:00
} from '../telemetry/events'
2019-10-10 19:18:07 +02:00
import { Telemetry } from '../telemetry/storage'
2019-04-10 18:37:13 +02:00
import { CompilerResult , runCompiler } from './compiler'
import { createEntrypoints , createPagesMapping } from './entries'
2019-02-17 12:56:48 +01:00
import { generateBuildId } from './generate-build-id'
import { isWriteable } from './is-writeable'
2020-12-21 20:26:00 +01:00
import * as Log from './output/log'
2019-10-01 04:08:01 +02:00
import createSpinner from './spinner'
2021-09-13 15:49:29 +02:00
import { trace , flushAllTraces , setGlobal } from '../trace'
2019-04-10 18:41:59 +02:00
import {
collectPages ,
2021-01-11 21:50:17 +01:00
detectConflictingPaths ,
2021-05-14 16:29:49 +02:00
computeFromManifest ,
2020-04-01 11:39:25 +02:00
getJsPageSizeInKb ,
2019-08-06 00:26:20 +02:00
PageInfo ,
2019-11-26 10:33:47 +01:00
printCustomRoutes ,
2019-11-27 22:48:28 +01:00
printTreeView ,
2021-11-02 22:03:29 +01:00
getUnresolvedModuleFromError ,
2021-11-09 18:03:20 +01:00
copyTracedFiles ,
2021-11-06 12:27:40 +01:00
isReservedPage ,
isCustomErrorPage ,
2019-04-10 18:41:59 +02:00
} from './utils'
2019-04-10 18:37:13 +02:00
import getBaseWebpackConfig from './webpack-config'
2020-05-25 23:15:56 +02:00
import { PagesManifest } from './webpack/plugins/pages-manifest-plugin'
2020-05-29 10:16:22 +02:00
import { writeBuildId } from './write-build-id'
2021-06-30 11:43:31 +02:00
import { normalizeLocalePath } from '../shared/lib/i18n/normalize-locale-path'
2021-07-12 23:38:57 +02:00
import { NextConfigComplete } from '../server/config-shared'
2021-10-21 01:23:44 +02:00
import isError , { NextError } from '../lib/is-error'
2021-10-05 21:31:48 +02:00
import { TelemetryPlugin } from './webpack/plugins/telemetry-plugin'
2021-10-20 19:52:11 +02:00
import { MiddlewareManifest } from './webpack/plugins/middleware-plugin'
2021-10-24 23:04:26 +02:00
import type { webpack5 as webpack } from 'next/dist/compiled/webpack/webpack'
2021-11-09 18:03:20 +01:00
import { recursiveCopy } from '../lib/recursive-copy'
2021-10-20 19:52:11 +02:00
2020-01-15 21:57:07 +01:00
export type SsgRoute = {
2019-09-24 10:50:04 +02:00
initialRevalidateSeconds : number | false
2019-10-02 15:28:38 +02:00
srcRoute : string | null
2019-10-01 04:08:01 +02:00
dataRoute : string
}
2020-01-15 21:57:07 +01:00
export type DynamicSsgRoute = {
2019-10-01 04:08:01 +02:00
routeRegex : string
2020-08-04 17:10:31 +02:00
fallback : string | null | false
2019-10-01 04:08:01 +02:00
dataRoute : string
dataRouteRegex : string
2019-09-24 10:50:04 +02:00
}
export type PrerenderManifest = {
2021-01-27 12:24:00 +01:00
version : 3
2020-01-15 21:57:07 +01:00
routes : { [ route : string ] : SsgRoute }
dynamicRoutes : { [ route : string ] : DynamicSsgRoute }
2020-10-15 23:55:38 +02:00
notFoundRoutes : string [ ]
2020-02-12 02:16:42 +01:00
preview : __ApiPreviewProps
2019-08-06 22:26:01 +02:00
}
2020-07-09 13:39:12 +02:00
export default async function build (
dir : string ,
conf = null ,
2020-08-20 17:43:38 +02:00
reactProductionProfiling = false ,
2021-06-03 14:01:24 +02:00
debugOutput = false ,
runLint = true
2020-07-09 13:39:12 +02:00
) : Promise < void > {
2021-11-03 12:51:55 +01:00
const nextBuildSpan = trace ( 'next-build' , undefined , {
2021-11-04 21:56:30 +01:00
version : process.env.__NEXT_VERSION as string ,
2021-11-03 12:51:55 +01:00
} )
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
2021-08-17 09:18:47 +02:00
const buildResult = await nextBuildSpan . traceAsyncFn ( async ( ) = > {
2020-12-21 17:02:41 +01:00
// attempt to load global env values so they are available in next.config.js
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
const { loadedEnvFiles } = nextBuildSpan
. traceChild ( 'load-dotenv' )
. traceFn ( ( ) = > loadEnvConfig ( dir , false , Log ) )
2020-03-26 13:32:41 +01:00
2021-07-12 23:38:57 +02:00
const config : NextConfigComplete = await nextBuildSpan
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
. traceChild ( 'load-next-config' )
. traceAsyncFn ( ( ) = > loadConfig ( PHASE_PRODUCTION_BUILD , dir , conf ) )
2021-10-26 18:50:56 +02:00
2021-08-25 10:47:16 +02:00
const distDir = path . join ( dir , config . distDir )
2021-10-05 12:52:45 +02:00
setGlobal ( 'phase' , PHASE_PRODUCTION_BUILD )
2021-08-25 10:47:16 +02:00
setGlobal ( 'distDir' , distDir )
2022-02-08 14:16:46 +01:00
// Currently, when the runtime option is set (either `nodejs` or `edge`),
// we enable concurrent features (Fizz-related rendering architecture).
const runtime = config . experimental . runtime
const hasConcurrentFeatures = ! ! runtime
2021-10-26 18:50:56 +02:00
const hasServerComponents =
2021-10-28 19:02:55 +02:00
hasConcurrentFeatures && ! ! config . experimental . serverComponents
2021-10-26 18:50:56 +02:00
2020-12-21 17:02:41 +01:00
const { target } = config
2021-03-26 16:19:48 +01:00
const buildId : string = await nextBuildSpan
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
. traceChild ( 'generate-buildid' )
. traceAsyncFn ( ( ) = > generateBuildId ( config . generateBuildId , nanoid ) )
2019-11-09 23:34:53 +01:00
2021-03-26 16:19:48 +01:00
const customRoutes : CustomRoutes = await nextBuildSpan
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
. traceChild ( 'load-custom-routes' )
. traceAsyncFn ( ( ) = > loadCustomRoutes ( config ) )
2019-10-10 19:18:07 +02:00
2021-03-26 16:19:48 +01:00
const { headers , rewrites , redirects } = customRoutes
2021-05-07 19:21:20 +02:00
const cacheDir = path . join ( distDir , 'cache' )
2020-12-21 17:02:41 +01:00
if ( ciEnvironment . isCI && ! ciEnvironment . hasNextSupport ) {
const hasCache = await fileExists ( cacheDir )
2019-10-18 18:40:47 +02:00
2020-12-21 17:02:41 +01:00
if ( ! hasCache ) {
// Intentionally not piping to stderr in case people fail in CI when
// stderr is detected.
console . log (
2021-03-29 10:25:00 +02:00
` ${ Log . prefixes . warn } No build cache found. Please configure build caching for faster rebuilds. Read more: https://nextjs.org/docs/messages/no-cache `
2020-12-21 17:02:41 +01:00
)
}
2019-10-18 18:40:47 +02:00
}
2020-12-21 17:02:41 +01:00
const telemetry = new Telemetry ( { distDir } )
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
setGlobal ( 'telemetry' , telemetry )
2019-10-10 19:18:07 +02:00
2020-12-21 17:02:41 +01:00
const publicDir = path . join ( dir , 'public' )
const pagesDir = findPagesDir ( dir )
const hasPublicDir = await fileExists ( publicDir )
2019-09-16 23:06:30 +02:00
2020-12-21 17:02:41 +01:00
telemetry . record (
2021-10-16 14:22:42 +02:00
eventCliSession ( dir , config , {
2021-10-07 01:46:46 +02:00
webpackVersion : 5 ,
2020-12-21 17:02:41 +01:00
cliCommand : 'build' ,
isSrcDir : path.relative ( dir , pagesDir ! ) . startsWith ( 'src' ) ,
hasNowJson : ! ! ( await findUp ( 'now.json' , { cwd : dir } ) ) ,
isCustomServer : null ,
} )
)
2019-10-03 16:21:15 +02:00
2020-12-21 17:02:41 +01:00
eventNextPlugins ( path . resolve ( dir ) ) . then ( ( events ) = >
telemetry . record ( events )
)
2019-12-03 17:18:58 +01:00
2021-08-24 16:08:18 +02:00
const ignoreTypeScriptErrors = Boolean ( config . typescript . ignoreBuildErrors )
2021-05-04 10:41:01 +02:00
const typeCheckStart = process . hrtime ( )
const typeCheckingSpinner = createSpinner ( {
2021-05-07 16:34:15 +02:00
prefixText : ` ${ Log . prefixes . info } ${
ignoreTypeScriptErrors
? 'Skipping validation of types'
: 'Checking validity of types'
} ` ,
2021-05-04 10:41:01 +02:00
} )
const verifyResult = await nextBuildSpan
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
. traceChild ( 'verify-typescript-setup' )
. traceAsyncFn ( ( ) = >
2021-06-22 18:56:21 +02:00
verifyTypeScriptSetup (
dir ,
pagesDir ,
! ignoreTypeScriptErrors ,
2021-09-24 00:52:05 +02:00
config ,
2021-06-22 18:56:21 +02:00
cacheDir
)
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
)
2019-08-18 21:45:39 +02:00
2021-05-04 10:41:01 +02:00
const typeCheckEnd = process . hrtime ( typeCheckStart )
2021-05-07 16:34:15 +02:00
if ( ! ignoreTypeScriptErrors ) {
telemetry . record (
eventTypeCheckCompleted ( {
durationInSeconds : typeCheckEnd [ 0 ] ,
typescriptVersion : verifyResult.version ,
inputFilesCount : verifyResult.result?.inputFilesCount ,
totalFilesCount : verifyResult.result?.totalFilesCount ,
incremental : verifyResult.result?.incremental ,
} )
)
}
2021-05-04 10:41:01 +02:00
2021-03-20 20:11:45 +01:00
if ( typeCheckingSpinner ) {
typeCheckingSpinner . stopAndPersist ( )
}
2021-08-24 16:08:18 +02:00
const ignoreESLint = Boolean ( config . eslint . ignoreDuringBuilds )
2021-08-23 19:56:21 +02:00
const eslintCacheDir = path . join ( cacheDir , 'eslint/' )
2021-12-07 03:41:31 +01:00
const shouldLint = ! ignoreESLint && runLint
if ( shouldLint ) {
2021-04-30 13:09:07 +02:00
await nextBuildSpan
. traceChild ( 'verify-and-lint' )
. traceAsyncFn ( async ( ) = > {
await verifyAndLint (
dir ,
2021-08-23 19:56:21 +02:00
eslintCacheDir ,
config . eslint ? . dirs ,
2021-04-30 13:09:07 +02:00
config . experimental . cpus ,
2021-06-15 03:31:40 +02:00
config . experimental . workerThreads ,
telemetry
2021-04-30 13:09:07 +02:00
)
} )
}
2021-12-07 03:41:31 +01:00
const buildLintEvent : EventBuildFeatureUsage = {
featureName : 'build-lint' ,
invocationCount : shouldLint ? 1 : 0 ,
}
telemetry . record ( {
eventName : EVENT_BUILD_FEATURE_USAGE ,
payload : buildLintEvent ,
} )
2021-04-30 13:09:07 +02:00
2021-03-20 20:11:45 +01:00
const buildSpinner = createSpinner ( {
prefixText : ` ${ Log . prefixes . info } Creating an optimized production build ` ,
} )
2020-12-21 17:02:41 +01:00
const isLikeServerless = isTargetLikeServerless ( target )
2019-08-06 00:26:20 +02:00
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
const pagePaths : string [ ] = await nextBuildSpan
. traceChild ( 'collect-pages' )
. traceAsyncFn ( ( ) = > collectPages ( pagesDir , config . pageExtensions ) )
2020-12-21 17:02:41 +01:00
// needed for static exporting since we want to replace with HTML
// files
const allStaticPages = new Set < string > ( )
let allPageInfos = new Map < string , PageInfo > ( )
2019-09-16 23:06:30 +02:00
2020-12-21 17:02:41 +01:00
const previewProps : __ApiPreviewProps = {
previewModeId : crypto.randomBytes ( 16 ) . toString ( 'hex' ) ,
previewModeSigningKey : crypto.randomBytes ( 32 ) . toString ( 'hex' ) ,
previewModeEncryptionKey : crypto.randomBytes ( 32 ) . toString ( 'hex' ) ,
2020-06-10 22:35:34 +02:00
}
2020-12-21 17:02:41 +01:00
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
const mappedPages = nextBuildSpan
. traceChild ( 'create-pages-mapping' )
2021-08-19 10:12:12 +02:00
. traceFn ( ( ) = >
2021-11-30 13:52:14 +01:00
createPagesMapping ( pagePaths , config . pageExtensions , {
isDev : false ,
hasServerComponents ,
2022-02-08 14:16:46 +01:00
runtime ,
2021-11-30 13:52:14 +01:00
} )
2021-08-19 10:12:12 +02:00
)
2021-10-26 18:50:56 +02:00
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
const entrypoints = nextBuildSpan
. traceChild ( 'create-entrypoints' )
. traceFn ( ( ) = >
createEntrypoints (
mappedPages ,
target ,
buildId ,
previewProps ,
config ,
loadedEnvFiles
)
2021-01-10 02:12:13 +01:00
)
2020-12-21 17:02:41 +01:00
const pageKeys = Object . keys ( mappedPages )
2021-10-22 05:00:51 +02:00
const hasMiddleware = pageKeys . some ( ( page ) = > MIDDLEWARE_ROUTE . test ( page ) )
2020-12-21 17:02:41 +01:00
const conflictingPublicFiles : string [ ] = [ ]
2021-08-17 09:18:08 +02:00
const hasCustomErrorPage : boolean =
mappedPages [ '/_error' ] . startsWith ( 'private-next-pages' )
2020-12-21 17:02:41 +01:00
const hasPages404 = Boolean (
mappedPages [ '/404' ] &&
mappedPages [ '/404' ] . startsWith ( 'private-next-pages' )
)
2021-10-22 08:40:57 +02:00
if ( hasMiddleware ) {
2021-10-25 00:27:00 +02:00
Log . warn (
` using beta Middleware (not covered by semver) - https://nextjs.org/docs/messages/beta-middleware `
2021-10-22 08:40:57 +02:00
)
}
2020-12-21 17:02:41 +01:00
if ( hasPublicDir ) {
const hasPublicUnderScoreNextDir = await fileExists (
path . join ( publicDir , '_next' )
)
if ( hasPublicUnderScoreNextDir ) {
throw new Error ( PUBLIC_DIR_MIDDLEWARE_CONFLICT )
}
2019-09-16 23:06:30 +02:00
}
2020-06-10 22:35:34 +02:00
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
await nextBuildSpan
. traceChild ( 'public-dir-conflict-check' )
. traceAsyncFn ( async ( ) = > {
2021-01-10 02:12:13 +01:00
// 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 fileExists (
path . join ( publicDir , page === '/' ? '/index' : page ) ,
'file'
)
if ( hasPublicPageFile ) {
conflictingPublicFiles . push ( page )
}
}
2019-09-16 23:06:30 +02:00
2021-01-10 02:12:13 +01:00
const numConflicting = conflictingPublicFiles . length
2019-09-16 23:06:30 +02:00
2021-01-10 02:12:13 +01:00
if ( numConflicting ) {
throw new Error (
` Conflicting public and page file ${
numConflicting === 1 ? ' was' : 's were'
2021-03-29 10:25:00 +02:00
} found . https : //nextjs.org/docs/messages/conflicting-public-file-page\n${conflictingPublicFiles.join(
2021-01-10 02:12:13 +01:00
'\n'
) } `
)
}
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
} )
2020-05-27 18:45:53 +02:00
2020-12-21 17:02:41 +01:00
const nestedReservedPages = pageKeys . filter ( ( page ) = > {
return (
page . match ( /\/(_app|_document|_error)$/ ) && path . dirname ( page ) !== '/'
)
2019-12-23 22:20:17 +01:00
} )
2020-12-21 17:02:41 +01:00
if ( nestedReservedPages . length ) {
Log . warn (
` The following reserved Next.js pages were detected not directly under the pages directory: \ n ` +
nestedReservedPages . join ( '\n' ) +
2021-03-29 10:25:00 +02:00
` \ nSee more info here: https://nextjs.org/docs/messages/nested-reserved-page \ n `
2020-12-21 17:02:41 +01:00
)
2020-10-15 20:21:30 +02:00
}
2020-12-16 21:46:55 +01:00
2021-07-13 21:38:14 +02:00
const restrictedRedirectPaths = [ '/_next' ] . map ( ( p ) = >
config . basePath ? ` ${ config . basePath } ${ p } ` : p
)
2020-12-21 17:02:41 +01:00
const buildCustomRoute = (
r : {
source : string
locale? : false
basePath? : false
statusCode? : number
destination? : string
} ,
type : RouteType
) = > {
const keys : any [ ] = [ ]
2018-12-03 14:18:52 +01:00
2020-12-21 17:02:41 +01:00
const routeRegex = pathToRegexp ( r . source , keys , {
strict : true ,
sensitive : false ,
delimiter : '/' , // default is `/#?`, but Next does not pass query info
} )
2021-07-13 21:38:14 +02:00
let regexSource = routeRegex . source
if ( ! ( r as any ) . internal ) {
regexSource = modifyRouteRegex (
routeRegex . source ,
type === 'redirect' ? restrictedRedirectPaths : undefined
)
}
2019-08-13 05:13:12 +02:00
2020-12-21 17:02:41 +01:00
return {
. . . r ,
. . . ( type === 'redirect'
? {
statusCode : getRedirectStatus ( r as Redirect ) ,
permanent : undefined ,
}
: { } ) ,
2021-07-13 21:38:14 +02:00
regex : normalizeRouteRegex ( regexSource ) ,
2019-02-17 12:56:48 +01:00
}
2019-01-10 22:10:50 +01:00
}
2020-12-21 17:02:41 +01:00
const routesManifestPath = path . join ( distDir , ROUTES_MANIFEST )
const routesManifest : {
version : number
pages404 : boolean
basePath : string
redirects : Array < ReturnType < typeof buildCustomRoute > >
2021-03-26 16:19:48 +01:00
rewrites :
| Array < ReturnType < typeof buildCustomRoute > >
| {
beforeFiles : Array < ReturnType < typeof buildCustomRoute > >
afterFiles : Array < ReturnType < typeof buildCustomRoute > >
fallback : Array < ReturnType < typeof buildCustomRoute > >
}
2020-12-21 17:02:41 +01:00
headers : Array < ReturnType < typeof buildCustomRoute > >
2021-10-20 19:52:11 +02:00
staticRoutes : Array < {
page : string
regex : string
namedRegex? : string
routeKeys ? : { [ key : string ] : string }
} >
2020-12-21 17:02:41 +01:00
dynamicRoutes : Array < {
page : string
regex : string
namedRegex? : string
routeKeys ? : { [ key : string ] : string }
} >
dataRoutes : Array < {
page : string
routeKeys ? : { [ key : string ] : string }
dataRouteRegex : string
namedDataRouteRegex? : string
} >
i18n ? : {
domains? : Array < {
http? : true
domain : string
locales? : string [ ]
defaultLocale : string
} >
locales : string [ ]
defaultLocale : string
localeDetection? : false
}
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
} = nextBuildSpan . traceChild ( 'generate-routes-manifest' ) . traceFn ( ( ) = > ( {
2020-12-21 17:02:41 +01:00
version : 3 ,
pages404 : true ,
basePath : config.basePath ,
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
redirects : redirects.map ( ( r : any ) = > buildCustomRoute ( r , 'redirect' ) ) ,
headers : headers.map ( ( r : any ) = > buildCustomRoute ( r , 'header' ) ) ,
2020-12-21 17:02:41 +01:00
dynamicRoutes : getSortedRoutes ( pageKeys )
2021-10-20 19:52:11 +02:00
. filter ( ( page ) = > isDynamicRoute ( page ) && ! page . match ( MIDDLEWARE_ROUTE ) )
. map ( pageToRoute ) ,
staticRoutes : getSortedRoutes ( pageKeys )
. filter (
( page ) = >
! isDynamicRoute ( page ) &&
! page . match ( MIDDLEWARE_ROUTE ) &&
2021-11-06 12:27:40 +01:00
! isReservedPage ( page )
2021-10-20 19:52:11 +02:00
)
. map ( pageToRoute ) ,
2020-12-21 17:02:41 +01:00
dataRoutes : [ ] ,
i18n : config.i18n || undefined ,
2021-01-10 02:12:13 +01:00
} ) )
2019-02-17 12:56:48 +01:00
2021-03-26 16:19:48 +01:00
if ( rewrites . beforeFiles . length === 0 && rewrites . fallback . length === 0 ) {
routesManifest . rewrites = rewrites . afterFiles . map ( ( r : any ) = >
buildCustomRoute ( r , 'rewrite' )
)
} else {
routesManifest . rewrites = {
beforeFiles : rewrites.beforeFiles.map ( ( r : any ) = >
buildCustomRoute ( r , 'rewrite' )
) ,
afterFiles : rewrites.afterFiles.map ( ( r : any ) = >
buildCustomRoute ( r , 'rewrite' )
) ,
fallback : rewrites.fallback.map ( ( r : any ) = >
buildCustomRoute ( r , 'rewrite' )
) ,
}
}
const combinedRewrites : Rewrite [ ] = [
. . . rewrites . beforeFiles ,
. . . rewrites . afterFiles ,
. . . rewrites . fallback ,
]
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
const distDirCreated = await nextBuildSpan
. traceChild ( 'create-dist-dir' )
. traceAsyncFn ( async ( ) = > {
2021-01-25 18:09:22 +01:00
try {
await promises . mkdir ( distDir , { recursive : true } )
return true
} catch ( err ) {
2021-09-16 18:06:57 +02:00
if ( isError ( err ) && err . code === 'EPERM' ) {
2021-01-25 18:09:22 +01:00
return false
}
throw err
}
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
} )
2021-01-25 18:09:22 +01:00
if ( ! distDirCreated || ! ( await isWriteable ( distDir ) ) ) {
throw new Error (
2021-03-29 10:25:00 +02:00
'> Build directory is not writeable. https://nextjs.org/docs/messages/build-dir-not-writeable'
2021-01-25 18:09:22 +01:00
)
}
2021-06-14 16:20:34 +02:00
if ( config . cleanDistDir ) {
await recursiveDelete ( distDir , /^cache/ )
}
2020-12-21 17:02:41 +01:00
// We need to write the manifest with rewrites before build
// so serverless can import the manifest
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
await nextBuildSpan
. traceChild ( 'write-routes-manifest' )
. traceAsyncFn ( ( ) = >
promises . writeFile (
routesManifestPath ,
JSON . stringify ( routesManifest ) ,
'utf8'
)
2021-01-10 02:12:13 +01:00
)
2019-07-15 17:16:35 +02:00
2020-12-21 17:02:41 +01:00
const manifestPath = path . join (
distDir ,
isLikeServerless ? SERVERLESS_DIRECTORY : SERVER_DIRECTORY ,
PAGES_MANIFEST
)
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
const requiredServerFiles = nextBuildSpan
. traceChild ( 'generate-required-server-files' )
. traceFn ( ( ) = > ( {
2021-01-10 02:12:13 +01:00
version : 1 ,
2022-02-08 04:50:23 +01:00
config : {
. . . config ,
configFile : undefined ,
experimental : {
. . . config . experimental ,
trustHostHeader : ciEnvironment.hasNextSupport ,
} ,
} ,
2021-03-09 19:41:57 +01:00
appDir : dir ,
2021-01-10 02:12:13 +01:00
files : [
ROUTES_MANIFEST ,
path . relative ( distDir , manifestPath ) ,
BUILD_MANIFEST ,
PRERENDER_MANIFEST ,
2021-11-09 18:03:20 +01:00
path . join ( SERVER_DIRECTORY , MIDDLEWARE_MANIFEST ) ,
2021-10-26 18:50:56 +02:00
hasServerComponents
2022-02-09 02:26:50 +01:00
? path . join (
SERVER_DIRECTORY ,
2022-02-09 20:24:05 +01:00
MIDDLEWARE_FLIGHT_MANIFEST +
( runtime === 'edge' ? '.js' : '.json' )
2022-02-09 02:26:50 +01:00
)
2021-10-26 18:50:56 +02:00
: null ,
2021-01-10 02:12:13 +01:00
REACT_LOADABLE_MANIFEST ,
2021-04-05 19:47:03 +02:00
config . optimizeFonts
2021-01-10 02:12:13 +01:00
? path . join (
isLikeServerless ? SERVERLESS_DIRECTORY : SERVER_DIRECTORY ,
FONT_MANIFEST
)
: null ,
BUILD_ID_FILE ,
]
. filter ( nonNullable )
. map ( ( file ) = > path . join ( config . distDir , file ) ) ,
2021-02-18 11:23:24 +01:00
ignore : [ ] as string [ ] ,
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
} ) )
2019-07-15 17:16:35 +02:00
2021-12-03 01:47:16 +01:00
let result : CompilerResult = { warnings : [ ] , errors : [ ] }
let webpackBuildStart
let telemetryPlugin
await ( async ( ) = > {
// IIFE to isolate locals and avoid retaining memory too long
const runWebpackSpan = nextBuildSpan . traceChild ( 'run-webpack-compiler' )
const configs = await runWebpackSpan
. traceChild ( 'generate-webpack-config' )
. traceAsyncFn ( ( ) = >
Promise . all ( [
getBaseWebpackConfig ( dir , {
buildId ,
reactProductionProfiling ,
isServer : false ,
config ,
target ,
pagesDir ,
entrypoints : entrypoints.client ,
rewrites ,
runWebpackSpan ,
} ) ,
getBaseWebpackConfig ( dir , {
buildId ,
reactProductionProfiling ,
isServer : true ,
config ,
target ,
pagesDir ,
entrypoints : entrypoints.server ,
rewrites ,
runWebpackSpan ,
} ) ,
2022-02-08 14:16:46 +01:00
runtime === 'edge'
2021-12-03 01:47:16 +01:00
? getBaseWebpackConfig ( dir , {
buildId ,
reactProductionProfiling ,
isServer : true ,
2022-02-08 14:16:46 +01:00
isEdgeRuntime : true ,
2021-12-03 01:47:16 +01:00
config ,
target ,
pagesDir ,
2022-02-08 14:16:46 +01:00
entrypoints : entrypoints.edgeServer ,
2021-12-03 01:47:16 +01:00
rewrites ,
runWebpackSpan ,
} )
: null ,
] )
)
2020-12-21 17:02:41 +01:00
2021-12-03 01:47:16 +01:00
const clientConfig = configs [ 0 ]
2019-03-17 13:13:29 +01:00
2021-12-03 01:47:16 +01:00
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 `
)
}
2020-02-11 23:09:00 +01:00
2021-12-03 01:47:16 +01:00
webpackBuildStart = process . hrtime ( )
2020-12-21 17:02:41 +01:00
2021-12-03 01:47:16 +01:00
// We run client and server compilation separately to optimize for memory usage
await runWebpackSpan . traceAsyncFn ( async ( ) = > {
const clientResult = await runCompiler ( clientConfig , { runWebpackSpan } )
// Fail build if clientResult contains errors
if ( clientResult . errors . length > 0 ) {
result = {
warnings : [ . . . clientResult . warnings ] ,
errors : [ . . . clientResult . errors ] ,
}
} else {
const serverResult = await runCompiler ( configs [ 1 ] , { runWebpackSpan } )
2022-02-08 14:16:46 +01:00
const edgeServerResult = configs [ 2 ]
2021-12-03 01:47:16 +01:00
? await runCompiler ( configs [ 2 ] , { runWebpackSpan } )
: null
result = {
warnings : [
. . . clientResult . warnings ,
. . . serverResult . warnings ,
2022-02-08 14:16:46 +01:00
. . . ( edgeServerResult ? . warnings || [ ] ) ,
2021-12-03 01:47:16 +01:00
] ,
errors : [
. . . clientResult . errors ,
. . . serverResult . errors ,
2022-02-08 14:16:46 +01:00
. . . ( edgeServerResult ? . errors || [ ] ) ,
2021-12-03 01:47:16 +01:00
] ,
}
2021-08-17 09:18:47 +02:00
}
2021-12-03 01:47:16 +01:00
} )
result = nextBuildSpan
. traceChild ( 'format-webpack-messages' )
. traceFn ( ( ) = > formatWebpackMessages ( result , true ) )
2020-08-04 09:58:23 +02:00
2021-12-03 01:47:16 +01:00
telemetryPlugin = ( clientConfig as webpack . Configuration ) . plugins ? . find (
isTelemetryPlugin
)
} ) ( )
2020-12-21 17:02:41 +01:00
const webpackBuildEnd = process . hrtime ( webpackBuildStart )
if ( buildSpinner ) {
buildSpinner . stopAndPersist ( )
}
2019-09-16 17:37:00 +02:00
2020-12-21 17:02:41 +01:00
if ( result . errors . length > 0 ) {
2021-10-21 01:23:44 +02:00
// Only keep the first few errors. Others are often indicative
2020-12-21 17:02:41 +01:00
// of the same problem, but confuse the reader with noise.
2021-10-21 01:23:44 +02:00
if ( result . errors . length > 5 ) {
result . errors . length = 5
2020-12-21 17:02:41 +01:00
}
const error = result . errors . join ( '\n\n' )
console . error ( chalk . 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 (
2021-03-29 10:25:00 +02:00
` 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. `
2020-12-21 17:02:41 +01:00
)
}
console . error ( error )
console . error ( )
2019-05-22 18:36:53 +02:00
2021-11-01 12:40:21 +01:00
// When using the web runtime, common Node.js native APIs are not available.
2021-11-02 22:03:29 +01:00
const moduleName = getUnresolvedModuleFromError ( error )
if ( hasConcurrentFeatures && moduleName ) {
2021-11-01 12:40:21 +01:00
const err = new Error (
2022-02-08 14:16:46 +01:00
` Native Node.js APIs are not supported in the Edge Runtime. Found \` ${ moduleName } \` imported. \ n \ n `
2021-11-01 12:40:21 +01:00
) as NextError
err . code = 'EDGE_RUNTIME_UNSUPPORTED_API'
throw err
}
2020-12-21 17:02:41 +01:00
if (
error . indexOf ( 'private-next-pages' ) > - 1 ||
error . indexOf ( '__next_polyfill__' ) > - 1
) {
2021-10-21 01:23:44 +02:00
const err = new Error (
'webpack config.resolve.alias was incorrectly overridden. https://nextjs.org/docs/messages/invalid-resolve-alias'
) as NextError
err . code = 'INVALID_RESOLVE_ALIAS'
throw err
2020-12-21 17:02:41 +01:00
}
2021-10-21 01:23:44 +02:00
const err = new Error (
'Build failed because of webpack errors'
) as NextError
err . code = 'WEBPACK_ERRORS'
throw err
2020-12-21 17:02:41 +01:00
} else {
telemetry . record (
eventBuildCompleted ( pagePaths , {
durationInSeconds : webpackBuildEnd [ 0 ] ,
} )
2020-09-15 03:03:43 +02:00
)
2019-06-28 22:01:11 +02:00
2020-12-21 17:02:41 +01:00
if ( result . warnings . length > 0 ) {
Log . warn ( 'Compiled with warnings\n' )
console . warn ( result . warnings . join ( '\n\n' ) )
console . warn ( )
} else {
Log . info ( 'Compiled successfully' )
}
}
2020-06-15 16:41:17 +02:00
2020-12-21 17:02:41 +01:00
const postCompileSpinner = createSpinner ( {
prefixText : ` ${ Log . prefixes . info } Collecting page data ` ,
} )
2020-06-15 16:41:17 +02:00
2020-12-21 17:02:41 +01:00
const buildManifestPath = path . join ( distDir , BUILD_MANIFEST )
const ssgPages = new Set < string > ( )
const ssgStaticFallbackPages = new Set < string > ( )
const ssgBlockingFallbackPages = new Set < string > ( )
const staticPages = new Set < string > ( )
const invalidPages = new Set < string > ( )
const hybridAmpPages = new Set < string > ( )
const serverPropsPages = new Set < string > ( )
const additionalSsgPaths = new Map < string , Array < string > > ( )
2020-12-28 21:08:58 +01:00
const additionalSsgPathsEncoded = new Map < string , Array < string > > ( )
2021-08-16 21:29:11 +02:00
const pageTraceIncludes = new Map < string , Array < string > > ( )
const pageTraceExcludes = new Map < string , Array < string > > ( )
2020-12-21 17:02:41 +01:00
const pageInfos = new Map < string , PageInfo > ( )
const pagesManifest = JSON . parse (
await promises . readFile ( manifestPath , 'utf8' )
) as PagesManifest
const buildManifest = JSON . parse (
await promises . readFile ( buildManifestPath , 'utf8' )
) as BuildManifest
2021-10-20 21:06:43 +02:00
const timeout = config . staticPageGenerationTimeout || 0
2021-08-12 21:54:49 +02:00
const sharedPool = config . experimental . sharedPool || false
const staticWorker = sharedPool
? require . resolve ( './worker' )
: require . resolve ( './utils' )
let infoPrinted = false
2021-12-16 07:17:42 +01:00
process . env . NEXT_PHASE = PHASE_PRODUCTION_BUILD
2021-08-12 21:54:49 +02:00
const staticWorkers = new 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 (
2021-11-11 11:38:53 +01:00
` Restarted static page generation for ${ pagePath } because it took more than ${ timeout } seconds `
2021-08-12 21:54:49 +02:00
)
} 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' ] ,
} ) as Worker &
Pick <
typeof import ( './worker' ) ,
| 'hasCustomGetInitialProps'
| 'isPageStatic'
| 'getNamedExports'
| 'exportPage'
>
2020-12-21 17:02:41 +01:00
const analysisBegin = process . hrtime ( )
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
const staticCheckSpan = nextBuildSpan . traceChild ( 'static-check' )
2021-05-17 14:04:06 +02:00
const {
customAppGetInitialProps ,
namedExports ,
isNextImageImported ,
hasSsrAmpPages ,
hasNonStaticErrorPage ,
} = await staticCheckSpan . traceAsyncFn ( async ( ) = > {
2021-10-22 03:18:57 +02:00
const { configFileName , publicRuntimeConfig , serverRuntimeConfig } =
config
const runtimeEnvConfig = { publicRuntimeConfig , serverRuntimeConfig }
2019-05-22 18:36:53 +02:00
2021-05-17 14:04:06 +02:00
const nonStaticErrorPageSpan = staticCheckSpan . traceChild (
'check-static-error-page'
)
2021-08-17 09:18:08 +02:00
const errorPageHasCustomGetInitialProps =
nonStaticErrorPageSpan . traceAsyncFn (
async ( ) = >
hasCustomErrorPage &&
( await staticWorkers . hasCustomGetInitialProps (
'/_error' ,
distDir ,
isLikeServerless ,
runtimeEnvConfig ,
false
) )
)
2021-06-11 11:29:40 +02:00
const errorPageStaticResult = nonStaticErrorPageSpan . traceAsyncFn (
async ( ) = >
hasCustomErrorPage &&
2021-08-12 21:54:49 +02:00
staticWorkers . isPageStatic (
2021-06-11 11:29:40 +02:00
'/_error' ,
distDir ,
isLikeServerless ,
2021-10-22 01:04:40 +02:00
configFileName ,
2021-06-11 11:29:40 +02:00
runtimeEnvConfig ,
2021-08-03 02:38:42 +02:00
config . httpAgentOptions ,
2021-06-11 11:29:40 +02:00
config . i18n ? . locales ,
config . i18n ? . defaultLocale
)
)
2021-05-17 14:04:06 +02:00
// we don't output _app in serverless mode so use _app export
// from _error instead
const appPageToCheck = isLikeServerless ? '/_error' : '/_app'
2021-08-17 09:18:08 +02:00
const customAppGetInitialPropsPromise =
staticWorkers . hasCustomGetInitialProps (
appPageToCheck ,
distDir ,
isLikeServerless ,
runtimeEnvConfig ,
true
)
2020-12-16 21:46:55 +01:00
2021-08-12 21:54:49 +02:00
const namedExportsPromise = staticWorkers . getNamedExports (
2021-05-17 14:04:06 +02:00
appPageToCheck ,
distDir ,
isLikeServerless ,
runtimeEnvConfig
)
2020-12-21 17:02:41 +01:00
2021-05-17 14:04:06 +02:00
// eslint-disable-next-line no-shadow
let isNextImageImported : boolean | undefined
// eslint-disable-next-line no-shadow
let hasSsrAmpPages = false
2020-11-11 16:46:48 +01:00
2021-05-17 14:04:06 +02:00
const computedManifestData = await computeFromManifest (
buildManifest ,
distDir ,
config . experimental . gzipSize
)
2021-10-26 18:50:56 +02:00
2021-05-17 14:04:06 +02:00
await Promise . all (
pageKeys . map ( async ( page ) = > {
const checkPageSpan = staticCheckSpan . traceChild ( 'check-page' , {
page ,
} )
return checkPageSpan . traceAsyncFn ( async ( ) = > {
const actualPage = normalizePagePath ( page )
const [ selfSize , allSize ] = await getJsPageSizeInKb (
actualPage ,
2021-03-09 10:55:28 +01:00
distDir ,
2021-05-17 14:04:06 +02:00
buildManifest ,
config . experimental . gzipSize ,
computedManifestData
)
let isSsg = false
let isStatic = false
let isHybridAmp = false
let ssgPageRoutes : string [ ] | null = null
2021-10-26 18:50:56 +02:00
let isMiddlewareRoute = ! ! page . match ( MIDDLEWARE_ROUTE )
2021-05-17 14:04:06 +02:00
2021-10-26 18:50:56 +02:00
if (
! isMiddlewareRoute &&
2021-11-06 12:27:40 +01:00
! isReservedPage ( page ) &&
2021-10-28 19:02:55 +02:00
! hasConcurrentFeatures
2021-10-26 18:50:56 +02:00
) {
2021-05-17 14:04:06 +02:00
try {
2021-08-17 09:18:08 +02:00
let isPageStaticSpan =
checkPageSpan . traceChild ( 'is-page-static' )
2021-05-17 14:04:06 +02:00
let workerResult = await isPageStaticSpan . traceAsyncFn ( ( ) = > {
2021-08-12 21:54:49 +02:00
return staticWorkers . isPageStatic (
2021-05-17 14:04:06 +02:00
page ,
distDir ,
isLikeServerless ,
2021-10-22 01:04:40 +02:00
configFileName ,
2021-05-17 14:04:06 +02:00
runtimeEnvConfig ,
2021-08-03 02:38:42 +02:00
config . httpAgentOptions ,
2021-05-17 14:04:06 +02:00
config . i18n ? . locales ,
config . i18n ? . defaultLocale ,
isPageStaticSpan . id
)
} )
2019-09-24 10:50:04 +02:00
2021-10-26 06:22:45 +02:00
if ( config . outputFileTracing ) {
2021-08-16 21:29:11 +02:00
pageTraceIncludes . set ( page , workerResult . traceIncludes || [ ] )
pageTraceExcludes . set ( page , workerResult . traceExcludes || [ ] )
}
2021-05-17 14:04:06 +02:00
if (
workerResult . isStatic === false &&
( workerResult . isHybridAmp || workerResult . isAmpOnly )
) {
hasSsrAmpPages = true
}
2020-08-04 17:10:31 +02:00
2021-05-17 14:04:06 +02:00
if ( workerResult . isHybridAmp ) {
isHybridAmp = true
hybridAmpPages . add ( page )
}
2020-02-01 15:47:42 +01:00
2021-05-17 14:04:06 +02:00
if ( workerResult . isNextImageImported ) {
isNextImageImported = true
}
2020-12-21 17:02:41 +01:00
2021-05-17 14:04:06 +02:00
if ( workerResult . hasStaticProps ) {
ssgPages . add ( page )
isSsg = true
2021-01-10 02:12:13 +01:00
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
if (
2021-05-17 14:04:06 +02:00
workerResult . prerenderRoutes &&
workerResult . encodedPrerenderRoutes
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
) {
2021-05-17 14:04:06 +02:00
additionalSsgPaths . set ( page , workerResult . prerenderRoutes )
additionalSsgPathsEncoded . set (
page ,
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
workerResult . encodedPrerenderRoutes
2021-05-17 14:04:06 +02:00
)
ssgPageRoutes = workerResult . prerenderRoutes
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
}
2021-02-22 17:29:50 +01:00
2021-05-17 14:04:06 +02:00
if ( workerResult . prerenderFallback === 'blocking' ) {
ssgBlockingFallbackPages . add ( page )
} else if ( workerResult . prerenderFallback === true ) {
ssgStaticFallbackPages . add ( page )
2021-01-10 02:12:13 +01:00
}
2021-05-17 14:04:06 +02:00
} else if ( workerResult . hasServerProps ) {
serverPropsPages . add ( page )
} else if (
workerResult . isStatic &&
2021-10-26 18:50:56 +02:00
! workerResult . hasFlightData &&
2021-05-17 14:04:06 +02:00
( await customAppGetInitialPropsPromise ) === false
) {
staticPages . add ( page )
isStatic = true
}
2020-12-21 17:02:41 +01:00
2021-05-17 14:04:06 +02:00
if ( hasPages404 && page === '/404' ) {
if ( ! workerResult . isStatic && ! workerResult . hasStaticProps ) {
throw new Error (
` \` pages/404 \` ${ STATIC_STATUS_PAGE_GET_INITIAL_PROPS_ERROR } `
)
}
// we need to ensure the 404 lambda is present since we use
// it when _app has getInitialProps
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
if (
2021-05-17 14:04:06 +02:00
( await customAppGetInitialPropsPromise ) &&
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
! workerResult . hasStaticProps
) {
2021-05-17 14:04:06 +02:00
staticPages . delete ( page )
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
}
}
2021-05-17 14:04:06 +02:00
if (
STATIC_STATUS_PAGES . includes ( page ) &&
! workerResult . isStatic &&
! workerResult . hasStaticProps
) {
throw new Error (
` \` pages ${ page } \` ${ STATIC_STATUS_PAGE_GET_INITIAL_PROPS_ERROR } `
)
}
} catch ( err ) {
2022-01-27 23:31:54 +01:00
if ( ! isError ( err ) || err . message !== 'INVALID_DEFAULT_EXPORT' )
2021-09-16 18:06:57 +02:00
throw err
2021-05-17 14:04:06 +02:00
invalidPages . add ( page )
2020-12-21 17:02:41 +01:00
}
2021-05-17 14:04:06 +02:00
}
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
2021-05-17 14:04:06 +02:00
pageInfos . set ( page , {
size : selfSize ,
totalSize : allSize ,
static : isStatic ,
isSsg ,
2021-10-26 18:50:56 +02:00
isWebSsr :
2021-10-28 19:02:55 +02:00
hasConcurrentFeatures &&
2021-10-26 18:50:56 +02:00
! isMiddlewareRoute &&
2021-11-06 12:27:40 +01:00
! isReservedPage ( page ) &&
! isCustomErrorPage ( page ) ,
2021-05-17 14:04:06 +02:00
isHybridAmp ,
ssgPageRoutes ,
initialRevalidateSeconds : false ,
2021-07-16 11:21:44 +02:00
pageDuration : undefined ,
ssgPageDurations : undefined ,
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
} )
2021-01-10 02:12:13 +01:00
} )
2021-05-17 14:04:06 +02:00
} )
)
2021-06-11 11:29:40 +02:00
const errorPageResult = await errorPageStaticResult
const nonStaticErrorPage =
( await errorPageHasCustomGetInitialProps ) ||
( errorPageResult && errorPageResult . hasServerProps )
2021-05-17 14:04:06 +02:00
const returnValue = {
customAppGetInitialProps : await customAppGetInitialPropsPromise ,
namedExports : await namedExportsPromise ,
isNextImageImported ,
hasSsrAmpPages ,
2021-06-11 11:29:40 +02:00
hasNonStaticErrorPage : nonStaticErrorPage ,
2021-01-10 02:12:13 +01:00
}
2021-05-17 14:04:06 +02:00
2021-08-12 21:54:49 +02:00
if ( ! sharedPool ) staticWorkers . end ( )
2021-05-17 14:04:06 +02:00
return returnValue
} )
if ( customAppGetInitialProps ) {
console . warn (
chalk . bold . yellow ( ` Warning: ` ) +
chalk . 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'
)
}
2019-04-24 10:48:43 +02:00
2020-12-21 17:02:41 +01:00
if ( ! hasSsrAmpPages ) {
requiredServerFiles . ignore . push (
path . relative (
dir ,
path . join (
2021-02-11 10:55:56 +01:00
path . dirname (
require . resolve (
'next/dist/compiled/@ampproject/toolbox-optimizer'
)
) ,
2020-12-21 17:02:41 +01:00
'**/*'
)
2020-12-16 21:46:55 +01:00
)
)
2020-12-21 17:02:41 +01:00
}
2020-01-27 23:50:59 +01:00
2021-10-26 06:22:45 +02:00
if ( config . outputFileTracing ) {
2021-10-23 01:49:38 +02:00
const { nodeFileTrace } =
require ( 'next/dist/compiled/@vercel/nft' ) as typeof import ( 'next/dist/compiled/@vercel/nft' )
const includeExcludeSpan = nextBuildSpan . traceChild (
'apply-include-excludes'
)
await includeExcludeSpan . traceAsyncFn ( async ( ) = > {
const globOrig =
require ( 'next/dist/compiled/glob' ) as typeof import ( 'next/dist/compiled/glob' )
const glob = ( pattern : string ) : Promise < string [ ] > = > {
return new Promise ( ( resolve , reject ) = > {
globOrig ( pattern , { cwd : dir } , ( err , files ) = > {
if ( err ) {
return reject ( err )
}
resolve ( files )
} )
2021-08-16 21:29:11 +02:00
} )
2021-10-23 01:49:38 +02:00
}
2021-08-16 21:29:11 +02:00
2021-10-23 01:49:38 +02:00
for ( let page of pageKeys ) {
await includeExcludeSpan
. traceChild ( 'include-exclude' , { page } )
. traceAsyncFn ( async ( ) = > {
const includeGlobs = pageTraceIncludes . get ( page )
const excludeGlobs = pageTraceExcludes . get ( page )
page = normalizePagePath ( page )
if ( ! includeGlobs ? . length && ! excludeGlobs ? . length ) {
return
}
const traceFile = path . join (
distDir ,
'server/pages' ,
` ${ page } .js.nft.json `
)
const pageDir = path . dirname ( traceFile )
const traceContent = JSON . parse (
await promises . readFile ( traceFile , 'utf8' )
)
let includes : string [ ] = [ ]
if ( includeGlobs ? . length ) {
for ( const includeGlob of includeGlobs ) {
const results = await glob ( includeGlob )
includes . push (
. . . results . map ( ( file ) = > {
return path . relative ( pageDir , path . join ( dir , file ) )
} )
)
}
}
const combined = new Set ( [ . . . traceContent . files , . . . includes ] )
if ( excludeGlobs ? . length ) {
const resolvedGlobs = excludeGlobs . map ( ( exclude ) = >
path . join ( dir , exclude )
)
combined . forEach ( ( file ) = > {
if ( isMatch ( path . join ( pageDir , file ) , resolvedGlobs ) ) {
combined . delete ( file )
}
} )
}
2021-08-16 21:29:11 +02:00
2021-10-23 01:49:38 +02:00
await promises . writeFile (
traceFile ,
JSON . stringify ( {
version : traceContent.version ,
files : [ . . . combined ] ,
} )
)
} )
2021-08-16 21:29:11 +02:00
}
2021-10-23 01:49:38 +02:00
} )
2021-08-16 21:29:11 +02:00
2021-10-23 01:49:38 +02:00
// 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 : string | undefined
// consider all lockFiles in tree in case user accidentally
// has both package-lock.json and yarn.lock
const lockFiles : string [ ] = (
await Promise . all (
[ 'package-lock.json' , 'yarn.lock' , 'pnpm-lock.yaml' ] . map ( ( file ) = >
findUp ( file , { cwd : dir } )
)
)
) . filter ( Boolean ) as any // TypeScript doesn't like this filter
const nextServerTraceOutput = path . join (
distDir ,
'next-server.js.nft.json'
)
const cachedTracePath = path . join (
distDir ,
'cache/next-server.js.nft.json'
)
if ( lockFiles . length > 0 ) {
const cacheHash = (
require ( 'crypto' ) as typeof import ( 'crypto' )
) . createHash ( 'sha256' )
cacheHash . update ( require ( 'next/package' ) . version )
2021-12-17 20:57:03 +01:00
cacheHash . update ( hasSsrAmpPages + '' )
cacheHash . update ( ciEnvironment . hasNextSupport + '' )
2021-10-23 01:49:38 +02:00
await Promise . all (
lockFiles . map ( async ( lockFile ) = > {
cacheHash . update ( await promises . readFile ( lockFile ) )
2021-10-22 20:55:45 +02:00
} )
)
2021-10-23 01:49:38 +02:00
cacheKey = cacheHash . digest ( 'hex' )
try {
const existingTrace = JSON . parse (
await promises . readFile ( cachedTracePath , 'utf8' )
)
if ( existingTrace . cacheKey === cacheKey ) {
await promises . copyFile ( cachedTracePath , nextServerTraceOutput )
return
}
} catch ( _ ) { }
2021-08-16 21:29:11 +02:00
}
2021-10-23 01:49:38 +02:00
const root = path . parse ( dir ) . root
const serverResult = await nodeFileTrace (
[ require . resolve ( 'next/dist/server/next-server' ) ] ,
{
base : root ,
processCwd : dir ,
ignore : [
'**/next/dist/pages/**/*' ,
'**/next/dist/compiled/webpack/(bundle4|bundle5).js' ,
'**/node_modules/webpack5/**/*' ,
2021-12-15 15:19:16 +01:00
'**/next/dist/server/lib/squoosh/**/*.wasm' ,
. . . ( ciEnvironment . hasNextSupport
? [
// only ignore image-optimizer code when
// this is being handled outside of next-server
'**/next/dist/server/image-optimizer.js' ,
'**/node_modules/sharp/**/*' ,
]
: [ ] ) ,
2021-12-17 20:57:03 +01:00
. . . ( ! hasSsrAmpPages
? [ '**/next/dist/compiled/@ampproject/toolbox-optimizer/**/*' ]
: [ ] ) ,
2021-10-23 01:49:38 +02:00
] ,
}
2021-10-22 20:55:45 +02:00
)
2021-10-23 01:49:38 +02:00
const tracedFiles = new Set ( )
serverResult . fileList . forEach ( ( file ) = > {
tracedFiles . add (
path . relative ( distDir , path . join ( root , file ) ) . replace ( /\\/g , '/' )
)
2021-10-22 20:55:45 +02:00
} )
2021-08-16 21:29:11 +02:00
2021-10-23 01:49:38 +02:00
await promises . writeFile (
nextServerTraceOutput ,
JSON . stringify ( {
version : 1 ,
cacheKey ,
files : [ . . . tracedFiles ] ,
} as {
version : number
files : string [ ]
} )
)
await promises . unlink ( cachedTracePath ) . catch ( ( ) = > { } )
await promises
. copyFile ( nextServerTraceOutput , cachedTracePath )
. catch ( ( ) = > { } )
} )
2021-08-16 21:29:11 +02:00
}
2020-12-21 17:02:41 +01:00
if ( serverPropsPages . size > 0 || ssgPages . size > 0 ) {
// We update the routes manifest after the build with the
// data routes since we can't determine these until after build
routesManifest . dataRoutes = getSortedRoutes ( [
. . . serverPropsPages ,
. . . ssgPages ,
] ) . map ( ( page ) = > {
const pagePath = normalizePagePath ( page )
const dataRoute = path . posix . join (
'/_next/data' ,
buildId ,
` ${ pagePath } .json `
)
2020-04-28 09:59:47 +02:00
2020-12-21 17:02:41 +01:00
let dataRouteRegex : string
let namedDataRouteRegex : string | undefined
let routeKeys : { [ named : string ] : string } | undefined
2020-04-28 09:59:47 +02:00
2020-12-21 17:02:41 +01:00
if ( isDynamicRoute ( page ) ) {
const routeRegex = getRouteRegex ( dataRoute . replace ( /\.json$/ , '' ) )
2020-04-28 09:59:47 +02:00
2020-12-21 17:02:41 +01:00
dataRouteRegex = normalizeRouteRegex (
2021-10-26 18:50:56 +02:00
routeRegex . re . source . replace ( /\(\?:\\\/\)\?\$$/ , ` \\ .json $ ` )
2020-12-21 17:02:41 +01:00
)
namedDataRouteRegex = routeRegex . namedRegex ! . replace (
/\(\?:\/\)\?\$$/ ,
2021-10-26 18:50:56 +02:00
` \\ .json $ `
2020-12-21 17:02:41 +01:00
)
routeKeys = routeRegex . routeKeys
} else {
dataRouteRegex = normalizeRouteRegex (
new RegExp (
` ^ ${ path . posix . join (
'/_next/data' ,
escapeStringRegexp ( buildId ) ,
` ${ pagePath } .json `
) } $ `
) . source
)
}
2020-01-27 23:50:59 +01:00
2020-12-21 17:02:41 +01:00
return {
page ,
routeKeys ,
dataRouteRegex ,
namedDataRouteRegex ,
}
} )
2019-06-14 02:08:19 +02:00
2020-12-21 17:02:41 +01:00
await promises . writeFile (
routesManifestPath ,
JSON . stringify ( routesManifest ) ,
'utf8'
)
}
2019-11-09 01:51:19 +01:00
2020-12-21 17:02:41 +01:00
// Since custom _app.js can wrap the 404 page we have to opt-out of static optimization if it has getInitialProps
// Only export the static 404 when there is no /_error present
const useStatic404 =
2021-11-06 12:27:40 +01:00
! hasConcurrentFeatures &&
! customAppGetInitialProps &&
( ! hasNonStaticErrorPage || hasPages404 )
2020-12-16 21:46:55 +01:00
2020-12-21 17:02:41 +01:00
if ( invalidPages . size > 0 ) {
2021-10-21 01:23:44 +02:00
const err = new Error (
2020-12-21 17:02:41 +01:00
` Build optimization failed: found page ${
invalidPages . size === 1 ? '' : 's'
} without a React Component as default export in \ n $ { [ . . . invalidPages ]
. map ( ( pg ) = > ` pages ${ pg } ` )
. join (
'\n'
2021-03-29 10:25:00 +02:00
) } \ n \ nSee https : //nextjs.org/docs/messages/page-without-valid-component for more info.\n`
2021-10-21 01:23:44 +02:00
) as NextError
err . code = 'BUILD_OPTIMIZATION_FAILED'
throw err
2019-05-22 18:36:53 +02:00
}
2020-10-09 11:13:05 +02:00
2020-12-21 17:02:41 +01:00
await writeBuildId ( distDir , buildId )
2021-02-17 23:52:43 +01:00
if ( config . experimental . optimizeCss ) {
2022-01-27 23:22:20 +01:00
const globOrig =
require ( 'next/dist/compiled/glob' ) as typeof import ( 'next/dist/compiled/glob' )
const cssFilePaths = await new Promise < string [ ] > ( ( resolve , reject ) = > {
globOrig ( '**/*.css' , { cwd : join ( distDir , 'static' ) } , ( err , files ) = > {
if ( err ) {
return reject ( err )
}
resolve ( files )
} )
} )
2021-02-17 23:52:43 +01:00
requiredServerFiles . files . push (
2022-01-27 23:22:20 +01:00
. . . cssFilePaths . map ( ( filePath ) = >
path . join ( config . distDir , 'static' , filePath )
)
2021-02-17 23:52:43 +01:00
)
}
2021-11-17 20:33:37 +01:00
const features : EventBuildFeatureUsage [ ] = [
{
featureName : 'experimental/optimizeCss' ,
invocationCount : config.experimental.optimizeCss ? 1 : 0 ,
} ,
{
featureName : 'optimizeFonts' ,
invocationCount : config.optimizeFonts ? 1 : 0 ,
} ,
]
telemetry . record (
features . map ( ( feature ) = > {
return {
eventName : EVENT_BUILD_FEATURE_USAGE ,
payload : feature ,
}
} )
)
2021-10-11 23:15:18 +02:00
2020-12-21 17:02:41 +01:00
await promises . writeFile (
path . join ( distDir , SERVER_FILES_MANIFEST ) ,
JSON . stringify ( requiredServerFiles ) ,
'utf8'
)
2022-01-04 01:47:18 +01:00
const middlewareManifest : MiddlewareManifest = JSON . parse (
await promises . readFile (
path . join ( distDir , SERVER_DIRECTORY , MIDDLEWARE_MANIFEST ) ,
'utf8'
)
)
2021-11-09 18:03:20 +01:00
const outputFileTracingRoot =
config . experimental . outputFileTracingRoot || dir
if ( config . experimental . outputStandalone ) {
await nextBuildSpan
. traceChild ( 'copy-traced-files' )
. traceAsyncFn ( async ( ) = > {
await copyTracedFiles (
dir ,
distDir ,
pageKeys ,
outputFileTracingRoot ,
2022-01-04 01:47:18 +01:00
requiredServerFiles . config ,
middlewareManifest
2021-11-09 18:03:20 +01:00
)
} )
}
2020-12-21 17:02:41 +01:00
const finalPrerenderRoutes : { [ route : string ] : SsgRoute } = { }
const tbdPrerenderRoutes : string [ ] = [ ]
let ssgNotFoundPaths : string [ ] = [ ]
if ( postCompileSpinner ) postCompileSpinner . stopAndPersist ( )
2021-01-27 12:24:00 +01:00
const { i18n } = config
2021-02-22 17:29:50 +01:00
const usedStaticStatusPages = STATIC_STATUS_PAGES . filter (
( page ) = >
mappedPages [ page ] && mappedPages [ page ] . startsWith ( 'private-next-pages' )
)
usedStaticStatusPages . forEach ( ( page ) = > {
2021-06-11 11:29:40 +02:00
if ( ! ssgPages . has ( page ) && ! customAppGetInitialProps ) {
2021-02-22 17:29:50 +01:00
staticPages . add ( page )
}
} )
const hasPages500 = usedStaticStatusPages . includes ( '/500' )
2021-06-11 11:29:40 +02:00
const useDefaultStatic500 =
! hasPages500 && ! hasNonStaticErrorPage && ! customAppGetInitialProps
2021-03-12 09:36:28 +01:00
const combinedPages = [ . . . staticPages , . . . ssgPages ]
2021-11-06 12:27:40 +01:00
if (
! hasConcurrentFeatures &&
( combinedPages . length > 0 || useStatic404 || useDefaultStatic500 )
) {
2021-03-12 09:36:28 +01:00
const staticGenerationSpan = nextBuildSpan . traceChild ( 'static-generation' )
await staticGenerationSpan . traceAsyncFn ( async ( ) = > {
detectConflictingPaths (
[
. . . combinedPages ,
. . . pageKeys . filter ( ( page ) = > ! combinedPages . includes ( page ) ) ,
] ,
ssgPages ,
additionalSsgPaths
)
2021-08-17 09:18:08 +02:00
const exportApp : typeof import ( '../export' ) . default =
require ( '../export' ) . default
2021-03-12 09:36:28 +01:00
const exportOptions = {
silent : false ,
buildExport : true ,
threads : config.experimental.cpus ,
pages : combinedPages ,
outdir : path.join ( distDir , 'export' ) ,
statusMessage : 'Generating static pages' ,
2021-08-12 21:54:49 +02:00
exportPageWorker : sharedPool
? staticWorkers . exportPage . bind ( staticWorkers )
: undefined ,
endWorker : sharedPool
? async ( ) = > {
await staticWorkers . end ( )
}
: undefined ,
2021-03-12 09:36:28 +01:00
}
const exportConfig : any = {
. . . config ,
initialPageRevalidationMap : { } ,
2021-07-16 11:21:44 +02:00
pageDurationMap : { } ,
2021-03-12 09:36:28 +01:00
ssgNotFoundPaths : [ ] as string [ ] ,
// Default map will be the collection of automatic statically exported
// pages and incremental pages.
// n.b. we cannot handle this above in combinedPages because the dynamic
// page must be in the `pages` array, but not in the mapping.
exportPathMap : ( defaultMap : any ) = > {
// Dynamically routed pages should be prerendered to be used as
// a client-side skeleton (fallback) while data is being fetched.
// This ensures the end-user never sees a 500 or slow response from the
// server.
//
// Note: prerendering disables automatic static optimization.
ssgPages . forEach ( ( page ) = > {
if ( isDynamicRoute ( page ) ) {
tbdPrerenderRoutes . push ( page )
if ( ssgStaticFallbackPages . has ( page ) ) {
// Override the rendering for the dynamic page to be treated as a
// fallback render.
if ( i18n ) {
defaultMap [ ` / ${ i18n . defaultLocale } ${ page } ` ] = {
page ,
query : { __nextFallback : true } ,
}
} else {
defaultMap [ page ] = { page , query : { __nextFallback : true } }
2020-12-21 17:02:41 +01:00
}
} else {
2021-03-12 09:36:28 +01:00
// Remove dynamically routed pages from the default path map when
// fallback behavior is disabled.
delete defaultMap [ page ]
2020-10-09 11:13:05 +02:00
}
2020-12-28 21:08:58 +01:00
}
2020-12-21 17:02:41 +01:00
} )
2021-03-12 09:36:28 +01:00
// Append the "well-known" routes we should prerender for, e.g. blog
// post slugs.
additionalSsgPaths . forEach ( ( routes , page ) = > {
const encodedRoutes = additionalSsgPathsEncoded . get ( page )
routes . forEach ( ( route , routeIdx ) = > {
defaultMap [ route ] = {
page ,
query : { __nextSsgPath : encodedRoutes?. [ routeIdx ] } ,
}
} )
} )
2021-01-10 02:12:13 +01:00
2021-03-12 09:36:28 +01:00
if ( useStatic404 ) {
defaultMap [ '/404' ] = {
page : hasPages404 ? '/404' : '/_error' ,
}
2020-12-21 17:02:41 +01:00
}
2020-01-20 15:10:24 +01:00
2021-03-12 09:36:28 +01:00
if ( useDefaultStatic500 ) {
defaultMap [ '/500' ] = {
page : '/_error' ,
}
2021-02-22 17:29:50 +01:00
}
2020-10-09 11:13:05 +02:00
2021-03-12 09:36:28 +01:00
if ( i18n ) {
for ( const page of [
. . . staticPages ,
. . . ssgPages ,
. . . ( useStatic404 ? [ '/404' ] : [ ] ) ,
. . . ( useDefaultStatic500 ? [ '/500' ] : [ ] ) ,
] ) {
const isSsg = ssgPages . has ( page )
const isDynamic = isDynamicRoute ( page )
const isFallback = isSsg && ssgStaticFallbackPages . has ( page )
for ( const locale of i18n . locales ) {
// skip fallback generation for SSG pages without fallback mode
if ( isSsg && isDynamic && ! isFallback ) continue
const outputPath = ` / ${ locale } ${ page === '/' ? '' : page } `
defaultMap [ outputPath ] = {
page : defaultMap [ page ] ? . page || page ,
query : { __nextLocale : locale } ,
}
2020-10-09 11:13:05 +02:00
2021-03-12 09:36:28 +01:00
if ( isFallback ) {
defaultMap [ outputPath ] . query . __nextFallback = true
}
2021-01-10 02:12:13 +01:00
}
2020-02-19 20:54:38 +01:00
2021-03-12 09:36:28 +01:00
if ( isSsg ) {
// remove non-locale prefixed variant from defaultMap
delete defaultMap [ page ]
}
2021-02-22 17:29:50 +01:00
}
}
2021-03-12 09:36:28 +01:00
return defaultMap
} ,
}
2020-06-17 05:40:07 +02:00
2021-09-13 15:49:29 +02:00
await exportApp ( dir , exportOptions , nextBuildSpan , exportConfig )
2019-05-22 18:36:53 +02:00
2021-03-12 09:36:28 +01:00
const postBuildSpinner = createSpinner ( {
prefixText : ` ${ Log . prefixes . info } Finalizing page optimization ` ,
} )
ssgNotFoundPaths = exportConfig . ssgNotFoundPaths
2019-08-06 22:26:01 +02:00
2021-03-12 09:36:28 +01:00
// remove server bundles that were exported
for ( const page of staticPages ) {
const serverBundle = getPagePath ( page , distDir , isLikeServerless )
await promises . unlink ( serverBundle )
}
const serverOutputDir = path . join (
distDir ,
isLikeServerless ? SERVERLESS_DIRECTORY : SERVER_DIRECTORY
)
2020-10-09 11:13:05 +02:00
2021-03-12 09:36:28 +01:00
const moveExportedPage = async (
originPage : string ,
page : string ,
file : string ,
isSsg : boolean ,
ext : 'html' | 'json' ,
additionalSsgFile = false
) = > {
return staticGenerationSpan
. traceChild ( 'move-exported-page' )
. traceAsyncFn ( async ( ) = > {
file = ` ${ file } . ${ ext } `
const orig = path . join ( exportOptions . outdir , file )
const pagePath = getPagePath (
originPage ,
distDir ,
isLikeServerless
)
const relativeDest = path
. relative (
serverOutputDir ,
2021-01-10 02:12:13 +01:00
path . join (
2021-03-12 09:36:28 +01:00
path . join (
pagePath ,
// strip leading / and then recurse number of nested dirs
// to place from base folder
originPage
. substr ( 1 )
. split ( '/' )
. map ( ( ) = > '..' )
. join ( '/' )
) ,
file
)
2021-01-10 02:12:13 +01:00
)
2021-03-12 09:36:28 +01:00
. replace ( /\\/g , '/' )
const dest = path . join (
distDir ,
isLikeServerless ? SERVERLESS_DIRECTORY : SERVER_DIRECTORY ,
relativeDest
2021-01-10 02:12:13 +01:00
)
2020-10-09 11:13:05 +02:00
2021-03-12 09:36:28 +01:00
if (
! isSsg &&
! (
// don't add static status page to manifest if it's
// the default generated version e.g. no pages/500
(
STATIC_STATUS_PAGES . includes ( page ) &&
! usedStaticStatusPages . includes ( page )
)
2021-02-22 17:29:50 +01:00
)
2021-03-12 09:36:28 +01:00
) {
pagesManifest [ page ] = relativeDest
}
2020-10-15 23:55:38 +02:00
2021-03-12 09:36:28 +01:00
const isNotFound = ssgNotFoundPaths . includes ( page )
// for SSG files with i18n the non-prerendered variants are
// output with the locale prefixed so don't attempt moving
// without the prefix
if ( ( ! i18n || additionalSsgFile ) && ! isNotFound ) {
await promises . mkdir ( path . dirname ( dest ) , { recursive : true } )
await promises . rename ( orig , dest )
} else if ( i18n && ! isSsg ) {
// this will be updated with the locale prefixed variant
// since all files are output with the locale prefix
delete pagesManifest [ page ]
}
2020-12-22 02:51:51 +01:00
2021-03-12 09:36:28 +01:00
if ( i18n ) {
if ( additionalSsgFile ) return
2020-10-09 11:13:05 +02:00
2021-03-12 09:36:28 +01:00
for ( const locale of i18n . locales ) {
const curPath = ` / ${ locale } ${ page === '/' ? '' : page } `
const localeExt = page === '/' ? path . extname ( file ) : ''
const relativeDestNoPages = relativeDest . substr (
'pages/' . length
)
2021-01-10 02:12:13 +01:00
2021-03-12 09:36:28 +01:00
if ( isSsg && ssgNotFoundPaths . includes ( curPath ) ) {
continue
}
const updatedRelativeDest = path
. join (
'pages' ,
locale + localeExt ,
// if it's the top-most index page we want it to be locale.EXT
// instead of locale/index.html
page === '/' ? '' : relativeDestNoPages
)
. replace ( /\\/g , '/' )
2021-01-10 02:12:13 +01:00
2021-03-12 09:36:28 +01:00
const updatedOrig = path . join (
exportOptions . outdir ,
2021-01-10 02:12:13 +01:00
locale + localeExt ,
2021-03-12 09:36:28 +01:00
page === '/' ? '' : file
)
const updatedDest = path . join (
distDir ,
isLikeServerless ? SERVERLESS_DIRECTORY : SERVER_DIRECTORY ,
updatedRelativeDest
2021-01-10 02:12:13 +01:00
)
2021-02-22 17:29:50 +01:00
2021-03-12 09:36:28 +01:00
if ( ! isSsg ) {
pagesManifest [ curPath ] = updatedRelativeDest
}
await promises . mkdir ( path . dirname ( updatedDest ) , {
recursive : true ,
} )
await promises . rename ( updatedOrig , updatedDest )
2021-01-10 02:12:13 +01:00
}
}
2021-03-12 09:36:28 +01:00
} )
}
2020-02-07 14:09:06 +01:00
2021-03-12 09:36:28 +01:00
// Only move /404 to /404 when there is no custom 404 as in that case we don't know about the 404 page
if ( ! hasPages404 && useStatic404 ) {
await moveExportedPage ( '/_error' , '/404' , '/404' , false , 'html' )
}
2019-09-24 10:50:04 +02:00
2021-03-12 09:36:28 +01:00
if ( useDefaultStatic500 ) {
await moveExportedPage ( '/_error' , '/500' , '/500' , false , 'html' )
}
2021-01-10 02:12:13 +01:00
2021-03-12 09:36:28 +01:00
for ( const page of combinedPages ) {
const isSsg = ssgPages . has ( page )
const isStaticSsgFallback = ssgStaticFallbackPages . has ( page )
const isDynamic = isDynamicRoute ( page )
const hasAmp = hybridAmpPages . has ( page )
const file = normalizePagePath ( page )
2021-01-27 12:24:00 +01:00
2021-07-16 11:21:44 +02:00
const pageInfo = pageInfos . get ( page )
const durationInfo = exportConfig . pageDurationMap [ page ]
if ( pageInfo && durationInfo ) {
// Set Build Duration
if ( pageInfo . ssgPageRoutes ) {
pageInfo . ssgPageDurations = pageInfo . ssgPageRoutes . map (
( pagePath ) = > durationInfo [ pagePath ]
)
}
pageInfo . pageDuration = durationInfo [ page ]
}
2021-03-12 09:36:28 +01:00
// The dynamic version of SSG pages are only prerendered if the
// fallback is enabled. Below, we handle the specific prerenders
// of these.
const hasHtmlOutput = ! ( isSsg && isDynamic && ! isStaticSsgFallback )
2020-10-16 11:27:34 +02:00
2021-03-12 09:36:28 +01:00
if ( hasHtmlOutput ) {
await moveExportedPage ( page , page , file , isSsg , 'html' )
}
2021-01-10 02:12:13 +01:00
2021-03-12 09:36:28 +01:00
if ( hasAmp && ( ! isSsg || ( isSsg && ! isDynamic ) ) ) {
const ampPage = ` ${ file } .amp `
await moveExportedPage ( page , ampPage , ampPage , isSsg , 'html' )
2019-09-24 10:50:04 +02:00
2021-03-12 09:36:28 +01:00
if ( isSsg ) {
await moveExportedPage ( page , ampPage , ampPage , isSsg , 'json' )
}
2021-02-22 17:29:50 +01:00
}
2021-03-12 09:36:28 +01:00
if ( isSsg ) {
// For a non-dynamic SSG page, we must copy its data file
// from export, we already moved the HTML file above
if ( ! isDynamic ) {
await moveExportedPage ( page , page , file , isSsg , 'json' )
if ( i18n ) {
// TODO: do we want to show all locale variants in build output
for ( const locale of i18n . locales ) {
const localePage = ` / ${ locale } ${ page === '/' ? '' : page } `
2021-10-19 02:27:20 +02:00
finalPrerenderRoutes [ localePage ] = {
initialRevalidateSeconds :
exportConfig . initialPageRevalidationMap [ localePage ] ,
srcRoute : null ,
dataRoute : path.posix.join (
'/_next/data' ,
buildId ,
` ${ file } .json `
) ,
2021-01-27 12:24:00 +01:00
}
}
2021-03-12 09:36:28 +01:00
} else {
finalPrerenderRoutes [ page ] = {
initialRevalidateSeconds :
exportConfig . initialPageRevalidationMap [ page ] ,
srcRoute : null ,
dataRoute : path.posix.join (
'/_next/data' ,
buildId ,
` ${ file } .json `
) ,
}
2021-01-10 02:12:13 +01:00
}
2021-03-12 09:36:28 +01:00
// Set Page Revalidation Interval
if ( pageInfo ) {
pageInfo . initialRevalidateSeconds =
exportConfig . initialPageRevalidationMap [ page ]
2021-02-22 17:29:50 +01:00
}
2021-03-12 09:36:28 +01:00
} else {
// For a dynamic SSG page, we did not copy its data exports and only
// copy the fallback HTML file (if present).
// We must also copy specific versions of this page as defined by
// `getStaticPaths` (additionalSsgPaths).
const extraRoutes = additionalSsgPaths . get ( page ) || [ ]
for ( const route of extraRoutes ) {
const pageFile = normalizePagePath ( route )
2020-12-21 17:02:41 +01:00
await moveExportedPage (
page ,
2021-03-12 09:36:28 +01:00
route ,
pageFile ,
2021-01-27 12:24:00 +01:00
isSsg ,
2020-12-21 17:02:41 +01:00
'html' ,
true
)
await moveExportedPage (
page ,
2021-03-12 09:36:28 +01:00
route ,
pageFile ,
2021-01-27 12:24:00 +01:00
isSsg ,
2020-12-21 17:02:41 +01:00
'json' ,
true
)
2021-03-12 09:36:28 +01:00
if ( hasAmp ) {
const ampPage = ` ${ pageFile } .amp `
await moveExportedPage (
page ,
ampPage ,
ampPage ,
isSsg ,
'html' ,
true
)
await moveExportedPage (
page ,
ampPage ,
ampPage ,
isSsg ,
'json' ,
true
)
}
2021-01-10 02:12:13 +01:00
2021-03-12 09:36:28 +01:00
finalPrerenderRoutes [ route ] = {
initialRevalidateSeconds :
exportConfig . initialPageRevalidationMap [ route ] ,
srcRoute : page ,
dataRoute : path.posix.join (
'/_next/data' ,
buildId ,
` ${ normalizePagePath ( route ) } .json `
) ,
}
// Set route Revalidation Interval
if ( pageInfo ) {
pageInfo . initialRevalidateSeconds =
exportConfig . initialPageRevalidationMap [ route ]
}
2020-12-21 17:02:41 +01:00
}
2020-08-04 10:42:18 +02:00
}
2019-09-24 10:50:04 +02:00
}
}
2020-12-21 17:02:41 +01:00
2021-03-12 09:36:28 +01:00
// remove temporary export folder
await recursiveDelete ( exportOptions . outdir )
await promises . rmdir ( exportOptions . outdir )
await promises . writeFile (
manifestPath ,
JSON . stringify ( pagesManifest , null , 2 ) ,
'utf8'
)
2020-12-21 17:02:41 +01:00
2021-03-12 09:36:28 +01:00
if ( postBuildSpinner ) postBuildSpinner . stopAndPersist ( )
console . log ( )
} )
}
2019-08-06 22:26:01 +02:00
2020-12-21 17:02:41 +01:00
const analysisEnd = process . hrtime ( analysisBegin )
telemetry . record (
eventBuildOptimize ( pagePaths , {
durationInSeconds : analysisEnd [ 0 ] ,
staticPageCount : staticPages.size ,
staticPropsPageCount : ssgPages.size ,
serverPropsPageCount : serverPropsPages.size ,
ssrPageCount :
pagePaths . length -
( staticPages . size + ssgPages . size + serverPropsPages . size ) ,
hasStatic404 : useStatic404 ,
hasReportWebVitals : namedExports?.includes ( 'reportWebVitals' ) ? ? false ,
2021-03-26 16:19:48 +01:00
rewritesCount : combinedRewrites.length ,
2020-12-21 17:02:41 +01:00
headersCount : headers.length ,
redirectsCount : redirects.length - 1 , // reduce one for trailing slash
2021-03-24 17:50:16 +01:00
headersWithHasCount : headers.filter ( ( r : any ) = > ! ! r . has ) . length ,
2021-03-26 16:19:48 +01:00
rewritesWithHasCount : combinedRewrites.filter ( ( r : any ) = > ! ! r . has )
. length ,
2021-03-24 17:50:16 +01:00
redirectsWithHasCount : redirects.filter ( ( r : any ) = > ! ! r . has ) . length ,
2021-10-22 22:12:12 +02:00
middlewareCount : pageKeys.filter ( ( page ) = > MIDDLEWARE_ROUTE . test ( page ) )
. length ,
2020-12-21 17:02:41 +01:00
} )
2020-05-02 06:10:19 +02:00
)
2019-11-09 23:34:53 +01:00
2021-10-05 21:31:48 +02:00
if ( telemetryPlugin ) {
const events = eventBuildFeatureUsage ( telemetryPlugin )
telemetry . record ( events )
}
2020-12-21 17:02:41 +01:00
if ( ssgPages . size > 0 ) {
const finalDynamicRoutes : PrerenderManifest [ 'dynamicRoutes' ] = { }
tbdPrerenderRoutes . forEach ( ( tbdRoute ) = > {
const normalizedRoute = normalizePagePath ( tbdRoute )
const dataRoute = path . posix . join (
'/_next/data' ,
buildId ,
` ${ normalizedRoute } .json `
)
2019-08-29 18:43:06 +02:00
2020-12-21 17:02:41 +01:00
finalDynamicRoutes [ tbdRoute ] = {
routeRegex : normalizeRouteRegex ( getRouteRegex ( tbdRoute ) . re . source ) ,
dataRoute ,
fallback : ssgBlockingFallbackPages.has ( tbdRoute )
? null
: ssgStaticFallbackPages . has ( tbdRoute )
? ` ${ normalizedRoute } .html `
: false ,
dataRouteRegex : normalizeRouteRegex (
getRouteRegex ( dataRoute . replace ( /\.json$/ , '' ) ) . re . source . replace (
/\(\?:\\\/\)\?\$$/ ,
'\\.json$'
)
) ,
}
} )
const prerenderManifest : PrerenderManifest = {
2021-01-27 12:24:00 +01:00
version : 3 ,
2020-12-21 17:02:41 +01:00
routes : finalPrerenderRoutes ,
dynamicRoutes : finalDynamicRoutes ,
notFoundRoutes : ssgNotFoundPaths ,
preview : previewProps ,
}
2019-10-01 04:08:01 +02:00
2020-12-21 17:02:41 +01:00
await promises . writeFile (
path . join ( distDir , PRERENDER_MANIFEST ) ,
JSON . stringify ( prerenderManifest ) ,
'utf8'
)
await generateClientSsgManifest ( prerenderManifest , {
distDir ,
buildId ,
2021-01-27 12:24:00 +01:00
locales : config.i18n?.locales || [ ] ,
2020-12-21 17:02:41 +01:00
} )
} else {
const prerenderManifest : PrerenderManifest = {
2021-01-27 12:24:00 +01:00
version : 3 ,
2020-12-21 17:02:41 +01:00
routes : { } ,
dynamicRoutes : { } ,
preview : previewProps ,
notFoundRoutes : [ ] ,
2019-10-01 04:08:01 +02:00
}
2020-12-21 17:02:41 +01:00
await promises . writeFile (
path . join ( distDir , PRERENDER_MANIFEST ) ,
JSON . stringify ( prerenderManifest ) ,
'utf8'
)
2019-09-24 10:50:04 +02:00
}
2021-10-22 08:40:57 +02:00
await promises . writeFile (
path . join (
distDir ,
CLIENT_STATIC_FILES_PATH ,
buildId ,
'_middlewareManifest.js'
) ,
` self.__MIDDLEWARE_MANIFEST= ${ devalue (
2021-10-26 22:18:08 +02:00
middlewareManifest . clientInfo
2021-10-22 08:40:57 +02:00
) } ; self . __MIDDLEWARE_MANIFEST_CB && self . __MIDDLEWARE_MANIFEST_CB ( ) `
)
2021-10-20 19:52:11 +02:00
2020-12-21 17:02:41 +01:00
const images = { . . . config . images }
const { deviceSizes , imageSizes } = images
2021-07-12 23:38:57 +02:00
; ( images as any ) . sizes = [ . . . deviceSizes , . . . imageSizes ]
2020-12-21 17:02:41 +01:00
2020-05-02 06:10:19 +02:00
await promises . writeFile (
2020-12-21 17:02:41 +01:00
path . join ( distDir , IMAGES_MANIFEST ) ,
JSON . stringify ( {
version : 1 ,
images ,
} ) ,
2020-02-10 23:43:34 +01:00
'utf8'
)
2020-05-02 06:10:19 +02:00
await promises . writeFile (
2020-12-21 17:02:41 +01:00
path . join ( distDir , EXPORT_MARKER ) ,
JSON . stringify ( {
version : 1 ,
hasExportPathMap : typeof config . exportPathMap === 'function' ,
exportTrailingSlash : config.trailingSlash === true ,
isNextImageImported : isNextImageImported === true ,
} ) ,
2019-08-06 22:26:01 +02:00
'utf8'
)
2020-12-21 17:02:41 +01:00
await promises . unlink ( path . join ( distDir , EXPORT_DETAIL ) ) . catch ( ( err ) = > {
if ( err . code === 'ENOENT' ) {
return Promise . resolve ( )
}
return Promise . reject ( err )
} )
2019-08-06 22:26:01 +02:00
2021-11-09 18:03:20 +01:00
if ( config . experimental . outputStandalone ) {
for ( const file of [
. . . requiredServerFiles . files ,
path . join ( config . distDir , SERVER_FILES_MANIFEST ) ,
] ) {
const filePath = path . join ( dir , file )
await promises . copyFile (
filePath ,
path . join (
distDir ,
'standalone' ,
path . relative ( outputFileTracingRoot , filePath )
)
)
}
await recursiveCopy (
path . join ( distDir , SERVER_DIRECTORY , 'pages' ) ,
path . join (
distDir ,
'standalone' ,
path . relative ( outputFileTracingRoot , distDir ) ,
SERVER_DIRECTORY ,
'pages'
2022-01-04 01:47:18 +01:00
) ,
{ overwrite : true }
2021-11-09 18:03:20 +01:00
)
}
2020-12-21 17:02:41 +01:00
staticPages . forEach ( ( pg ) = > allStaticPages . add ( pg ) )
pageInfos . forEach ( ( info : PageInfo , key : string ) = > {
allPageInfos . set ( key , info )
} )
2020-10-26 21:07:52 +01:00
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
await nextBuildSpan . traceChild ( 'print-tree-view' ) . traceAsyncFn ( ( ) = >
2021-01-10 02:12:13 +01:00
printTreeView ( Object . keys ( mappedPages ) , allPageInfos , isLikeServerless , {
2020-12-21 17:02:41 +01:00
distPath : distDir ,
buildId : buildId ,
pagesDir ,
useStatic404 ,
pageExtensions : config.pageExtensions ,
buildManifest ,
2021-05-14 16:29:49 +02:00
gzipSize : config.experimental.gzipSize ,
2021-01-10 02:12:13 +01:00
} )
2020-12-21 17:02:41 +01:00
)
2020-10-16 13:10:01 +02:00
2020-12-21 17:02:41 +01:00
if ( debugOutput ) {
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
nextBuildSpan
. traceChild ( 'print-custom-routes' )
. traceFn ( ( ) = > printCustomRoutes ( { redirects , rewrites , headers } ) )
2019-12-13 20:30:22 +01:00
}
2019-01-25 18:36:29 +01:00
2020-12-21 17:02:41 +01:00
if ( config . analyticsId ) {
console . log (
chalk . bold . green ( 'Next.js Analytics' ) +
' is enabled for this production build. ' +
"You'll receive a Real Experience Score computed by all of your visitors."
)
console . log ( '' )
2019-12-12 17:20:24 +01:00
}
2019-08-18 21:45:39 +02:00
Telemetry-compatible tracing (#22713)
A number of changes here. I recommend viewing the diff with the <a href="?w=1">whitespace flag enabled</a>.
- OpenTelemetry is replaced with a custom and lightweight tracing solution.
- Three trace targets are currently supported: console, Zipkin, and NextJS.
- Tracing is now governed by environment variables rather than `--require instrument.js`.
+ `TRACE_TARGET`: one of `CONSOLE`, `ZIPKIN`, or `TELEMETRY`; defaults to `TELEMETRY` if unset or invalid.
+ `TRACE_ID`: an 8-byte hex-encoded value used as the Zipkin trace ID; if not provided, this value will be randomly generated and passed down to subprocesses.
Other sundry:
- I'm missing something, probably a setup step, with the Zipkin target. Traces are captured successfully, but you have to manually enter the Trace ID in order to view the trace - it doesn't show up in queries.
- I'm generally unhappy with [this commit](https://github.com/vercel/next.js/pull/22713/commits/235cedcb3ead76b630b4c8aa695f904489da2831). It is... untidy to provide a telemetry object via `setGlobal`, but I don't have a ready alternative. Is `distDir` strictly required when creating a new Telemetry object? I didn't dig too deep here.
As noted, there are a lot of changes, so it'd be great if a reviewer could:
- [ ] pull down the branch and try to break it
- [ ] check the Zipkin traces and identify possible regressions in the functionality
Closes #22570
Fixes #22574
2021-03-10 22:00:20 +01:00
await nextBuildSpan
. traceChild ( 'telemetry-flush' )
. traceAsyncFn ( ( ) = > telemetry . flush ( ) )
2020-12-21 17:02:41 +01:00
} )
2021-08-17 09:18:47 +02:00
// Ensure all traces are flushed before finishing the command
await flushAllTraces ( )
return buildResult
2018-12-03 14:18:52 +01:00
}
2020-03-02 18:14:40 +01:00
function generateClientSsgManifest (
prerenderManifest : PrerenderManifest ,
2021-01-27 12:24:00 +01:00
{
buildId ,
distDir ,
locales ,
} : { buildId : string ; distDir : string ; locales : string [ ] }
2020-03-02 18:14:40 +01:00
) {
2021-11-25 10:46:00 +01:00
const ssgPages = new Set < string > ( [
2020-03-02 18:14:40 +01:00
. . . Object . entries ( prerenderManifest . routes )
// Filter out dynamic routes
. filter ( ( [ , { srcRoute } ] ) = > srcRoute == null )
2021-01-27 12:24:00 +01:00
. map ( ( [ route ] ) = > normalizeLocalePath ( route , locales ) . pathname ) ,
2020-03-02 18:14:40 +01:00
. . . Object . keys ( prerenderManifest . dynamicRoutes ) ,
] )
const clientSsgManifestContent = ` self.__SSG_MANIFEST= ${ devalue (
ssgPages
) } ; self . __SSG_MANIFEST_CB && self . __SSG_MANIFEST_CB ( ) `
2020-11-18 19:30:00 +01:00
writeFileSync (
path . join ( distDir , CLIENT_STATIC_FILES_PATH , buildId , '_ssgManifest.js' ) ,
clientSsgManifestContent
2020-03-02 18:14:40 +01:00
)
}
2021-10-05 21:31:48 +02:00
function isTelemetryPlugin ( plugin : unknown ) : plugin is TelemetryPlugin {
return plugin instanceof TelemetryPlugin
}
2021-10-20 19:52:11 +02:00
function pageToRoute ( page : string ) {
const routeRegex = getRouteRegex ( page )
return {
page ,
regex : normalizeRouteRegex ( routeRegex . re . source ) ,
routeKeys : routeRegex.routeKeys ,
namedRegex : routeRegex.namedRegex ,
}
}