Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove static analysis of process.env #50260

Merged
merged 2 commits into from
May 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions docs/api-reference/edge-runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
4 changes: 0 additions & 4 deletions docs/basic-features/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
>
Expand Down
1 change: 0 additions & 1 deletion packages/next/src/build/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ export function getModuleBuildInfo(webpackModule: webpack.Module) {
nextEdgeMiddleware?: EdgeMiddlewareMeta
nextEdgeApiFunction?: EdgeMiddlewareMeta
nextEdgeSSR?: EdgeSSRMeta
nextUsedEnvVars?: Set<string>
nextWasmMiddlewareBinding?: AssetBinding
nextAssetMiddlewareBinding?: AssetBinding
usingIndirectEval?: boolean | Set<string>
Expand Down
83 changes: 0 additions & 83 deletions packages/next/src/build/webpack/plugins/middleware-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -55,7 +54,6 @@ interface EntryMetadata {
edgeMiddleware?: EdgeMiddlewareMeta
edgeApiFunction?: EdgeMiddlewareMeta
edgeSSR?: EdgeSSRMeta
env: Set<string>
wasmBindings: Map<string, string>
assetBindings: Map<string, string>
regions?: string[] | string
Expand Down Expand Up @@ -188,7 +186,6 @@ function getCreateAssets(params: {
]

const edgeFunctionDefinition: EdgeFunctionDefinition = {
env: Array.from(metadata.env),
ijjk marked this conversation as resolved.
Show resolved Hide resolved
files: getEntryFiles(entrypoint.getFiles(), metadata, opts),
name: entrypoint.name,
page: page,
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -653,7 +581,6 @@ function getExtractMetadata(params: {
entry.includeDependencies.forEach(addEntriesFromDependency)

const entryMetadata: EntryMetadata = {
env: new Set<string>(),
wasmBindings: new Map(),
assetBindings: new Map(),
}
Expand Down Expand Up @@ -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.
Expand Down
1 change: 0 additions & 1 deletion packages/next/src/server/lib/route-resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: [],
}
Expand Down
4 changes: 0 additions & 4 deletions packages/next/src/server/next-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
15 changes: 5 additions & 10 deletions packages/next/src/server/web/sandbox/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,8 @@ async function loadWasm(
return modules
}

function buildEnvironmentVariablesFrom(
keys: string[]
): Record<string, string | undefined> {
const pairs = keys.map((key) => [key, process.env[key]])
function buildEnvironmentVariablesFrom(): Record<string, string | undefined> {
const pairs = Object.keys(process.env).map((key) => [key, process.env[key]])
const env = Object.fromEntries(pairs)
env.NEXT_RUNTIME = 'edge'
return env
Expand All @@ -108,10 +106,8 @@ Learn more: https://nextjs.org/docs/api-reference/edge-runtime`)
throw error
}

function createProcessPolyfill(options: Pick<ModuleContextOptions, 'env'>) {
const env = buildEnvironmentVariablesFrom(options.env)

const processPolyfill = { env }
function createProcessPolyfill() {
const processPolyfill = { env: buildEnvironmentVariablesFrom() }
const overridenValue: Record<string, any> = {}
for (const key of Object.keys(process)) {
if (key === 'env') continue
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -416,7 +412,6 @@ interface ModuleContextOptions {
moduleName: string
onWarning: (warn: Error) => void
useCache: boolean
env: string[]
distDir: string
edgeFunctionEntry: Pick<EdgeFunctionDefinition, 'assets' | 'wasm'>
}
Expand Down
3 changes: 0 additions & 3 deletions packages/next/src/server/web/sandbox/sandbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ const FORBIDDEN_HEADERS = [

type RunnerFn = (params: {
name: string
env: string[]
onWarning?: (warn: Error) => void
paths: string[]
request: NodejsRequestData
Expand Down Expand Up @@ -49,7 +48,6 @@ export const getRuntimeContext = async (params: {
name: string
onWarning?: any
useCache: boolean
env: string[]
edgeFunctionEntry: any
distDir: string
paths: string[]
Expand All @@ -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,
})
Expand Down
16 changes: 0 additions & 16 deletions test/e2e/middleware-general/app/middleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,22 +116,6 @@ export async function middleware(request) {
}

if (url.pathname === '/global') {
// The next line is required to allow to find the env variable
// eslint-disable-next-line no-unused-expressions
process.env.MIDDLEWARE_TEST

// The next line is required to allow to find the env variable
// eslint-disable-next-line no-unused-expressions
const { ANOTHER_MIDDLEWARE_TEST } = process.env
if (!ANOTHER_MIDDLEWARE_TEST) {
console.log('missing ANOTHER_MIDDLEWARE_TEST')
}

const { STRING_ENV_VAR: stringEnvVar } = process['env']
if (!stringEnvVar) {
console.log('missing STRING_ENV_VAR')
}

return serializeData(JSON.stringify({ process: { env: process.env } }))
}

Expand Down
7 changes: 1 addition & 6 deletions test/e2e/middleware-general/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,6 @@ describe('Middleware Runtime', () => {
)
expect(manifest.middleware).toEqual({
'/': {
env: expect.arrayContaining([
'MIDDLEWARE_TEST',
'ANOTHER_MIDDLEWARE_TEST',
'STRING_ENV_VAR',
]),
files: expect.arrayContaining([
'server/edge-runtime-webpack.js',
'server/middleware.js',
Expand Down Expand Up @@ -481,7 +476,7 @@ describe('Middleware Runtime', () => {
})
}

it('should contain process polyfill', async () => {
it('allows to access env variables', async () => {
const res = await fetchViaHTTP(next.url, `/global`)
const json = readMiddlewareJSON(res)

Expand Down
1 change: 0 additions & 1 deletion test/e2e/middleware-trailing-slash/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ describe('Middleware Runtime trailing slash', () => {
'/': {
files: ['server/edge-runtime-webpack.js', 'server/middleware.js'],
name: 'middleware',
env: expect.arrayContaining([]),
page: '/',
matchers: [{ regexp: '^/.*$', originalSource: '/:path*' }],
wasm: [],
Expand Down
4 changes: 0 additions & 4 deletions test/e2e/switchable-runtime/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ describe('Switchable runtime', () => {
expect(manifest).toMatchObject({
functions: {
'/api/hello': {
env: expect.arrayContaining([]),
files: [
'server/edge-runtime-webpack.js',
'server/pages/api/hello.js',
Expand All @@ -200,7 +199,6 @@ describe('Switchable runtime', () => {
wasm: [],
},
'/api/edge': {
env: expect.arrayContaining([]),
files: [
'server/edge-runtime-webpack.js',
'server/pages/api/edge.js',
Expand Down Expand Up @@ -623,7 +621,6 @@ describe('Switchable runtime', () => {
expect(manifest).toMatchObject({
functions: {
'/api/hello': {
env: expect.arrayContaining([]),
files: [
'server/edge-runtime-webpack.js',
'server/pages/api/hello.js',
Expand All @@ -636,7 +633,6 @@ describe('Switchable runtime', () => {
wasm: [],
},
'/api/edge': {
env: expect.arrayContaining([]),
files: [
'server/edge-runtime-webpack.js',
'server/pages/api/edge.js',
Expand Down
Loading