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

192
由于 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等。 虽然这两种方法似乎有些粗糙。有更好的方法吗?

难道Bower不是前端包管理的标准吗?它可以轻松地完成这个任务。 (https://dev59.com/RWQn5IYBdhLWcg3w9K_3) - laggingreflex
是的,bower 看起来是一个替代方案。遗憾的是似乎没有 npm 的解决方案,因为向一个大型团队引入另一个包管理系统可能很困难,特别是如果你已经有基础设施支持 npm(例如私有的 npm 注册服务器)。 - mark
这个回答解决了你的问题吗?如何使用npm安装两个不同版本的Bootstrap? - Julian
12个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
263

v6.9.0起,npm支持包别名,并实现了与Yarn相同的语法

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

2
yarn 还支持软件包别名。 - Greg K
嗨,我已经尝试了以下步骤来安装两个包:"react-native-track-player": "1.1.4"和"react-native-track-player": "1.1.8"。在iOS上运行良好,但在Android上显示一个错误,即“MusicManager$1被定义多次”。我该如何防止Android构建1.1.8? - EmBeCoRau
因为库中存在一些冲突,所以我需要在iOS上使用1.1.8版本,在Android上使用1.1.4版本。 - EmBeCoRau
对我来说没有用,因为依赖项的别名与它所寻找的不同,即它正在寻找 eslint,但不知道它现在被命名为 eslint6 - Crimbo
这对于在小步骤(大型代码库)中迁移到新版本非常棒,但愿我早些知道这个。 - josias

106

我想在这里发布一些信息,特别是像我这样正在使用 Yarn 且来到这里的人。它是 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


34
谢谢。为了澄清,通用的公式是 <alternative-name>@npm:<package-name>@<version> - katsos
太棒了。我尝试安装 yarn add react-bootstrap4@npm:react-bootstrap@1.5.1,但是 React Webpacker 抱怨找不到模块 react-bootstrap4。然而,yarn add react-bootstrap-next@npm:react-bootstrap@1.5.1 却完美地工作了。 - new2cpp
嗨,有没有使用npm的解决方案? - famfamfam

5
看起来 "JSPM" 可能正是您需要的工具。JSPM 在 NPM 基础上构建,允许您从多个来源(github,npm 等)拉取软件包。它在前端使用 System.js 通用模块加载器来加载模块,并且“使用平面版本管理下载到带有 版本后缀文件夹 的”软件包,这样易于理解。 请参考以下链接了解更多信息:jspm.io 当您使用 jspm 安装软件包时,可以将该软件包别名为特定名称,稍后可以在模块中特别地要求使用它。
$ 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),如果需要的话,允许你根据需要来回切换。

对于任何你想使用多个版本的包,都适用这个方法。


4

我不是npm的专家,但我有以下问题:两个依赖项在争夺一个版本。 我提供一个例子,因为对于初学者来说很难理解。

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

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

他们都需要webpack的一个版本,但是不同的版本。他们之间存在竞争关系。你的评论和解决方案对我很有帮助,因为我在devDependencies中定义了以下内容:

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

现在,"@ngtools/webpack" 和 "angular-named-lazy-chunks-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"已经被满足,但我仍然从"angular-named-lazy-chunks-webpack-plugin"中获得了类似的错误。


4

我需要安装react-table新版本7,而我之前全局安装的是旧版本6。因此,我们面临一个问题,在应用程序中需要使用新版本表格进行新开发,但不能破坏旧表格的功能,所以我安装了两个带有不同关键字的表格。

例如:

  1. npm install react-table-7@npm:react-table@latest - 新
  2. npm install react-table@npm:react-table@6.11.5 - 旧

2
这很难清洁地完成,因为npm的工作方式,因此我建议避免在生产环境中尝试这样做。 但是,对于集成测试和类似的用例,我创建了一个名为multidep的包,它可以让您安装同一软件包的多个版本并像这样使用require

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

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

2
在我的情况下,我需要安装一个比我全局安装的版本更旧的create-react-app版本,因为我正在参加一门要求使用这个旧版本的课程。 我创建了一个新的文件夹来包含这个旧版本,进入该文件夹并执行以下命令:
npm init

在设置了这个shell package.json之后,我安装了我需要的确切版本的create-react-app。

npm install create-react-app@1.5.2

这个操作会在本地创建一个node_modules文件夹,并包含旧版本的create-react-app。

之后我创建了一个名为create-react-app.sh的简单bash脚本,作为访问旧版本的快捷方式,并使用bash变量"$@"来转发所有参数:

#!/bin/bash
{full-directory-path}/node_modules/create-react-app/index.js "$@"
最后,我使这个简单的bash脚本可执行。
chmod u+x create-react-app.sh
直接运行此bash脚本将执行旧版本的create-react-app:
./create-react-app.sh  --version
1.5.2

你好,我想安装 react-native-reanimated v2.10.0 和 v3.1.0 版本,能帮忙吗? - famfamfam

1
如果有人在2022年看到这篇文章,以下是如何在您的package.json文件中实现此操作的方法。
"graphql": "^15.8.0 || ^16.6.0 || ^15.3.0",
你需要运行 npm install。

我很确定它只会选择其中一个版本,而不是安装全部三个。 - Florian Wendelborn

0

NPM Install Version (https://github.com/scott113341/npm-install-version) 是另一个选择。它本质上与这里的其他解决方案做的事情相同(从技术角度讲),但使用起来非常简单。使用版本号(NPM使用的标准@version命令参数)安装的模块会被预测性地安装在名为该名称的子文件夹下的node_modules文件夹中。您还可以控制每个模块的目标目录-这对于构建系统非常有用。

来自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

0
如果在更新一个包时,另一个包仍然依赖于旧版本,你可以允许两个版本存在于包树的不同部分,以解决冲突的对等依赖关系: npm install --legacy-peer-deps

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,