Две версии одного и того же пакета npm в приложении Node

Я работаю над инструментом CLI в NodeJS, который использует другой пакет NodeJs, который мы разрабатываем, который является SDK.

Дело в том, что мы только что опубликовали версию V2 этого SDK, и мы хотим предложить пользователю CLI устаревший режим, поэтому они могут использовать либо первую, либо вторую версию нашего SDK, например:

$ cli do-stuff
#execute sdk v2

или

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

Моя проблема в том, что я не нашел никакого чистого способа использовать две версии одной и той же зависимости в моем CLI. Я попытался использовать пакет npm-install-version. Он хорошо работает в моей локальной среде, но после публикации моего cli и выполнения npm install -g my-cli он больше не работает, потому что он создает папку node_modules в текущей папке вместо папки /usr/local/lib/node_modules/my-cli. Я также пробовал multidep, и у меня есть одна и та же проблема.

На данный момент мой пакет .json вообще не содержит моего sdk, но я хотел бы иметь что-то вроде:

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

или

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

Я еще ничего не нашел. Я думаю о публикации первой версии моего пакета sdk с другим именем, например "my-sdk-legacy", но я хотел бы избежать этого, если это возможно.

Любое решение для этого?

Ответ 1

Так что на самом деле это довольно распространенный сценарий, который рассматривался несколько раз.

Существует закрытая проблема для npm и открытая проблема для менеджеров пакетов пряжи.


Первое решение было предложено автором NPM в этом комментарии GH:

Опубликуйте отдельный пакет под другим именем. Это потребует определенной версии внутри.

{ "name": "express3",
  "version": "1.0.0",
  "description":"Express version 3",
  "dependencies": { "express":"3" } }

// index.js
module.exports = require('express')

В вашем случае вы опубликуете my-sdk-v1 и my-sdk-v2. И теперь вы можете легко установить 2 версии пакета в одном проекте, не сталкиваясь с конфликтами.

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

Второй способ, по большей части аналогичный предложенной, - использовать 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"
}

В отличие от пакета npm, вы можете выбрать любое имя! Источником правды является git url.

Позже выскочила npm-install-version. Buuut, как вы уже доказали, его использование немного ограничено. Так как он порождает дочерний процесс для выполнения некоторых команд и записи в каталоги tmp. Не самый надежный способ для CLI.

Подводя итог: у вас остались варианты 1 и 2. Я бы остановился на первом, поскольку имя и теги репозитория github могут измениться.

Второй вариант с git url лучше, если вы хотите изменить версию, чтобы она зависела чаще. Представьте, что вы хотите опубликовать исправление безопасности для my-sdk-v1 legacy. Будет легче ссылаться на URL-адрес git, затем снова и снова публиковать my-sdk-v1.1 в npm.

Ответ 2

Таким образом, чтобы просто добавить к текущим решениям, вы также можете предоставить такие пакеты:

yarn add [email protected]:my-sdk

или в package.json

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

если вы заботитесь только о конкретной устаревшей версии и новейшей.

Ответ 3

Исходя из моего ответа на аналогичный вопрос:

Начиная с npm v6.9.0, npm теперь поддерживает псевдонимы пакетов. Он реализует тот же синтаксис, который использует Yarn:

npm install [email protected]:[email protected]
npm install my-sdk

Это добавляет следующее в package.json:

"dependencies": {
  "my-sdk-legacy": "npm:[email protected]^1.0.0",
  "my-sdk": "2.0.0"
}

Мне кажется, это самое элегантное из доступных решений, которое совместимо с решением Yarn, предложенным @Aivus.