Skip to content

Commit 3af0fe5

Browse files
authored
Add warning for non-standard NODE_ENV value (vercel#12361)
1 parent e70e35a commit 3af0fe5

File tree

7 files changed

+179
-0
lines changed

7 files changed

+179
-0
lines changed

errors/non-standard-node-env.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Non-Standard Node_env
2+
3+
#### Why This Error Occurred
4+
5+
In your environment you set a non-standard value for `NODE_ENV`.
6+
7+
Next.js automatically sets this environment value for you and also forces the correct value during bundling to ensure the bundles are optimized and code can be tree-shaken correctly.
8+
9+
When you set a non-standard environment value like `staging` this causes inconsistent behavior since we override the value to the standard one during bundling e.g. `production` or `development`.
10+
11+
#### Possible Ways to Fix It
12+
13+
Remove any custom `NODE_ENV` environment variables and let Next.js automatically set the correct value for you.
14+
15+
### Useful Links
16+
17+
- [Environment Variables](https://en.wikipedia.org/wiki/Environment_variable)

packages/next/bin/next.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#!/usr/bin/env node
2+
import * as log from '../build/output/log'
23
import arg from 'next/dist/compiled/arg/index.js'
4+
import { NON_STANDARD_NODE_ENV } from '../lib/constants'
35
;['react', 'react-dom'].forEach(dependency => {
46
try {
57
// When 'npm link' is used it checks the clone location. Not the project.
@@ -85,6 +87,13 @@ if (args['--help']) {
8587
}
8688

8789
const defaultEnv = command === 'dev' ? 'development' : 'production'
90+
91+
const standardEnv = ['production', 'development', 'test']
92+
93+
if (process.env.NODE_ENV && !standardEnv.includes(process.env.NODE_ENV)) {
94+
log.warn(NON_STANDARD_NODE_ENV)
95+
}
96+
8897
;(process.env as any).NODE_ENV = process.env.NODE_ENV || defaultEnv
8998

9099
// this needs to come after we set the correct NODE_ENV or

packages/next/lib/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,5 @@ export const UNSTABLE_REVALIDATE_RENAME_ERROR =
4141
'https://nextjs.link/issg'
4242

4343
export const GSSP_COMPONENT_MEMBER_ERROR = `can not be attached to a page's component and must be exported from the page. See more info here: https://err.sh/next.js/gssp-component-member`
44+
45+
export const NON_STANDARD_NODE_ENV = `You are using a non-standard "NODE_ENV" value in your environment. This creates inconsistencies in the project and is strongly advised against. https://err.sh/next.js/non-standard-node-env`

packages/next/server/next.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import Server, { ServerConstructor } from '../next-server/server/next-server'
2+
import { NON_STANDARD_NODE_ENV } from '../lib/constants'
3+
import * as log from '../build/output/log'
24

35
type NextServerConstructor = Omit<ServerConstructor, 'staticMarkup'> & {
46
/**
@@ -9,6 +11,16 @@ type NextServerConstructor = Omit<ServerConstructor, 'staticMarkup'> & {
911

1012
// This file is used for when users run `require('next')`
1113
function createServer(options: NextServerConstructor): Server {
14+
const standardEnv = ['production', 'development', 'test']
15+
16+
if (
17+
!(options as any).isNextDevCommand &&
18+
process.env.NODE_ENV &&
19+
!standardEnv.includes(process.env.NODE_ENV)
20+
) {
21+
log.warn(NON_STANDARD_NODE_ENV)
22+
}
23+
1224
if (options.dev) {
1325
const Server = require('./next-dev-server').default
1426
return new Server(options)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default () => 'hi'
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
const http = require('http')
2+
const next = require('next')
3+
4+
const dev = process.env.NODE_ENV !== 'production'
5+
const dir = __dirname
6+
const port = process.env.PORT || 3000
7+
8+
const app = next({ dev, dir })
9+
const handleNextRequests = app.getRequestHandler()
10+
11+
app.prepare().then(() => {
12+
const server = new http.Server(async (req, res) => {
13+
handleNextRequests(req, res)
14+
})
15+
16+
server.listen(port, err => {
17+
if (err) {
18+
throw err
19+
}
20+
21+
console.log(`> Ready on http://localhost:${port}`)
22+
})
23+
})
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/* eslint-env jest */
2+
/* global jasmine */
3+
import { join } from 'path'
4+
import {
5+
findPort,
6+
launchApp,
7+
killApp,
8+
waitFor,
9+
initNextServerScript,
10+
} from 'next-test-utils'
11+
12+
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 2
13+
14+
const appDir = join(__dirname, '..')
15+
const warningText = `You are using a non-standard "NODE_ENV" value in your environment`
16+
17+
let appPort
18+
let app
19+
20+
const startServer = async (optEnv = {}, opts) => {
21+
const scriptPath = join(appDir, 'server.js')
22+
appPort = appPort = await findPort()
23+
const env = Object.assign({}, process.env, { PORT: `${appPort}` }, optEnv)
24+
25+
return initNextServerScript(
26+
scriptPath,
27+
/ready on/i,
28+
env,
29+
/ReferenceError: options is not defined/,
30+
opts
31+
)
32+
}
33+
34+
describe('Non-Standard NODE_ENV', () => {
35+
it('should not show the warning with no NODE_ENV set', async () => {
36+
let output = ''
37+
38+
app = await launchApp(appDir, await findPort(), {
39+
onStdout(msg) {
40+
output += msg || ''
41+
},
42+
})
43+
await waitFor(2000)
44+
await killApp(app)
45+
expect(output).not.toContain(warningText)
46+
})
47+
48+
it('should not show the warning with NODE_ENV set to valid value', async () => {
49+
let output = ''
50+
51+
app = await launchApp(appDir, await findPort(), {
52+
env: {
53+
NODE_ENV: 'development',
54+
},
55+
onStdout(msg) {
56+
output += msg || ''
57+
},
58+
})
59+
await waitFor(2000)
60+
await killApp(app)
61+
expect(output).not.toContain(warningText)
62+
})
63+
64+
it('should not show the warning with NODE_ENV set to valid value (custom server)', async () => {
65+
let output = ''
66+
67+
app = await startServer(
68+
{
69+
NODE_ENV: 'development',
70+
},
71+
{
72+
onStdout(msg) {
73+
output += msg || ''
74+
},
75+
}
76+
)
77+
await waitFor(2000)
78+
await killApp(app)
79+
expect(output).not.toContain(warningText)
80+
})
81+
82+
it('should show the warning with NODE_ENV set to invalid value', async () => {
83+
let output = ''
84+
85+
app = await launchApp(appDir, await findPort(), {
86+
env: {
87+
NODE_ENV: 'abc',
88+
},
89+
onStdout(msg) {
90+
output += msg || ''
91+
},
92+
})
93+
await waitFor(2000)
94+
await killApp(app)
95+
expect(output).toContain(warningText)
96+
})
97+
98+
it('should show the warning with NODE_ENV set to invalid value (custom server)', async () => {
99+
let output = ''
100+
101+
app = await startServer(
102+
{
103+
NODE_ENV: 'abc',
104+
},
105+
{
106+
onStdout(msg) {
107+
output += msg || ''
108+
},
109+
}
110+
)
111+
await waitFor(2000)
112+
await killApp(app)
113+
expect(output).toContain(warningText)
114+
})
115+
})

0 commit comments

Comments
 (0)