From ead02bd42ed0531b2ef10cce6d8a74790250ad37 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Fri, 22 Apr 2022 02:20:37 +0200 Subject: [PATCH 1/7] feat: add process.env.__NEXT_RUNTIME --- packages/next/bin/next.ts | 1 + packages/next/build/webpack-config.ts | 5 ++- packages/next/lib/chalk.ts | 6 ++-- packages/next/pages/_document.tsx | 2 +- packages/next/server/base-server.ts | 9 ++++-- packages/next/server/render.tsx | 31 +++++++++++++------ packages/next/server/web/sandbox/context.ts | 4 ++- packages/next/shared/lib/isomorphic/path.ts | 7 +++-- .../app/pages/runtime.js | 2 +- 9 files changed, 44 insertions(+), 23 deletions(-) diff --git a/packages/next/bin/next.ts b/packages/next/bin/next.ts index dead0052077f..2eafc3ac2db2 100755 --- a/packages/next/bin/next.ts +++ b/packages/next/bin/next.ts @@ -104,6 +104,7 @@ if (process.env.NODE_ENV) { } ;(process.env as any).NODE_ENV = process.env.NODE_ENV || defaultEnv +;(process.env as any).__NEXT_RUNTIME = 'nodejs' // x-ref: https://github.com/vercel/next.js/pull/34688#issuecomment-1047994505 if (process.versions.pnp === '3') { diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index 488c64fa5ea7..248cbe85dd3d 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -1325,7 +1325,10 @@ export default async function getBaseWebpackConfig( dev ? 'development' : 'production' ), 'process.env.__NEXT_CROSS_ORIGIN': JSON.stringify(crossOrigin), - 'process.browser': JSON.stringify(targetWeb), + 'process.browser': JSON.stringify(!isServer), + 'process.env.__NEXT_RUNTIME': JSON.stringify( + !isServer ? 'browser' : isEdgeRuntime ? 'edge' : 'nodejs' + ), 'process.env.__NEXT_TEST_MODE': JSON.stringify( process.env.__NEXT_TEST_MODE ), diff --git a/packages/next/lib/chalk.ts b/packages/next/lib/chalk.ts index f25f56ec3522..e6b4b89e2731 100644 --- a/packages/next/lib/chalk.ts +++ b/packages/next/lib/chalk.ts @@ -1,9 +1,9 @@ let chalk: typeof import('next/dist/compiled/chalk') -if (!process.browser) { - chalk = require('next/dist/compiled/chalk') -} else { +if (process.env.__NEXT_RUNTIME === 'edge') { chalk = require('./web/chalk').default +} else { + chalk = require('next/dist/compiled/chalk') } export default chalk diff --git a/packages/next/pages/_document.tsx b/packages/next/pages/_document.tsx index b989817a6a7e..d308cf6710a8 100644 --- a/packages/next/pages/_document.tsx +++ b/packages/next/pages/_document.tsx @@ -80,7 +80,7 @@ function getPreNextWorkerScripts(context: HtmlProps, props: OriginProps) { const { assetPrefix, scriptLoader, crossOrigin, nextScriptWorkers } = context // disable `nextScriptWorkers` in edge runtime - if (!nextScriptWorkers || process.browser) return null + if (!nextScriptWorkers || process.env.__NEXT_RUNTIME === 'edge') return null try { let { diff --git a/packages/next/server/base-server.ts b/packages/next/server/base-server.ts index 4df12587419f..26846469990a 100644 --- a/packages/next/server/base-server.ts +++ b/packages/next/server/base-server.ts @@ -1153,7 +1153,7 @@ export default abstract class Server { (isServerComponent && !hasServerProps && !hasGetInitialProps && - !process.browser) + process.env.__NEXT_RUNTIME !== 'edge') // Toggle whether or not this is a Data request const isDataReq = @@ -1238,7 +1238,7 @@ export default abstract class Server { if (hasServerProps || isSSG) { // For the edge runtime, we don't support preview mode in SSG. - if (!process.browser) { + if (process.env.__NEXT_RUNTIME !== 'edge') { const { tryGetPreviewData } = require('./api-utils/node') as typeof import('./api-utils/node') previewData = tryGetPreviewData(req, res, this.renderOpts.previewProps) @@ -1756,7 +1756,10 @@ export default abstract class Server { ) if (!isWrappedError) { - if ((this.minimalMode && !process.browser) || this.renderOpts.dev) { + if ( + (this.minimalMode && process.env.__NEXT_RUNTIME !== 'edge') || + this.renderOpts.dev + ) { if (isError(err)) err.page = page throw err } diff --git a/packages/next/server/render.tsx b/packages/next/server/render.tsx index 95399d2bb986..bb0612e3115a 100644 --- a/packages/next/server/render.tsx +++ b/packages/next/server/render.tsx @@ -89,7 +89,7 @@ let postProcess: typeof import('../shared/lib/post-process').default const DOCTYPE = '' -if (!process.browser) { +if (process.env.__NEXT_RUNTIME !== 'edge') { require('./node-polyfill-web-streams') optimizeAmp = require('./optimize-amp').default getFontDefinitionFromManifest = @@ -517,7 +517,9 @@ export async function renderToHTML( Uint8Array, Uint8Array > | null = - isServerComponent && !process.browser ? new TransformStream() : null + isServerComponent && process.env.__NEXT_RUNTIME !== 'edge' + ? new TransformStream() + : null if (isServerComponent) { serverComponentsInlinedTransformStream = new TransformStream() @@ -699,7 +701,11 @@ export async function renderToHTML( let isPreview let previewData: PreviewData - if ((isSSG || getServerSideProps) && !isFallback && !process.browser) { + if ( + (isSSG || getServerSideProps) && + !isFallback && + process.env.__NEXT_RUNTIME !== 'edge' + ) { // Reads of this are cached on the `req` object, so this should resolve // instantly. There's no need to pass this data down from a previous // invoke, where we'd have to consider server & serverless. @@ -769,7 +775,8 @@ export async function renderToHTML( } // Disable AMP under the web environment - const inAmpMode = !process.browser && isInAmpMode(ampState) + const inAmpMode = + process.env.__NEXT_RUNTIME !== 'edge' && isInAmpMode(ampState) const reactLoadableModules: string[] = [] @@ -1302,7 +1309,7 @@ export async function renderToHTML( | typeof Document | undefined - if (process.browser && Document.getInitialProps) { + if (process.env.__NEXT_RUNTIME === 'edge' && Document.getInitialProps) { // In the Edge runtime, `Document.getInitialProps` isn't supported. // We throw an error here if it's customized. if (!builtinDocument) { @@ -1312,7 +1319,10 @@ export async function renderToHTML( } } - if ((isServerComponent || process.browser) && Document.getInitialProps) { + if ( + (isServerComponent || process.env.__NEXT_RUNTIME === 'edge') && + Document.getInitialProps + ) { if (builtinDocument) { Document = builtinDocument } else { @@ -1542,7 +1552,7 @@ export async function renderToHTML( const hasDocumentGetInitialProps = !( isServerComponent || - process.browser || + process.env.__NEXT_RUNTIME === 'edge' || !Document.getInitialProps ) @@ -1561,7 +1571,7 @@ export async function renderToHTML( const { docProps } = (documentInitialPropsRes as any) || {} const documentElement = () => { - if (isServerComponent || process.browser) { + if (isServerComponent || process.env.__NEXT_RUNTIME === 'edge') { return (Document as any)() } @@ -1752,7 +1762,8 @@ export async function renderToHTML( return html } : null, - !process.browser && process.env.__NEXT_OPTIMIZE_FONTS + process.env.__NEXT_RUNTIME !== 'edge' && + process.env.__NEXT_OPTIMIZE_FONTS ? async (html: string) => { return await postProcess( html, @@ -1763,7 +1774,7 @@ export async function renderToHTML( ) } : null, - !process.browser && renderOpts.optimizeCss + process.env.__NEXT_RUNTIME !== 'edge' && renderOpts.optimizeCss ? async (html: string) => { // eslint-disable-next-line import/no-extraneous-dependencies const Critters = require('critters') diff --git a/packages/next/server/web/sandbox/context.ts b/packages/next/server/web/sandbox/context.ts index 71c221a6078c..def6cade593c 100644 --- a/packages/next/server/web/sandbox/context.ts +++ b/packages/next/server/web/sandbox/context.ts @@ -266,7 +266,9 @@ function buildEnvironmentVariablesFrom( keys: string[] ): Record { const pairs = keys.map((key) => [key, process.env[key]]) - return Object.fromEntries(pairs) + const env = Object.fromEntries(pairs) + env.__NEXT_RUNTIME = 'edge' + return env } async function loadWasm( diff --git a/packages/next/shared/lib/isomorphic/path.ts b/packages/next/shared/lib/isomorphic/path.ts index b074412ddefb..1d8d09d43652 100644 --- a/packages/next/shared/lib/isomorphic/path.ts +++ b/packages/next/shared/lib/isomorphic/path.ts @@ -1,5 +1,6 @@ -const path = process.browser - ? require('next/dist/compiled/path-browserify') - : require('path') +const path = + process.env.__NEXT_RUNTIME === 'edge' + ? require('next/dist/compiled/path-browserify') + : require('path') export default path diff --git a/test/integration/react-streaming-and-server-components/app/pages/runtime.js b/test/integration/react-streaming-and-server-components/app/pages/runtime.js index 05a3bd70a5af..a951c4bdaeca 100644 --- a/test/integration/react-streaming-and-server-components/app/pages/runtime.js +++ b/test/integration/react-streaming-and-server-components/app/pages/runtime.js @@ -1,5 +1,5 @@ export default function () { - return process.version + return process.env.__NEXT_RUNTIME === 'nodejs' ? `Runtime: Node.js ${process.version}` : 'Runtime: Edge/Browser' } From 9247d8d8a8d0fbb08978977f400b9cb0298ce484 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Fri, 22 Apr 2022 11:36:08 +0200 Subject: [PATCH 2/7] fix test --- .../index.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/production/middleware-environment-variables-in-node-server-reflect-the-usage-inference/index.test.ts b/test/production/middleware-environment-variables-in-node-server-reflect-the-usage-inference/index.test.ts index f18fc371cf08..62cae006868d 100644 --- a/test/production/middleware-environment-variables-in-node-server-reflect-the-usage-inference/index.test.ts +++ b/test/production/middleware-environment-variables-in-node-server-reflect-the-usage-inference/index.test.ts @@ -44,6 +44,7 @@ describe('middleware environment variables in node server reflect the usage infe rest: { CAN_BE_INFERRED: 'can-be-inferred', X_CUSTOM_HEADER: 'x-custom-header', + __NEXT_RUNTIME: 'edge', }, }) }) From 3700e50a311970f79323b1c2efc05fabfd181836 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Fri, 22 Apr 2022 13:03:34 +0200 Subject: [PATCH 3/7] fix test --- test/integration/middleware/core/test/index.test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/integration/middleware/core/test/index.test.js b/test/integration/middleware/core/test/index.test.js index c224307ef734..ff5c12afac4a 100644 --- a/test/integration/middleware/core/test/index.test.js +++ b/test/integration/middleware/core/test/index.test.js @@ -130,6 +130,7 @@ describe('Middleware base tests', () => { process: { env: { MIDDLEWARE_TEST: 'asdf', + __NEXT_RUNTIME: 'edge', }, nextTick: 'function', }, From a55d0430b11d84d2a1813a0f14af28120dce04cb Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Fri, 22 Apr 2022 13:44:17 +0200 Subject: [PATCH 4/7] remove browser env --- packages/next/build/webpack-config.ts | 8 +++++--- test/integration/middleware/core/test/index.test.js | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index 248cbe85dd3d..472c46a6c711 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -1326,9 +1326,11 @@ export default async function getBaseWebpackConfig( ), 'process.env.__NEXT_CROSS_ORIGIN': JSON.stringify(crossOrigin), 'process.browser': JSON.stringify(!isServer), - 'process.env.__NEXT_RUNTIME': JSON.stringify( - !isServer ? 'browser' : isEdgeRuntime ? 'edge' : 'nodejs' - ), + ...(isServer && { + 'process.env.__NEXT_RUNTIME': JSON.stringify( + isEdgeRuntime ? 'edge' : 'nodejs' + ), + }), 'process.env.__NEXT_TEST_MODE': JSON.stringify( process.env.__NEXT_TEST_MODE ), diff --git a/test/integration/middleware/core/test/index.test.js b/test/integration/middleware/core/test/index.test.js index ff5c12afac4a..393b25d36697 100644 --- a/test/integration/middleware/core/test/index.test.js +++ b/test/integration/middleware/core/test/index.test.js @@ -119,6 +119,7 @@ describe('Middleware base tests', () => { context.app = await launchApp(context.appDir, context.appPort, { env: { MIDDLEWARE_TEST: 'asdf', + __NEXT_RUNTIME: 'edge', }, }) }) From ac56d4b40db3b6e5f8fc984afa7c7d9dda62e531 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Tue, 26 Apr 2022 15:47:29 +0200 Subject: [PATCH 5/7] rm underscore prefix --- packages/next/bin/next.ts | 2 +- packages/next/build/webpack-config.ts | 2 +- packages/next/lib/chalk.ts | 2 +- packages/next/pages/_document.tsx | 2 +- packages/next/server/base-server.ts | 6 +++--- packages/next/server/render.tsx | 21 +++++++++---------- packages/next/server/web/sandbox/context.ts | 2 +- packages/next/shared/lib/isomorphic/path.ts | 2 +- .../middleware/core/test/index.test.js | 4 ++-- .../app/pages/runtime.js | 2 +- .../index.test.ts | 2 +- 11 files changed, 23 insertions(+), 24 deletions(-) diff --git a/packages/next/bin/next.ts b/packages/next/bin/next.ts index 2eafc3ac2db2..d6442c51b732 100755 --- a/packages/next/bin/next.ts +++ b/packages/next/bin/next.ts @@ -104,7 +104,7 @@ if (process.env.NODE_ENV) { } ;(process.env as any).NODE_ENV = process.env.NODE_ENV || defaultEnv -;(process.env as any).__NEXT_RUNTIME = 'nodejs' +;(process.env as any).NEXT_RUNTIME = 'nodejs' // x-ref: https://github.com/vercel/next.js/pull/34688#issuecomment-1047994505 if (process.versions.pnp === '3') { diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index f0837233f308..31bd353a4870 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -1375,7 +1375,7 @@ export default async function getBaseWebpackConfig( 'process.env.__NEXT_CROSS_ORIGIN': JSON.stringify(crossOrigin), 'process.browser': JSON.stringify(!isServer), ...(isServer && { - 'process.env.__NEXT_RUNTIME': JSON.stringify( + 'process.env.NEXT_RUNTIME': JSON.stringify( isEdgeRuntime ? 'edge' : 'nodejs' ), }), diff --git a/packages/next/lib/chalk.ts b/packages/next/lib/chalk.ts index e6b4b89e2731..8e40472953f8 100644 --- a/packages/next/lib/chalk.ts +++ b/packages/next/lib/chalk.ts @@ -1,6 +1,6 @@ let chalk: typeof import('next/dist/compiled/chalk') -if (process.env.__NEXT_RUNTIME === 'edge') { +if (process.env.NEXT_RUNTIME === 'edge') { chalk = require('./web/chalk').default } else { chalk = require('next/dist/compiled/chalk') diff --git a/packages/next/pages/_document.tsx b/packages/next/pages/_document.tsx index d308cf6710a8..4d0c3ec539fe 100644 --- a/packages/next/pages/_document.tsx +++ b/packages/next/pages/_document.tsx @@ -80,7 +80,7 @@ function getPreNextWorkerScripts(context: HtmlProps, props: OriginProps) { const { assetPrefix, scriptLoader, crossOrigin, nextScriptWorkers } = context // disable `nextScriptWorkers` in edge runtime - if (!nextScriptWorkers || process.env.__NEXT_RUNTIME === 'edge') return null + if (!nextScriptWorkers || process.env.NEXT_RUNTIME === 'edge') return null try { let { diff --git a/packages/next/server/base-server.ts b/packages/next/server/base-server.ts index fe08fc96cb63..3bde9a187d47 100644 --- a/packages/next/server/base-server.ts +++ b/packages/next/server/base-server.ts @@ -1155,7 +1155,7 @@ export default abstract class Server { (isServerComponent && !hasServerProps && !hasGetInitialProps && - process.env.__NEXT_RUNTIME !== 'edge') + process.env.NEXT_RUNTIME !== 'edge') // Toggle whether or not this is a Data request const isDataReq = @@ -1240,7 +1240,7 @@ export default abstract class Server { if (hasServerProps || isSSG) { // For the edge runtime, we don't support preview mode in SSG. - if (process.env.__NEXT_RUNTIME !== 'edge') { + if (process.env.NEXT_RUNTIME !== 'edge') { const { tryGetPreviewData } = require('./api-utils/node') as typeof import('./api-utils/node') previewData = tryGetPreviewData(req, res, this.renderOpts.previewProps) @@ -1759,7 +1759,7 @@ export default abstract class Server { if (!isWrappedError) { if ( - (this.minimalMode && process.env.__NEXT_RUNTIME !== 'edge') || + (this.minimalMode && process.env.NEXT_RUNTIME !== 'edge') || this.renderOpts.dev ) { if (isError(err)) err.page = page diff --git a/packages/next/server/render.tsx b/packages/next/server/render.tsx index 127a8c21e5c8..9d9b053562ae 100644 --- a/packages/next/server/render.tsx +++ b/packages/next/server/render.tsx @@ -89,7 +89,7 @@ let postProcess: typeof import('../shared/lib/post-process').default const DOCTYPE = '' -if (process.env.__NEXT_RUNTIME !== 'edge') { +if (process.env.NEXT_RUNTIME !== 'edge') { require('./node-polyfill-web-streams') optimizeAmp = require('./optimize-amp').default getFontDefinitionFromManifest = @@ -518,7 +518,7 @@ export async function renderToHTML( Uint8Array, Uint8Array > | null = - isServerComponent && process.env.__NEXT_RUNTIME !== 'edge' + isServerComponent && process.env.NEXT_RUNTIME !== 'edge' ? new TransformStream() : null @@ -705,7 +705,7 @@ export async function renderToHTML( if ( (isSSG || getServerSideProps) && !isFallback && - process.env.__NEXT_RUNTIME !== 'edge' + process.env.NEXT_RUNTIME !== 'edge' ) { // Reads of this are cached on the `req` object, so this should resolve // instantly. There's no need to pass this data down from a previous @@ -781,8 +781,7 @@ export async function renderToHTML( } // Disable AMP under the web environment - const inAmpMode = - process.env.__NEXT_RUNTIME !== 'edge' && isInAmpMode(ampState) + const inAmpMode = process.env.NEXT_RUNTIME !== 'edge' && isInAmpMode(ampState) const reactLoadableModules: string[] = [] @@ -1320,7 +1319,7 @@ export async function renderToHTML( | typeof Document | undefined - if (process.env.__NEXT_RUNTIME === 'edge' && Document.getInitialProps) { + if (process.env.NEXT_RUNTIME === 'edge' && Document.getInitialProps) { // In the Edge runtime, `Document.getInitialProps` isn't supported. // We throw an error here if it's customized. if (!builtinDocument) { @@ -1331,7 +1330,7 @@ export async function renderToHTML( } if ( - (isServerComponent || process.env.__NEXT_RUNTIME === 'edge') && + (isServerComponent || process.env.NEXT_RUNTIME === 'edge') && Document.getInitialProps ) { if (builtinDocument) { @@ -1551,7 +1550,7 @@ export async function renderToHTML( const hasDocumentGetInitialProps = !( isServerComponent || - process.env.__NEXT_RUNTIME === 'edge' || + process.env.NEXT_RUNTIME === 'edge' || !Document.getInitialProps ) @@ -1570,7 +1569,7 @@ export async function renderToHTML( const { docProps } = (documentInitialPropsRes as any) || {} const documentElement = () => { - if (isServerComponent || process.env.__NEXT_RUNTIME === 'edge') { + if (isServerComponent || process.env.NEXT_RUNTIME === 'edge') { return (Document as any)() } @@ -1761,7 +1760,7 @@ export async function renderToHTML( return html } : null, - process.env.__NEXT_RUNTIME !== 'edge' && + process.env.NEXT_RUNTIME !== 'edge' && process.env.__NEXT_OPTIMIZE_FONTS ? async (html: string) => { return await postProcess( @@ -1773,7 +1772,7 @@ export async function renderToHTML( ) } : null, - process.env.__NEXT_RUNTIME !== 'edge' && renderOpts.optimizeCss + process.env.NEXT_RUNTIME !== 'edge' && renderOpts.optimizeCss ? async (html: string) => { // eslint-disable-next-line import/no-extraneous-dependencies const Critters = require('critters') diff --git a/packages/next/server/web/sandbox/context.ts b/packages/next/server/web/sandbox/context.ts index 6008a70f79e8..9e96005bbccb 100644 --- a/packages/next/server/web/sandbox/context.ts +++ b/packages/next/server/web/sandbox/context.ts @@ -266,7 +266,7 @@ function buildEnvironmentVariablesFrom( ): Record { const pairs = keys.map((key) => [key, process.env[key]]) const env = Object.fromEntries(pairs) - env.__NEXT_RUNTIME = 'edge' + env.NEXT_RUNTIME = 'edge' return env } diff --git a/packages/next/shared/lib/isomorphic/path.ts b/packages/next/shared/lib/isomorphic/path.ts index 1d8d09d43652..bf4e2197fd80 100644 --- a/packages/next/shared/lib/isomorphic/path.ts +++ b/packages/next/shared/lib/isomorphic/path.ts @@ -1,5 +1,5 @@ const path = - process.env.__NEXT_RUNTIME === 'edge' + process.env.NEXT_RUNTIME === 'edge' ? require('next/dist/compiled/path-browserify') : require('path') diff --git a/test/integration/middleware/core/test/index.test.js b/test/integration/middleware/core/test/index.test.js index 5f5d8f2e082f..a5e44c99ce90 100644 --- a/test/integration/middleware/core/test/index.test.js +++ b/test/integration/middleware/core/test/index.test.js @@ -119,7 +119,7 @@ describe('Middleware base tests', () => { context.app = await launchApp(context.appDir, context.appPort, { env: { MIDDLEWARE_TEST: 'asdf', - __NEXT_RUNTIME: 'edge', + NEXT_RUNTIME: 'edge', }, }) }) @@ -131,7 +131,7 @@ describe('Middleware base tests', () => { process: { env: { MIDDLEWARE_TEST: 'asdf', - __NEXT_RUNTIME: 'edge', + NEXT_RUNTIME: 'edge', }, // it's poflyfilled since there is the "process" module // as a devDepencies of the next package diff --git a/test/integration/react-streaming-and-server-components/app/pages/runtime.js b/test/integration/react-streaming-and-server-components/app/pages/runtime.js index a951c4bdaeca..4d0cde67a02f 100644 --- a/test/integration/react-streaming-and-server-components/app/pages/runtime.js +++ b/test/integration/react-streaming-and-server-components/app/pages/runtime.js @@ -1,5 +1,5 @@ export default function () { - return process.env.__NEXT_RUNTIME === 'nodejs' + return process.env.NEXT_RUNTIME === 'nodejs' ? `Runtime: Node.js ${process.version}` : 'Runtime: Edge/Browser' } diff --git a/test/production/middleware-environment-variables-in-node-server-reflect-the-usage-inference/index.test.ts b/test/production/middleware-environment-variables-in-node-server-reflect-the-usage-inference/index.test.ts index 62cae006868d..7aa6ddb7577b 100644 --- a/test/production/middleware-environment-variables-in-node-server-reflect-the-usage-inference/index.test.ts +++ b/test/production/middleware-environment-variables-in-node-server-reflect-the-usage-inference/index.test.ts @@ -44,7 +44,7 @@ describe('middleware environment variables in node server reflect the usage infe rest: { CAN_BE_INFERRED: 'can-be-inferred', X_CUSTOM_HEADER: 'x-custom-header', - __NEXT_RUNTIME: 'edge', + NEXT_RUNTIME: 'edge', }, }) }) From c2595b928a22fd6187e56ce7409612359f907da0 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Tue, 26 Apr 2022 16:44:32 +0200 Subject: [PATCH 6/7] error if conflicted --- errors/env-key-not-allowed.md | 4 +-- packages/next/build/webpack-config.ts | 31 +++++++++++++------ .../production-config/next.config.js | 5 +++ .../production-config/test/index.test.js | 10 ++++++ 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/errors/env-key-not-allowed.md b/errors/env-key-not-allowed.md index cb365e1217fd..3af2991856d0 100644 --- a/errors/env-key-not-allowed.md +++ b/errors/env-key-not-allowed.md @@ -2,8 +2,8 @@ #### Why This Error Occurred -Next.js configures internal variables for replacement itself. These start with `__` or `NODE_`, for this reason they are not allowed as values for `env` in `next.config.js` +Next.js configures internal variables for replacement itself. These start with `__` or `NODE_` and conflicted with existing `NEXT_RUNTIME` env variable, for this reason they are not allowed as values for `env` in `next.config.js` #### Possible Ways to Fix It -Rename the specified key so that it does not start with `__` or `NODE_`. +Rename the specified key so that it does not start with `__` or `NODE_`, or pick other another name for `NEXT_RUNTIME`. diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index 31bd353a4870..167c7e43ae69 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -1354,11 +1354,7 @@ export default async function getBaseWebpackConfig( {} ), ...Object.keys(config.env).reduce((acc, key) => { - if (/^(?:NODE_.+)|^(?:__.+)$/i.test(key)) { - throw new Error( - `The key "${key}" under "env" in ${config.configFileName} is not allowed. https://nextjs.org/docs/messages/env-key-not-allowed` - ) - } + errorIfEnvConflicted(config, key, isServer) return { ...acc, @@ -1369,16 +1365,16 @@ export default async function getBaseWebpackConfig( 'process.env.NODE_ENV': JSON.stringify( dev ? 'development' : 'production' ), - 'process.env.__NEXT_NEW_LINK_BEHAVIOR': JSON.stringify( - config.experimental.newNextLinkBehavior - ), - 'process.env.__NEXT_CROSS_ORIGIN': JSON.stringify(crossOrigin), - 'process.browser': JSON.stringify(!isServer), ...(isServer && { 'process.env.NEXT_RUNTIME': JSON.stringify( isEdgeRuntime ? 'edge' : 'nodejs' ), }), + 'process.env.__NEXT_NEW_LINK_BEHAVIOR': JSON.stringify( + config.experimental.newNextLinkBehavior + ), + 'process.env.__NEXT_CROSS_ORIGIN': JSON.stringify(crossOrigin), + 'process.browser': JSON.stringify(!isServer), 'process.env.__NEXT_TEST_MODE': JSON.stringify( process.env.__NEXT_TEST_MODE ), @@ -2187,3 +2183,18 @@ export default async function getBaseWebpackConfig( return webpackConfig } + +function errorIfEnvConflicted( + config: NextConfigComplete, + key: string, + isServer: boolean +) { + const isPrivateKey = /^(?:NODE_.+)|^(?:__.+)$/i.test(key) + const hasNextRuntimeKey = isServer && key === 'NEXT_RUNTIME' + + if (isPrivateKey || hasNextRuntimeKey) { + throw new Error( + `The key "${key}" under "env" in ${config.configFileName} is not allowed. https://nextjs.org/docs/messages/env-key-not-allowed` + ) + } +} diff --git a/test/integration/production-config/next.config.js b/test/integration/production-config/next.config.js index a2120be4a6ee..c72c2361ba07 100644 --- a/test/integration/production-config/next.config.js +++ b/test/integration/production-config/next.config.js @@ -15,6 +15,11 @@ module.exports = { SOME__ENV__VAR: '123', } : {}), + ...(process.env.ENABLE_ENV_NEXT_PRESERVED + ? { + NEXT_RUNTIME: 'nodejs', + } + : {}), }, onDemandEntries: { // Make sure entries are not getting disposed. diff --git a/test/integration/production-config/test/index.test.js b/test/integration/production-config/test/index.test.js index 53e57cb5c749..53696974199f 100644 --- a/test/integration/production-config/test/index.test.js +++ b/test/integration/production-config/test/index.test.js @@ -56,6 +56,16 @@ describe('Production Config Usage', () => { expect(result.stderr).toMatch(/The key "NODE_ENV" under/) }) + it('should fail with NEXT_RUNTIME in env key', async () => { + const result = await runNextCommand(['build', appDir], { + env: { ENABLE_ENV_NEXT_PRESERVED: true }, + stdout: true, + stderr: true, + }) + + expect(result.stderr).toMatch(/The key "NEXT_RUNTIME" under/) + }) + it('should allow __ within env key', async () => { const result = await runNextCommand(['build', appDir], { env: { ENABLE_ENV_WITH_UNDERSCORES: true }, From 6a156ea6f3e20934749ab293878650416d8efcf6 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Tue, 26 Apr 2022 19:01:56 +0200 Subject: [PATCH 7/7] tweak docs and error on all compilers --- errors/env-key-not-allowed.md | 2 +- packages/next/build/webpack-config.ts | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/errors/env-key-not-allowed.md b/errors/env-key-not-allowed.md index 3af2991856d0..ae45e9e0cffa 100644 --- a/errors/env-key-not-allowed.md +++ b/errors/env-key-not-allowed.md @@ -2,7 +2,7 @@ #### Why This Error Occurred -Next.js configures internal variables for replacement itself. These start with `__` or `NODE_` and conflicted with existing `NEXT_RUNTIME` env variable, for this reason they are not allowed as values for `env` in `next.config.js` +Next.js configures internal variables for replacement itself. `NEXT_RUNTIME` along with variables starting with `__` or `NODE_` are currently internal, for this reason they are not allowed as values for `env` in `next.config.js` #### Possible Ways to Fix It diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index 167c7e43ae69..53fd9eebccdb 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -1354,7 +1354,7 @@ export default async function getBaseWebpackConfig( {} ), ...Object.keys(config.env).reduce((acc, key) => { - errorIfEnvConflicted(config, key, isServer) + errorIfEnvConflicted(config, key) return { ...acc, @@ -2184,13 +2184,9 @@ export default async function getBaseWebpackConfig( return webpackConfig } -function errorIfEnvConflicted( - config: NextConfigComplete, - key: string, - isServer: boolean -) { +function errorIfEnvConflicted(config: NextConfigComplete, key: string) { const isPrivateKey = /^(?:NODE_.+)|^(?:__.+)$/i.test(key) - const hasNextRuntimeKey = isServer && key === 'NEXT_RUNTIME' + const hasNextRuntimeKey = key === 'NEXT_RUNTIME' if (isPrivateKey || hasNextRuntimeKey) { throw new Error(