Skip to content

Commit a3707f5

Browse files
committed
feat: add deploymentId config (#63198)
This PR stabilizes an experimental feature that was added in a previous PR #50470 It allows the user to set `deploymentId` in `next.config.js`, which is a unique identifier for a deployment that will be included in each request's query string or header. This PR is easier to review with whitespace hidden: https://github.com/vercel/next.js/pull/63198/files?w=1 Closes NEXT-2789
1 parent f904dcd commit a3707f5

File tree

12 files changed

+83
-117
lines changed

12 files changed

+83
-117
lines changed

docs/02-app/01-building-your-application/10-deploying/index.mdx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,11 +210,13 @@ module.exports = {
210210

211211
### Version Skew
212212

213-
Next.js will automatically mitigate most instances of [version skew](https://www.industrialempathy.com/posts/version-skew/) and automatically reload the application to retrieve new assets when detected. For example, if there is a mismatch in the build ID, transitions between pages will perform a hard navigation versus using a prefetched value.
213+
Next.js will automatically mitigate most instances of [version skew](https://www.industrialempathy.com/posts/version-skew/) and automatically reload the application to retrieve new assets when detected. For example, if there is a mismatch in the `deploymentId`, transitions between pages will perform a hard navigation versus using a prefetched value.
214214

215215
When the application is reloaded, there may be a loss of application state if it's not designed to persist between page navigations. For example, using URL state or local storage would persist state after a page refresh. However, component state like `useState` would be lost in such navigations.
216216

217-
Vercel provides additional [skew protection](https://vercel.com/docs/deployments/skew-protection?utm_source=next-site&utm_medium=docs&utm_campaign=next-website) for Next.js applications to ensure assets and functions from the previous build are still available while the new build is being deployed.
217+
Vercel provides additional [skew protection](https://vercel.com/docs/deployments/skew-protection?utm_source=next-site&utm_medium=docs&utm_campaign=next-website) for Next.js applications to ensure assets and functions from the previous version are still available to older clients, even after the new version is deployed.
218+
219+
You can manually configure the `deploymentId` property in your `next.config.js` file to ensure each request uses either `?dpl` query string or `x-deployment-id` header.
218220

219221
<PagesOnly>
220222

packages/next/src/build/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,7 @@ export default async function build(
730730
})
731731
)
732732

733-
process.env.NEXT_DEPLOYMENT_ID = config.experimental.deploymentId || ''
733+
process.env.NEXT_DEPLOYMENT_ID = config.deploymentId || ''
734734
NextBuildContext.config = config
735735

736736
let configOutDir = 'out'

packages/next/src/build/webpack/plugins/define-env-plugin.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,8 @@ export function getDefineEnv({
9696
),
9797
'process.env.NEXT_MINIMAL': JSON.stringify(''),
9898
'process.env.__NEXT_PPR': JSON.stringify(config.experimental.ppr === true),
99-
'process.env.__NEXT_ACTIONS_DEPLOYMENT_ID': JSON.stringify(
100-
config.experimental.useDeploymentIdServerActions
101-
),
10299
'process.env.NEXT_DEPLOYMENT_ID': JSON.stringify(
103-
config.experimental.deploymentId || false
100+
config.deploymentId || false
104101
),
105102
'process.env.__NEXT_FETCH_CACHE_KEY_PREFIX':
106103
JSON.stringify(fetchCacheKeyPrefix),

packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,7 @@ async function fetchServerAction(
7070
Accept: RSC_CONTENT_TYPE_HEADER,
7171
[ACTION]: actionId,
7272
[NEXT_ROUTER_STATE_TREE]: encodeURIComponent(JSON.stringify(state.tree)),
73-
...(process.env.__NEXT_ACTIONS_DEPLOYMENT_ID &&
74-
process.env.NEXT_DEPLOYMENT_ID
73+
...(process.env.NEXT_DEPLOYMENT_ID
7574
? {
7675
'x-deployment-id': process.env.NEXT_DEPLOYMENT_ID,
7776
}

packages/next/src/export/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ export async function exportAppImpl(
505505
}
506506
: {}),
507507
strictNextHead: !!nextConfig.experimental.strictNextHead,
508-
deploymentId: nextConfig.experimental.deploymentId,
508+
deploymentId: nextConfig.deploymentId,
509509
experimental: {
510510
ppr: nextConfig.experimental.ppr === true,
511511
missingSuspenseWithCSRBailout:

packages/next/src/server/base-server.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -501,13 +501,12 @@ export default abstract class Server<ServerOptions extends Options = Options> {
501501
this.nextFontManifest = this.getNextFontManifest()
502502

503503
if (process.env.NEXT_RUNTIME !== 'edge') {
504-
process.env.NEXT_DEPLOYMENT_ID =
505-
this.nextConfig.experimental.deploymentId || ''
504+
process.env.NEXT_DEPLOYMENT_ID = this.nextConfig.deploymentId || ''
506505
}
507506

508507
this.renderOpts = {
509508
trailingSlash: this.nextConfig.trailingSlash,
510-
deploymentId: this.nextConfig.experimental.deploymentId,
509+
deploymentId: this.nextConfig.deploymentId,
511510
strictNextHead: !!this.nextConfig.experimental.strictNextHead,
512511
poweredByHeader: this.nextConfig.poweredByHeader,
513512
canonicalBase: this.nextConfig.amp.canonicalBase || '',

packages/next/src/server/config-schema.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ export const configSchema: zod.ZodType<NextConfig> = z.lazy(() =>
204204
z.literal('use-credentials'),
205205
])
206206
.optional(),
207+
deploymentId: z.string().optional(),
207208
devIndicators: z
208209
.object({
209210
buildActivity: z.boolean().optional(),
@@ -247,9 +248,6 @@ export const configSchema: zod.ZodType<NextConfig> = z.lazy(() =>
247248
memoryBasedWorkersCount: z.boolean().optional(),
248249
craCompat: z.boolean().optional(),
249250
caseSensitiveRoutes: z.boolean().optional(),
250-
useDeploymentId: z.boolean().optional(),
251-
useDeploymentIdServerActions: z.boolean().optional(),
252-
deploymentId: z.string().optional(),
253251
disableOptimizedLoading: z.boolean().optional(),
254252
disablePostcssPresetEnv: z.boolean().optional(),
255253
esmExternals: z.union([z.boolean(), z.literal('loose')]).optional(),

packages/next/src/server/config-shared.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,6 @@ export interface NextJsWebpackConfig {
160160

161161
export interface ExperimentalConfig {
162162
caseSensitiveRoutes?: boolean
163-
useDeploymentId?: boolean
164-
useDeploymentIdServerActions?: boolean
165-
deploymentId?: string
166163
appDocumentPreloading?: boolean
167164
strictNextHead?: boolean
168165
clientRouterFilter?: boolean
@@ -591,6 +588,11 @@ export interface NextConfig extends Record<string, any> {
591588
canonicalBase?: string
592589
}
593590

591+
/**
592+
* A unique identifier for a deployment that will be included in each request's query string or header.
593+
*/
594+
deploymentId?: string
595+
594596
/**
595597
* Deploy a Next.js application under a sub-path of a domain
596598
*
@@ -812,9 +814,6 @@ export const defaultConfig: NextConfig = {
812814
serverMinification: true,
813815
serverSourceMaps: false,
814816
caseSensitiveRoutes: false,
815-
useDeploymentId: false,
816-
deploymentId: undefined,
817-
useDeploymentIdServerActions: false,
818817
appDocumentPreloading: undefined,
819818
clientRouterFilter: true,
820819
clientRouterFilterRedirects: false,

packages/next/src/server/config.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -601,16 +601,8 @@ function assignDefaults(
601601
}
602602

603603
// only leverage deploymentId
604-
if (result.experimental?.useDeploymentId && process.env.NEXT_DEPLOYMENT_ID) {
605-
if (!result.experimental) {
606-
result.experimental = {}
607-
}
608-
result.experimental.deploymentId = process.env.NEXT_DEPLOYMENT_ID
609-
}
610-
611-
// can't use this one without the other
612-
if (result.experimental?.useDeploymentIdServerActions) {
613-
result.experimental.useDeploymentId = true
604+
if (process.env.NEXT_DEPLOYMENT_ID) {
605+
result.deploymentId = process.env.NEXT_DEPLOYMENT_ID
614606
}
615607

616608
// use the closest lockfile as tracing root

packages/next/src/server/next-server.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,7 @@ export default class NextNodeServer extends BaseServer {
194194
if (this.renderOpts.nextScriptWorkers) {
195195
process.env.__NEXT_SCRIPT_WORKERS = JSON.stringify(true)
196196
}
197-
process.env.NEXT_DEPLOYMENT_ID =
198-
this.nextConfig.experimental.deploymentId || ''
197+
process.env.NEXT_DEPLOYMENT_ID = this.nextConfig.deploymentId || ''
199198

200199
if (!this.minimalMode) {
201200
this.imageResponseCache = new ResponseCache(this.minimalMode)

0 commit comments

Comments
 (0)