Two versions of the same npm package in a Node application

I am working on a CLI tool in NodeJS that uses another NodeJs package that we are developing, which is an SDK.

The fact is that we just published the V2 version of this SDK, and we want to offer the CLI user an outdated mode, so they can use either the first or second version of our SDK, for example:

$ cli do-stuff #execute sdk v2 

or

 $ LEGACY_MODE='on' cli do-stuff #execute sdk v1 

My problem is that I did not find any clean way to use two versions of the same dependency in my CLI. I tried using the npm-install-version package. It works well in my local environment, but after publishing my cli and running npm install -g my-cli it no longer works because it creates the node_modules folder in the current folder instead of the /usr/local/lib/node_modules/my-cli . I also tried multidep and I have the same problem.

At the moment, my .json package does not contain my sdk at all, but I would like to have something like:

 "dependencies": { "my-sdk": "2.0.0" "my-sdk-legacy": "1.0.0" } 

or

 "dependencies": { "my-sdk": ["2.0.0", "1.0.0"] } 

I haven't found anything yet. I am thinking of publishing the first version of my sdk with a different name, for example "my-sdk-legacy", but I would like to avoid this if possible.

Any solution for this?

+18
npm npm-install
source share
3 answers

So in fact, this is a fairly common scenario, which has been considered several times.

There is a closed problem for npm and an open problem for yarn package managers.


The first solution was proposed by NPM author in this GH comment:

Publish a separate package under a different name. This will require a specific version inside.

 { "name": "express3", "version": "1.0.0", "description":"Express version 3", "dependencies": { "express":"3" } } // index.js module.exports = require('express') 

In your case, you will publish my-sdk-v1 and my-sdk-v2 . And now you can easily install 2 versions of the package in one project without encountering conflicts.

 const mySDKLegacy = require('my-sdk-v1'); const mySDKModern = require('my-sdk-v2'); 

The second way, for the most part similar to the one suggested, is to use git url:

 { "my-sdk-v1": "git://github.com/user/my-sdk#1.0.0", "my-sdk-v2": "git://github.com/user/my-sdk#2.0.0" } 

Unlike the npm package, you can choose any name! The source of truth is git url.

Later npm-install-version popped up. Buuut, as you have already proven, its use is a bit limited. Since it spawns a child process to execute some commands and write to tmp directories. Not the most reliable way for the CLI.

To summarize: you still have options 1 and 2. I would dwell on the first one, since the name and tags of the github repository can change.

The second option with git url is better if you want to change the version so that it depends more often. Imagine that you want to publish a security patch for my-sdk-v1 legacy. It will be easier to link to the git url, then publish my-sdk-v1.1 to npm again and again.

+17
source share

Thus, in order to simply add to the current solutions, you can also provide such packages:

 yarn add my-sdk-newest@npm :my-sdk 

or in package.json

 { ... "my-sdk-newest": "npm:my-sdk", "my-sdk": "1.0.0" ... } 

if you only care about a specific outdated version and the latest.

+4
source share

Based on my answer to a similar question:

Starting with npm v6.9.0, npm now supports package aliases. It implements the same syntax that Yarn uses:

 npm install my-sdk-legacy@npm : my-sdk@1 npm install my-sdk 

This adds the following to package.json :

 "dependencies": { "my-sdk-legacy": "npm: my-sdk@ ^1.0.0", "my-sdk": "2.0.0" } 

I think this is the most elegant of the available solutions, which is compatible with the Yarn solution proposed by @Aivus.

0
source share

All Articles