如何使用 npm 安装多个版本的软件包

由于 https://github.com/npm/npm/issues/2943的原因,npm 永远不会支持别名软件包和安装同一软件包的多个版本。

发布在 github 问题上的解决方案可能适用于纯 JS 模块,但是随着 npm 成为前端包管理的标准,包现在包括各种资产,如 CSS。

是否有任何解决方案来安装同一软件包的多个版本?

我想到的最好的办法就是“克隆”一个包,然后用一个稍微不同的名字发布它。

例如,如果您需要 jquery的多个版本,您可以只发布称为 jquery-alias1jquery-alias2jquery-alias3等的包,然后在 package.json中设置适当的版本。

或者你可以根据它们的版本号来命名软件包,例如 jquery-1.11.xjquery-2.1.x等等。

不过,这两种方法似乎都很草率,有更好的方法吗?

97319 次浏览

听起来“ JSPM”可能正是您要寻找的工具。JSPM 构建在 NPM 之上,但是允许您从多个源(github、 NPM 等)提取包。它使用前端的 System.js 通用模块加载器来加载模块,并且“使用平面版本管理来将模块下载到版本后缀的文件夹中”,这很容易理解。

JSPM.io

使用 jspm 安装包时,可以将该包别名为特定名称,稍后可以在模块中使用 require

$ jspm install jquery
... (status msgs) ...
ok   Installed jquery as github:components/jquery@^2.1.4 (2.1.4)


$ jspm install jqueryOne=jquery@1.11.3
... (status msgs) ...
ok   Installed jqueryOne as github:components/jquery@1.11.3 (1.11.3)


github:components/jquery 1.11.3 2.1.4

然后在您的 js 中,您可以根据需要简单地使用 require(jquery)和/或 require(jqueryOne),从而允许您根据需要来回切换。

对于希望使用多个版本的。

由于 npm 的工作方式,这非常难以干净利落地完成,因此我将避免在生产环境中尝试这样做。

但是,对于集成测试和类似的用例,我创建了一个名为 多层的包,它允许您安装同一个包的多个版本,并按如下方式安装 require:

var multidepPackages = require('multidep')('test/multidep.json');


var jquery1 = multidepRequire('jquery', '1.11.3');
var jquery2 = multidepRequire('jquery', '2.1.4');

我想发布在这里的任何人喜欢我是使用 纱线和降落在这里。这是一个或多或少的插入式替代 NPM,支持别名开箱即用:

yarn add material-ui@latest
yarn add material-ui-next@npm:material-ui@next
then


import FlatButton from 'material-ui/FlatButton'; // v0.x
import Button from 'material-ui-next/Button'; // v1.x

(例如,信贷归于 https://github.com/callemall/material-ui/issues/7195#issuecomment-314547601)

NPM 安装版本(https://github.com/scott113341/npm-install-version)也是一个选项。它本质上和这里的其他一些解决方案(从技术上讲)一样,但是使用起来非常简单。用版本号安装的模块(NPM 使用的标准@version 命令参数)可以预见地安装在 Node _ module下的子文件夹中。您还可以控制每个模块的目标目录-这对于构建系统非常有用。

来自 GitHub 文档的使用代码片段:

const niv = require('npm-install-version');
const benchmark = require('./some-benchmark-function.js');


niv.install('csjs@1.0.0');
// installs csjs@1.0.0 to node_modules/csjs@1.0.0/


niv.install('csjs@1.0.1');
// installs csjs@1.0.1 to node_modules/csjs@1.0.1/


const csjs_old = niv.require('csjs@1.0.0');
const csjs_new = niv.require('csjs@1.0.1');
// require the old and new versions of csjs


benchmark([csjs_old, csjs_new], 'some-test-input');
// run our fake benchmark function on the old and new versions of csjs

install-npm-version(https://github.com/scott-lin/install-npm-version)是另一种选择。它可以在命令行上使用,也可以通过编程接口使用——用 TypeScript 编写,用于现代开发。

示例 # 1: 安装到版本化(默认)目录

import inv = require('install-npm-version');


inv.Install('chalk@2.4.0');
// installs chalk@2.4.0 to node_modules/chalk@2.4.0/


inv.Install('chalk@2.4.1');
// installs chalk@2.4.1 to node_modules/chalk@2.4.1/

示例 # 2: 安装到自定义目录

import inv = require('install-npm-version');


inv.Install('chalk@2.4.0', { 'Destination': 'some/path/chalk' });
// installs chalk@2.4.0 to node_modules/some/path/chalk/

示例 # 3: 使用静音或嘈杂的标准输出安装

import inv = require('install-npm-version');


inv.Install('chalk@2.4.0', { 'Verbosity': 'Silent' });
inv.Install('chalk@2.4.0', { 'Verbosity': 'Debug' });

示例 # 4: 覆盖现有的安装

import inv = require('install-npm-version');


inv.Install('chalk@2.4.0', { 'Destination': 'mydir' });
// installs chalk@2.4.0 to node_modules/mydir/


inv.Install('chalk@2.4.1', { 'Destination': 'mydir' });
// does not install chalk@2.4.1 since node_modules/mydir/ already exists


inv.Install('chalk@2.4.1', { 'Destination': 'mydir', 'Overwrite': true });
// installs chalk@2.4.1 to node_modules/mydir/ by overwriting existing install

Npm 从 V6.9.0开始就支持包别名,它实现了 和纱线的语法一样:

npm install jquery2@npm:jquery@2
npm install jquery3@npm:jquery@3

这使得 package.json增加了以下内容:

"dependencies": {
"jquery2": "npm:jquery@^2.2.4",
"jquery3": "npm:jquery@^3.4.1"
}

也可以直接从 GitHub 安装。例如,如果希望同时安装 npm 注册表版本和 foobar包的 GitHub 分支:

npm install foobar
npm install foobar-fork@github:username/foobar

在我的例子中,我需要安装一个比我在全球范围内安装的版本更老的 create-response-app 版本,因为我参加的课程需要这个更老的版本来完成作业。

我创建了一个新的文件夹,只是为了包含这个旧版本,cd 到它,并做了一个

npm init

在设置了这个 shell package.json 之后,我安装了我需要的具体版本的 create-response-app

npm install create-react-app@1.5.2

它使用旧版本的 create-response-app 创建了一个本地 node _ module 文件夹。

然后我创建了一个简单的 bash 脚本( create-react-app.sh )作为这个旧版本的快捷方式,并使用 bash 变量“ $@”转发所有参数:

#!/bin/bash
{full-directory-path}/node_modules/create-react-app/index.js "$@"

最后,我将这个简单的 bash 脚本设置为可执行

chmod u+x create-react-app.sh

因此,直接运行这个 bash 脚本将执行 create-response-app 的旧版本:

./create-react-app.sh  --version
1.5.2

在我的例子中,我需要安装一个比我已经安装的版本更新的版本7,即全球范围内的版本6。因此,我们面临的问题,新的开发,我们需要使用新的版本表,而不破坏旧的表功能在应用程序中,所以我安装了两个表与不同的关键-

前女友。

  1. 安装 response-table-7@npm: response-table@best-new
  2. 安装 response-table@npm: response-table@6.11.5-old

我不是 npm 方面的专家,但我有以下问题: 两个相互依赖的地方竞争一个版本。我给出的例子,作为初学者很难理解。

我在 package.json 中定义了以下两个依赖项:

"@ngtools/webpack": "^13.2.2",
"angular-named-lazy-chunks-webpack-plugin": "^2.1.0",

它们都需要一个版本的 webpack,但是是另一个版本。他们在竞争。您的评论和解决方案帮助了我,正如我在 devDependency 中定义的那样:

"webpack5": "npm:webpack@^5.68.0",
"webpack4": "npm:webpack@^4.46.0",

现在,“@ngtools/webpack”和“ angle-named- 惰性块-webpack-plugin”都很满意。 名字 webpack5和 webpack4是随机的。我想你可以把任何你喜欢的。

错误是:

npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: openpaas-ssp@0.0.0
npm ERR! Found: webpack@4.46.0
npm ERR! node_modules/webpack
npm ERR!   dev webpack@"^4.46.0" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer webpack@"^5.30.0" from @ngtools/webpack@13.2.2
npm ERR! node_modules/@ngtools/webpack
npm ERR!   dev @ngtools/webpack@"^13.2.2" from the root project

当我为 webpack 设置5.30时,那么“@ngtools/webpack”就满足了,但是我从“ angle-named- 惰性块-webpack-plugin”中得到了类似的错误

如果有人在2022年看到这篇文章,以下是您现在如何在 package.json 中完成它的方法

"graphql": "^15.8.0 || ^16.6.0 || ^15.3.0",

然后运行 npm install