Since the release of Node.js LTS v16 (and npm 8), many team members have encountered various conflicts with the lockfileVersion in their package-lock.json. Here, I will address a few common questions about lockfileVersion and provide assistance in finding the best solution for any issues you may have with your package-lock.json and lockfileVersion.
What is package-lock.json
So, you have a file called package.json, which you’re probably familiar with. One of the main functions of package.json is to keep track of the main dependencies of your project. However, these dependencies also rely on other libraries, which in turn may depend on even more libraries. This is where package-lock.json comes into play!
package-lock.json serves the purpose of tracking the exact versions of all dependencies (including the sub-dependencies of the packages you defined in package.json). Think of it as a snapshot of all the packages you have when you run npm install!
Here’s the thing: when you run npm install (or npm i), it has the ability to update the package-lock.json file. For example, if you have a dependency in package.json specified as “somePackage”: “^1.0.0”, and a newer version of somePackage (v1.1.0) becomes available, running npm install will update your package-lock.json with the latest version of somePackage, as well as all its dependencies.
Due to emerging tools like GitHub Dependabot, as a developer, you don’t really want to manually upgrade packages every time you make a commit. Tools like Dependabot handle dependency updates for you, ensuring that your project is always in good shape.
The same applies to automations like CI/CD pipelines/workflows. By using npm ci, you can install your dependencies while keeping the package-lock.json unchanged. This guarantees that you won’t encounter unexpected behavior caused by sudden upgrades in dependencies. Instead of using npm install, all you need to do is run:
“ci” stands for “continuous integration,” and it was initially designed for pipelines. However, I highly recommend using it even in your development environments.
Another scenario where you can utilize the “ci” command is when you’re using a git submodule and you don’t wish to make any modifications to the submodule since you’re not responsible for maintaining it.
Which npm version is compatible with lockfileVersion 2?
Lockfiles generated by npm v7+ will contain lockfileVersion: 2 : The version of package-lock.json generated on your machine depend the version of npm you are using. Lets see which version of package-lock.json associates with which version of npm :
- lockfileVersion: 1 => npm v6 and earlier.
- lockfileVersion: 2 => npm v7+, which is backwards compatible to v1 lockfiles.
- lockfileVersion: 3 => npm v7+ without backwards compatibility
Handle npm WARN read-shrinkwrap error
Some legacy codebases are still using version 1. If you’re working with a team and you happen to update your Node.js version, running npm install will automatically upgrade the entire package-lock.json to version 2. Consequently, when you commit this change with your code, it becomes irrelevant to your actual commit. This situation leads to a warning for people who are still on npm 6:
npm WARN read-shrinkwrap This version of npm is compatible with lockfileVersion@1, but package-lock.json was generated for lockfileVersion@2. I’ll try to do my best with it!
To solve this you basically have 2 options:
- every one and entire of your tool chain should upgrade the node version (recommended )
- you downgrade your npm (or even node)
Upgrade to lockfileVersion: 2
If you choose the first option and decide to upgrade your Node.js to the LTS version (16 or 18), this will result in npm version 8 or 9, as well as package-lock.json version 2. It’s crucial to communicate with your team and ensure that everyone is aware of these changes. Additionally, make sure to upgrade your toolchain, including dev containers and workflows (pipelines), to align with the updated versions.
Stay on lockfileVersion: 1
Option 1: Switch to older version of NodeJS that matched your project (recommended)
If you need to downgrade your Node.js to match a specific project, you don’t have to go through the hassle of installing and uninstalling. There is a tool called nvm (Node Version Manager) that enables you to swiftly install and utilize different versions of Node.js via the command line.
You can use the nvm CLI in the following manner to switch to your preferred version:
nvm use 14
You can also use this tool to install different versions of NodeJS. Here you can learn how to install nvm . But here is the easy way :
# install nvm on windows
choco install nvm
# install nvm on mac OS
brew install nvm
source $(brew --prefix nvm)/nvm.sh # this fixes nvm: command not found
# install nvm debian / ubuntu
curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash
#(you need to logout and login or run source ~/.bashrc )
Option 2: use higher version node but downgrade npm
In some cases you want to keep using the latest NodeJS but you want to keep the lockfileVersion, in that case you can downgrade your npm version:
npm install -g email@example.com
on mac (and linux) you run below first, if line above was not sufficient:
&& ln -s ~/.npm-packages/bin/npm /usr/local/bin/npm
And when you decide to go package-lock.json version 2, run:
npm install -g npm@latest
Older node version with lockfile version 2
If you happen to update the lockfile version to 2 and have a machine or pipeline agent that has older node (thus older npm version) , you are going to face one of these errors:
in case of
fsevents not accessible from jest-haste-map
and in case of npm install you face
This version of npm is compatible with lockfileVersion@1, but package-lock.json was generated for lockfileVersion@2
In the aforementioned scenario, you have two options: either downgrade your npm and generate the package.lock.json file with lockfile version 1 (simply run npm i and push the lock file), or upgrade the npm version on the machine that is encountering the error to match the Node.js version. Here’s an example of a GitHub workflow pipeline with a specific version:
- uses: actions/setup-node@v3
For other tools please use nvm as instructed above (Option 2).