Add nodejs version check (#58958)

There're some reports related to using incorrect Node.js version, sometimes users ended up in weird errors. As pkg manager like pnpm only gives a warning ` WARN  Unsupported engine: wanted: {"node":">=18.17.0"} (current: {"node":"v16.18.0","pnpm":"8.9.0"})` which is not easy to investigate the issue.

We're adding a version check at the beginning of the Next.js process so if Node.js version is mis-match the version specified in package.json, bail with error.

Examples

node 16.x
```
You are using Node.js 16.18.0. Node.js >= v18.17.0 is required.
```

node.18.16
```
You are using Node.js 18.16.1. Node.js >= v18.17.0 is required.
```
This commit is contained in:
Jiachi Liu 2023-11-27 17:53:26 +01:00 committed by GitHub
parent 1c5ff6e735
commit cdf2b79ea9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 30 additions and 12 deletions

View file

@ -3,6 +3,7 @@ performance.mark('next-start')
import '../server/require-hook'
import * as log from '../build/output/log'
import arg from 'next/dist/compiled/arg/index.js'
import semver from 'next/dist/compiled/semver'
import { NON_STANDARD_NODE_ENV } from '../lib/constants'
import { commands } from '../lib/commands'
import { commandArgs } from '../lib/command-args'
@ -115,6 +116,15 @@ async function main() {
}
}
if (
semver.lt(process.versions.node, process.env.__NEXT_REQUIRED_NODE_VERSION!)
) {
console.error(
`You are using Node.js ${process.versions.node}. For Next.js, Node.js version >= v${process.env.__NEXT_REQUIRED_NODE_VERSION} is required.`
)
process.exit(1)
}
await commands[command]()
.then((exec) => exec(validatedArgs))
.then(() => {

View file

@ -32,7 +32,6 @@ import {
import { traverseModules, forEachEntryModule } from '../utils'
import { normalizePathSep } from '../../../shared/lib/page-path/normalize-path-sep'
import { getProxiedPluginState } from '../../build-context'
import semver from 'next/dist/compiled/semver'
import { generateRandomActionKeyRaw } from '../../../server/app-render/action-encryption-utils'
interface Options {
@ -788,17 +787,6 @@ export class FlightClientEntryPlugin {
}) {
const actionsArray = Array.from(actions.entries())
// Node < 18.11 does not have sufficient support for FormData
if (actionsArray.length > 0 && semver.lt(process.version, '18.11.0')) {
compilation.errors.push(
new compilation.compiler.webpack.WebpackError(
'Your version of Node does not support server actions. Please upgrade to Node 18.11 or higher.'
)
)
return Promise.resolve()
}
const actionLoader = `next-flight-action-entry-loader?${stringify({
actions: JSON.stringify(actionsArray),
__client_imported__: fromClient,

View file

@ -190,6 +190,10 @@ function setNextVersion(code) {
/process\.env\.__NEXT_VERSION/g,
`"${require('./package.json').version}"`
)
.replace(
/process\.env\.__NEXT_REQUIRED_NODE_VERSION/g,
`"${require('./package.json').engines.node.replace('>=', '')}"`
)
.replace(
/process\.env\.REQUIRED_APP_REACT_VERSION/,
`"${

View file

@ -1,5 +1,7 @@
/* eslint-env jest */
import { transform } from 'next/dist/build/swc'
import path from 'path'
import fsp from 'fs/promises'
const swc = async (code) => {
let output = await transform(code)
@ -111,4 +113,18 @@ describe('next/swc', () => {
`)
})
})
describe('private env replacement', () => {
it('__NEXT_REQUIRED_NODE_VERSION is replaced', async () => {
const pkgDir = path.dirname(require.resolve('next/package.json'))
const nextEntryContent = await fsp.readFile(
path.join(pkgDir, 'dist/bin/next'),
'utf8'
)
expect(nextEntryContent).not.toContain('__NEXT_REQUIRED_NODE_VERSION')
expect(nextEntryContent).toMatch(
/For Next.js, Node.js version >= v\$\{"\d+\.\d+\.\d*"\}/
)
})
})
})