Recently I had to re-deploy an old Node.js project, which still runs node.js v0.10.x (it is pointless to upgrade it, a whole new project will replace it soon).
What I found is that quite a few nested dependencies ended up not working with Node.js v0.10 (it was a long chain of dependencies, each linking to a "too new" version of their dependencies due to not an optimal semver)
One solution one can find online is to use npm shrinkwrap --dev
to generate an npm-shrinkwrap.json file, and manually update its content to point to the right versions of the nested dependencies. The problem is - there were too many of these to update since many nested dependencies I had to change in turn had their dependencies, and tracking all that down manually was just not feasible.
For example - one of the modules was depending on module request
with semver ^2.34.0
. Which in turn picked up the latest available version 2.84.0
. The problem is - 2.34.0 works with node v0.10, while 2.84.0 does not, since the latter relies on the support of some ES6 features, like const
. That is a bug in versioning, but there is no quick way for me to fix it, so I had to work around it.
The workaround, once found, was relatively easy. I started with a clean slate and removed node_modules
:
rm -rf node_modules
After that I installed all the modules, and, since in my case npm i
would break due to scripts running as part of the post-install process, I needed to disable the post install scripts:
npm install --ignore-scripts
Now, for each problematic dependency I would cd
into its folder and manually install a working version of the dependency. To find the right version I simply open package.json and check version in there. Like with the module request
above, I saw that originally the author relied on the version of request@2.34.0
and that is what I will manually install:
cd node_modules/dependency_causing_troubles npm i --save --save-exact request@2.34.0 cd -
That will force module dependency_causing_troubles
to use the version of request
set at exactly to 2.34.0
.
Obviously, the whole thing will break down right after next npm install
during deployment to a new host. To make sure we get the same repeatable build, we will use NPM's shrinkwrap feature:
npm shrinkwrap --dev
That will create npm-shrinkwrap.json
which NPM will use instead of package.json when installing dependencies. And that file lists exact versions and exact URLs to download these modules from, so you will get exact 1:1 build on the host you are deploying it on.
Commit that npm-shrinkwrap.json
into your repo and deploy.