From 68af131dd23ecad4ee0f3bbb6d243a72982290f4 Mon Sep 17 00:00:00 2001 From: Javi Velasco Date: Wed, 24 May 2023 10:48:22 +0200 Subject: [PATCH] Remove static analysis of `process.env` --- docs/api-reference/edge-runtime.md | 9 -- docs/basic-features/environment-variables.md | 4 - packages/next/src/build/utils.ts | 1 - .../webpack/loaders/get-module-build-info.ts | 1 - .../webpack/plugins/middleware-plugin.ts | 83 ------------------- .../next/src/server/lib/route-resolver.ts | 1 - packages/next/src/server/next-server.ts | 4 - .../next/src/server/web/sandbox/context.ts | 15 ++-- .../next/src/server/web/sandbox/sandbox.ts | 3 - 9 files changed, 5 insertions(+), 116 deletions(-) diff --git a/docs/api-reference/edge-runtime.md b/docs/api-reference/edge-runtime.md index ee584860807659..a7d712689766a8 100644 --- a/docs/api-reference/edge-runtime.md +++ b/docs/api-reference/edge-runtime.md @@ -130,15 +130,6 @@ The Edge Runtime supports the following web standard APIs: You can use `process.env` to access [Environment Variables](/docs/basic-features/environment-variables.md) for both `next dev` and `next build`. -Running `console.log` on `process.env` **will not** show all your Environment Variables. You have to access the variables directly as shown below: - -```javascript -console.log(process.env) -// { NEXT_RUNTIME: 'edge' } -console.log(process.env.TEST_VARIABLE) -// value -``` - ## Compatible Node.js Modules The following modules can be imported with and without the `node:` prefix when using the `import` statement: diff --git a/docs/basic-features/environment-variables.md b/docs/basic-features/environment-variables.md index a2ed7a0f0b345f..acf28266607a6f 100644 --- a/docs/basic-features/environment-variables.md +++ b/docs/basic-features/environment-variables.md @@ -44,10 +44,6 @@ export async function getStaticProps() { } ``` -> **Note**: In order to keep server-only secrets safe, environment variables are evaluated at build time, so only environment variables _actually_ used will be included. This means that `process.env` is not a standard JavaScript object, so you’re not able to -> use [object destructuring](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment). -> Environment variables must be referenced as e.g. `process.env.PUBLISHABLE_KEY`, _not_ `const { PUBLISHABLE_KEY } = process.env`. - > **Note**: Next.js will automatically expand variables (`$VAR`) inside of your `.env*` files. > This allows you to reference other secrets, like so: > diff --git a/packages/next/src/build/utils.ts b/packages/next/src/build/utils.ts index 11cb72b26b166e..07b3f0f4915c64 100644 --- a/packages/next/src/build/utils.ts +++ b/packages/next/src/build/utils.ts @@ -1389,7 +1389,6 @@ export async function isPageStatic({ if (pathIsEdgeRuntime) { const runtime = await getRuntimeContext({ paths: edgeInfo.files.map((file: string) => path.join(distDir, file)), - env: edgeInfo.env, edgeFunctionEntry: { ...edgeInfo, wasm: (edgeInfo.wasm ?? []).map((binding: AssetBinding) => ({ diff --git a/packages/next/src/build/webpack/loaders/get-module-build-info.ts b/packages/next/src/build/webpack/loaders/get-module-build-info.ts index 1527bc8f1f9dc5..c99994d29409fc 100644 --- a/packages/next/src/build/webpack/loaders/get-module-build-info.ts +++ b/packages/next/src/build/webpack/loaders/get-module-build-info.ts @@ -33,7 +33,6 @@ export function getModuleBuildInfo(webpackModule: webpack.Module) { nextEdgeMiddleware?: EdgeMiddlewareMeta nextEdgeApiFunction?: EdgeMiddlewareMeta nextEdgeSSR?: EdgeSSRMeta - nextUsedEnvVars?: Set nextWasmMiddlewareBinding?: AssetBinding nextAssetMiddlewareBinding?: AssetBinding usingIndirectEval?: boolean | Set diff --git a/packages/next/src/build/webpack/plugins/middleware-plugin.ts b/packages/next/src/build/webpack/plugins/middleware-plugin.ts index 66803d1245e5b8..a06c388fe40af8 100644 --- a/packages/next/src/build/webpack/plugins/middleware-plugin.ts +++ b/packages/next/src/build/webpack/plugins/middleware-plugin.ts @@ -34,7 +34,6 @@ import { INSTRUMENTATION_HOOK_FILENAME } from '../../../lib/constants' import { NextBuildContext } from '../../build-context' export interface EdgeFunctionDefinition { - env: string[] files: string[] name: string page: string @@ -55,7 +54,6 @@ interface EntryMetadata { edgeMiddleware?: EdgeMiddlewareMeta edgeApiFunction?: EdgeMiddlewareMeta edgeSSR?: EdgeSSRMeta - env: Set wasmBindings: Map assetBindings: Map regions?: string[] | string @@ -188,7 +186,6 @@ function getCreateAssets(params: { ] const edgeFunctionDefinition: EdgeFunctionDefinition = { - env: Array.from(metadata.env), files: getEntryFiles(entrypoint.getFiles(), metadata, opts), name: entrypoint.name, page: page, @@ -248,17 +245,6 @@ function isInMiddlewareLayer(parser: webpack.javascript.JavascriptParser) { return parser.state.module?.layer === 'middleware' } -function isProcessEnvMemberExpression(memberExpression: any): boolean { - return ( - memberExpression.object?.type === 'Identifier' && - memberExpression.object.name === 'process' && - ((memberExpression.property?.type === 'Literal' && - memberExpression.property.value === 'env') || - (memberExpression.property?.type === 'Identifier' && - memberExpression.property.name === 'env')) - ) -} - function isNodeJsModule(moduleName: string) { return require('module').builtinModules.includes(moduleName) } @@ -461,32 +447,6 @@ function getCodeAnalyzer(params: { } } - /** - * Declares an environment variable that is being used in this module - * through this static analysis. - */ - const addUsedEnvVar = (envVarName: string) => { - const buildInfo = getModuleBuildInfo(parser.state.module) - if (buildInfo.nextUsedEnvVars === undefined) { - buildInfo.nextUsedEnvVars = new Set() - } - - buildInfo.nextUsedEnvVars.add(envVarName) - } - - /** - * A handler for calls to `process.env` where we identify the name of the - * ENV variable being assigned and store it in the module info. - */ - const handleCallMemberChain = (_: unknown, members: string[]) => { - if (members.length >= 2 && members[0] === 'env') { - addUsedEnvVar(members[1]) - if (!isInMiddlewareLayer(parser)) { - return true - } - } - } - /** * Handler to store original source location of static and dynamic imports into module's buildInfo. */ @@ -541,41 +501,9 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`, .tap(NAME, handleWrapWasmInstantiateExpression) } - hooks.callMemberChain.for('process').tap(NAME, handleCallMemberChain) - hooks.expressionMemberChain.for('process').tap(NAME, handleCallMemberChain) hooks.importCall.tap(NAME, handleImport) hooks.import.tap(NAME, handleImport) - /** - * Support static analyzing environment variables through - * destructuring `process.env` or `process["env"]`: - * - * const { MY_ENV, "MY-ENV": myEnv } = process.env - * ^^^^^^ ^^^^^^ - */ - hooks.declarator.tap(NAME, (declarator) => { - if ( - declarator.init?.type === 'MemberExpression' && - isProcessEnvMemberExpression(declarator.init) && - declarator.id?.type === 'ObjectPattern' - ) { - for (const property of declarator.id.properties) { - if (property.type === 'RestElement') continue - if ( - property.key.type === 'Literal' && - typeof property.key.value === 'string' - ) { - addUsedEnvVar(property.key.value) - } else if (property.key.type === 'Identifier') { - addUsedEnvVar(property.key.name) - } - } - - if (!isInMiddlewareLayer(parser)) { - return true - } - } - }) if (!dev) { // do not issue compilation warning on dev: invoking code will provide details registerUnsupportedApiHooks(parser, compilation) @@ -653,7 +581,6 @@ function getExtractMetadata(params: { entry.includeDependencies.forEach(addEntriesFromDependency) const entryMetadata: EntryMetadata = { - env: new Set(), wasmBindings: new Map(), assetBindings: new Map(), } @@ -760,16 +687,6 @@ function getExtractMetadata(params: { entryMetadata.edgeApiFunction = buildInfo.nextEdgeApiFunction } - /** - * If there are env vars found in the module, append them to the set - * of env vars for the entry. - */ - if (buildInfo?.nextUsedEnvVars !== undefined) { - for (const envName of buildInfo.nextUsedEnvVars) { - entryMetadata.env.add(envName) - } - } - /** * If the module is a WASM module we read the binding information and * append it to the entry wasm bindings. diff --git a/packages/next/src/server/lib/route-resolver.ts b/packages/next/src/server/lib/route-resolver.ts index 2c75ca175789c9..e83aeac49728c3 100644 --- a/packages/next/src/server/lib/route-resolver.ts +++ b/packages/next/src/server/lib/route-resolver.ts @@ -165,7 +165,6 @@ export async function makeResolver( return { name: 'middleware', paths: middleware.files.map((file) => join(process.cwd(), file)), - env: Object.keys(process.env), wasm: [], assets: [], } diff --git a/packages/next/src/server/next-server.ts b/packages/next/src/server/next-server.ts index 3e5658d89cc585..364c5f4118771d 100644 --- a/packages/next/src/server/next-server.ts +++ b/packages/next/src/server/next-server.ts @@ -2183,7 +2183,6 @@ export default class NextNodeServer extends BaseServer { }): { name: string paths: string[] - env: string[] wasm: { filePath: string; name: string }[] assets: { filePath: string; name: string }[] } | null { @@ -2214,7 +2213,6 @@ export default class NextNodeServer extends BaseServer { return { name: pageInfo.name, paths: pageInfo.files.map((file) => join(this.distDir, file)), - env: pageInfo.env ?? [], wasm: (pageInfo.wasm ?? []).map((binding) => ({ ...binding, filePath: join(this.distDir, binding.filePath), @@ -2322,7 +2320,6 @@ export default class NextNodeServer extends BaseServer { distDir: this.distDir, name: middlewareInfo.name, paths: middlewareInfo.paths, - env: middlewareInfo.env, edgeFunctionEntry: middlewareInfo, request: { headers: params.request.headers, @@ -2825,7 +2822,6 @@ export default class NextNodeServer extends BaseServer { distDir: this.distDir, name: edgeInfo.name, paths: edgeInfo.paths, - env: edgeInfo.env, edgeFunctionEntry: edgeInfo, request: { headers: params.req.headers, diff --git a/packages/next/src/server/web/sandbox/context.ts b/packages/next/src/server/web/sandbox/context.ts index 96d788a31e0a5e..bcb5dba9d9fc4d 100644 --- a/packages/next/src/server/web/sandbox/context.ts +++ b/packages/next/src/server/web/sandbox/context.ts @@ -91,10 +91,8 @@ async function loadWasm( return modules } -function buildEnvironmentVariablesFrom( - keys: string[] -): Record { - const pairs = keys.map((key) => [key, process.env[key]]) +function buildEnvironmentVariablesFrom(): Record { + const pairs = Object.keys(process.env).map((key) => [key, process.env[key]]) const env = Object.fromEntries(pairs) env.NEXT_RUNTIME = 'edge' return env @@ -108,10 +106,8 @@ Learn more: https://nextjs.org/docs/api-reference/edge-runtime`) throw error } -function createProcessPolyfill(options: Pick) { - const env = buildEnvironmentVariablesFrom(options.env) - - const processPolyfill = { env } +function createProcessPolyfill() { + const processPolyfill = { env: buildEnvironmentVariablesFrom() } const overridenValue: Record = {} for (const key of Object.keys(process)) { if (key === 'env') continue @@ -236,7 +232,7 @@ async function createModuleContext(options: ModuleContextOptions) { : undefined, extend: (context) => { context.WebSocket = require('next/dist/compiled/ws').WebSocket - context.process = createProcessPolyfill(options) + context.process = createProcessPolyfill() Object.defineProperty(context, 'require', { enumerable: false, @@ -416,7 +412,6 @@ interface ModuleContextOptions { moduleName: string onWarning: (warn: Error) => void useCache: boolean - env: string[] distDir: string edgeFunctionEntry: Pick } diff --git a/packages/next/src/server/web/sandbox/sandbox.ts b/packages/next/src/server/web/sandbox/sandbox.ts index 2398275b05802e..c88d2cb063e8c5 100644 --- a/packages/next/src/server/web/sandbox/sandbox.ts +++ b/packages/next/src/server/web/sandbox/sandbox.ts @@ -15,7 +15,6 @@ const FORBIDDEN_HEADERS = [ type RunnerFn = (params: { name: string - env: string[] onWarning?: (warn: Error) => void paths: string[] request: NodejsRequestData @@ -49,7 +48,6 @@ export const getRuntimeContext = async (params: { name: string onWarning?: any useCache: boolean - env: string[] edgeFunctionEntry: any distDir: string paths: string[] @@ -59,7 +57,6 @@ export const getRuntimeContext = async (params: { moduleName: params.name, onWarning: params.onWarning ?? (() => {}), useCache: params.useCache !== false, - env: params.env, edgeFunctionEntry: params.edgeFunctionEntry, distDir: params.distDir, })