如何在 package.json 中指定所需的 Node.js 版本?

How can I specify the required Node.js version in package.json?

我有一个 Node.js 项目需要 Node 版本 12 或更高版本。有没有办法在packages.json文件中指定这个,这样安装程序会自动检查并通知用户是否需要升级?

您可以在 package.json 中设置 engines 字段并为 nodenpm 版本或两者设置要求:

  "engines" : { 
    "npm" : ">=7.0.0",
    "node" : ">=16.0.0"
  }

要通过 npm 执行此操作,您需要创建一个 .npmrc 文件(并将其提交到存储库)并将 engines-strict 选项设置为 true,这将导致 npm 命令例如 npm install 如果所需的引擎版本不匹配则失败:

# .npmrc
engine-strict=true

如果没有该文件,每个开发人员都需要 运行 npm config set engine-strict true 在他们的本地工作区中打开此选项。

原答案

正如您所说的,您的代码肯定不适用于任何较低版本,您可能也需要“engineStrict”标志:

{ "engineStrict" : true }

可以找到 package.json 文件的文档 on the npmjs site

更新

engineStrict 现已弃用,因此只会给出警告。现在取决于用户是否需要 运行 npm config set engine-strict true

更新 2

正如 ben 在下面指出的那样,在项目的根目录(与 package.json 文件相同的级别)创建文本 engine-strict=true.npmrc 文件将导致错误安装过程中如果 Node 版本不兼容。

正如 Ibam 所说,engineStrict 现在已弃用。但我找到了这个解决方案:

check-version.js:

import semver from 'semver';
import { engines } from './package';

const version = engines.node;
if (!semver.satisfies(process.version, version)) {
  console.log(`Required node version ${version} not satisfied with current version ${process.version}.`);
  process.exit(1);
}

package.json:

{
  "name": "my package",
  "engines": {
    "node": ">=50.9" // intentionally so big version number
  },
  "scripts": {
    "requirements-check": "babel-node check-version.js",
    "postinstall": "npm run requirements-check"
  }
}

在此处了解更多信息: https://medium.com/@adambisek/how-to-check-minimum-required-node-js-version-4a78a8855a0f#.3oslqmig4

.nvmrc

还有一件事。 点文件“.nvmrc”可用于要求特定节点版本 - https://github.com/creationix/nvm#nvmrc

但是,只有 npm 脚本(和 yarn 脚本)才尊重它。

还有另一种更简单的方法:

  1. npm install Node@8(将节点 8 保存为 package.json 中的依赖项)
  2. 您的应用程序将运行为任何人 - 甚至 Yarn 用户使用 Node 8!

这是可行的,因为 node 只是一个将节点作为其包二进制文件发送的包。它只包含 node_module/.bin,这意味着它只使节点可用于打包脚本。不是主要的 shell.

在此处查看 Twitter 上的讨论:https://twitter.com/housecor/status/962347301456015360

将以下内容添加到 package.json

  "engines": {
    "npm": ">=6.0.0",
    "node": ">=10.0.0"
  },

将以下内容添加到 .npmrc(与 package.json 相同的目录):

engine-strict=true

.nvmrc

如果您是 using NVM like this,您可能应该这样做,那么您可以在 git-tracked .nvmrc 文件中指明给定项目所需的 nodejs 版本:

node --version > .nvmrc

或:

echo v10.15.1 > .nvmrc

这不会在 cd 上自动生效,这是理智的:用户必须执行以下操作:

nvm use

现在该版本的节点将用于当前 shell。

您可以列出您拥有的节点版本:

nvm list

.nvmrc 记录在:https://github.com/creationix/nvm/tree/02997b0753f66c9790c6016ed022ed2072c22603#nvmrc

如何自动 select cd 上的节点版本被问到:Automatically switch to correct version of Node based on project

使用 NVM 0.33.11 测试。

.nvmrc 对比 package.json engines

您可能想要做的是:

  • 使用 给出“未知的不兼容性范围”
  • .nvmrc 设置一个“测试用”

很像 package.json vs package-lock.json.

Heroku 确实尊重 package.json engines:

值得一提的是,作为 documented here,Heroku 确实玩得很好并且遵守 engines: 条目,例如:

  "engines": {
    "node": "14.17.0",
    "npm": "6.14.13"
  },

所以你应该 将其设置为你在本地使用的内容。

之前在此 self deleted answer to this thread 中提到过。

Mocha 测试用例示例:

describe('Check version of node', function () {
    it('Should test version assert', async function () {

            var version = process.version;
            var check = parseFloat(version.substr(1,version.length)) > 12.0;
            console.log("version: "+version);
            console.log("check: " +check);         
            assert.equal(check, true);
    });});

这是我的完整脚本,基于 Adam's answer

它检查节点 and/or npm 版本,如 package.json 中指定(engines 条目),例如

  "engines": {
    "node": ">=16.0.0 <17.0.0",
    "npm": ">=8.0.0 <9.0.0"
  },

您可以手动调用它

node check-version.js [verbose]

或将其作为脚本包含在 package json 中,作为独立脚本或作为其他脚本的先决条件,例如

"scripts" : {
  "start": "node check-version.js && vite",
  "build": "node check-version.js && vite build",
  "lint": "node check-version.js && eslint .",
  "check-version": "node check-version.js verbose"
},

应该放在项目根目录下

/* eslint-disable no-console */
const fs = require('fs');
const semver = require('semver');
const childProcess = require('child_process');

// checks that current node and npm versions satisfies requirements in package.json
// to run manually:   node check-version.js [verbose]

const VERBOSE_FORCED = false;    
const args = process.argv.slice(2);
const VERBOSE = VERBOSE_FORCED || (args.length > 0 && args[0] === 'verbose');

const printErrAndExit = (x) => {
  console.error(x);
  console.error('Aborting');
  process.exit(1);
};

const checkNpmVersion = (npmVersionRequired) => {
  if (!npmVersionRequired) {
    console.log('No required npm version specified');
    return;
  }
  const npmVersion = `${childProcess.execSync('npm -v')}`.trim();
  if (VERBOSE) console.log(`npm required: '${npmVersionRequired}' - current: '${npmVersion}'`);
  if (!semver.satisfies(npmVersion, npmVersionRequired)) {
    printErrAndExit(`Required npm version '${npmVersionRequired}' not satisfied. Current: '${npmVersion}'.`);
  }
};

const checkNodeVersion = (nodeVersionRequired) => {
  if (!nodeVersionRequired) {
    console.log('No required node version specified');
    return;
  }
  const nodeVersion = process.version;
  if (VERBOSE) console.log(`node required: '${nodeVersionRequired}' - current: '${nodeVersion}'`);
  if (!semver.satisfies(nodeVersion, nodeVersionRequired)) {
    printErrAndExit(`Required node version '${nodeVersionRequired}' not satisfied. Current: '${nodeVersion}'.`);
  }
};

const json = JSON.parse(fs.readFileSync('./package.json'));
if (!json.engines) printErrAndExit('no engines entry in package json?');
checkNodeVersion(json.engines.node);
checkNpmVersion(json.engines.npm);