I have a Node.js project that requires Node version 12 or higher. Is there a way to specify this in the packages.json
file, so that the installer will automatically check and inform the users if they need to upgrade?
yarn
version 2+, you will need to install the yarn engines plugin found here: github.com/devoto13/yarn-plugin-engines
You can set the engines
field in your package.json
and set requirements for either node
or npm
versions or both:
"engines" : {
"npm" : ">=7.0.0",
"node" : ">=16.0.0"
}
To enforce this via npm you need to create an .npmrc
file (and commit it to the repository) and set the engines-strict
option to true
, which will cause npm commands such as npm install
to fail if the required engine versions to not match:
# .npmrc
engine-strict=true
Without that file, every developer will need to run npm config set engine-strict true
in their local workspace to switch on this option.
Original Answer
As you're saying your code definitely won't work with any lower versions, you probably want the "engineStrict" flag too:
{ "engineStrict" : true }
Documentation for the package.json file can be found on the npmjs site
Update
engineStrict
is now deprecated, so this will only give a warning. It's now down to the user to run npm config set engine-strict true
if they want this.
Update 2
As ben pointed out below, creating a .npmrc
file at the root of your project (the same level as your package.json file) with the text engine-strict=true
will force an error during installation if the Node version is not compatible.
Add the following to package.json
:
"engines": {
"npm": ">=6.0.0",
"node": ">=10.0.0"
},
Add the following to .npmrc
(same directory as package.json
):
engine-strict=true
npm install
; works with yarn
as well
package.json
with an "engines" section similar to the above (11.13.0
and 6.7.0
), and a .npmrc
with nothing but content specified above. I had nvm switch me to an older node version, then ran npm install
, but it just installs the dependencies and doesn't even mention the engine version mismatch.
engine-strict=true
to your .npmrc file only enforces you to use the right engine when you install packages. It does not enforce anything for your end user. If you want your users to use the engines listed under the "engines: {}"
property in your package.json when they install it, you should tell them to add engine-strict=true
to their .npmrc file.
package.json
the script "preinstall": "echo 'engine-strict=true' >> .npmrc"
engine-strict
usage in .npmrc
is currently not supported by direnv's .envrc
github.com/direnv/direnv/wiki/Node (Found '.nvmrc' with version engine-strict=true
N/A: version "engine-strict=true -> N/A" is not yet installed.
Just like said Ibam, engineStrict
is now deprecated. But I've found this solution:
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"
}
}
Find out more here: https://medium.com/@adambisek/how-to-check-minimum-required-node-js-version-4a78a8855a0f#.3oslqmig4
.nvmrc
And one more thing. A dotfile '.nvmrc' can be used for requiring specific node version - https://github.com/creationix/nvm#nvmrc
But, it is only respected by npm scripts (and yarn scripts).
.nvmrc
If you are using NVM like this, which you likely should, then you can indicate the nodejs version required for given project in a git-tracked .nvmrc
file:
node --version > .nvmrc
or:
echo v10.15.1 > .nvmrc
This does not take effect automatically on cd
, which is sane: the user must then do a:
nvm use
and now that version of node will be used for the current shell.
You can list the versions of node that you have with:
nvm list
.nvmrc
is documented at: https://github.com/creationix/nvm/tree/02997b0753f66c9790c6016ed022ed2072c22603#nvmrc
How to automatically select that node version on cd
was asked at: Automatically switch to correct version of Node based on project
Tested with NVM 0.33.11.
.nvmrc
vs package.json engines
What you might want to do is:
use engines in package.json to give a "no known incompatibilities range"
give the .nvmrc to set a "tested with"
much like package.json vs package-lock.json.
Heroku does respect package.json engines:
Worth mentioning, as documented here, Heroku does play it nice and obey the engines:
entry e.g.:
"engines": {
"node": "14.17.0",
"npm": "6.14.13"
},
So you should Always, Always set that to what you are using locally.
This had been previously mentioned on this self deleted answer to this thread.
nvm use
doesn't pick up .nvmrc for nvm version 1.1.7
There's another, simpler way to do this:
npm install Node@8 (saves Node 8 as dependency in package.json) Your app will run using Node 8 for anyone - even Yarn users!
This works because node
is just a package that ships node as its package binary. It just includes as node_module/.bin which means it only makes node available to package scripts. Not main shell.
See discussion on Twitter here: https://twitter.com/housecor/status/962347301456015360
./node node-sass
rather than just node-sass
. Not sure if same for all .bin files.
Here's my complete ready-to-use script, based on Adam's answer.
check-version.js
:
/* 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);
It should be placed in the root project directory.
It checks node and/or npm version, as specified in package.json
(engines
entry), eg
"engines": {
"node": ">=16.0.0 <17.0.0",
"npm": ">=8.0.0 <9.0.0"
},
You can invoke it manually as
node check-version.js [verbose]
or include it as script inside package json
, either as standalone script or as a prerequisite for other scripts, eg
"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"
},
A Mocha test case example:
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);
});});
Success story sharing
engineStrict
has been deprecated for several months, producing warnings when it was used. Starting with npm@3, the value of the field is ignored, and engine violations will only produce warnings. If you, as a user, want strict engines field enforcement, just run npm config set engine-strict true"cd .. && npm i <folder-name>
in order to check for the project itself. However, this will trigger a whole build in it self.engine-strict=true
to your .npmrc now has the same effect