优先版本
背景
Rush 通过在公共文件夹下创建了一个虚假的 rush-common 项目来实现一次性安装,该项目引用了每个项目的。例如,假设 rush.json 内有两个项目 "project1" 和 "project2"。生成的文件可能如下:
common/temp/package.json
{
"name": "rush-common",
"description": "Temporary file generated by the Rush tool",
"private": true,
"version": "0.0.0",
"dependencies": {
"@rush-temp/project1": "file:./projects/project-1.tgz",
"@rush-temp/project2": "file:./projects/project-2.tgz"
}
}
包管理器认为每个以 "@rush-temp" 命名的项目都是 rush-common 项目的直接依赖。通常而言,NPM 会首先安装项目的直接依赖(在 node_modules 树的根目录),然后再下载间接依赖。但是,由于你的项目的直接依赖现在已经间接依赖 rush-common 项目了,所以 npm install
的行为可能有些不同。
假如 project-1/package.json 如下:
{
"name": "project-1",
"version": "1.0.0",
"dependencies": {
"library-a": "1.0.1",
"library-b": "1.1.3"
}
}
接着假设 library-a (来自于互联网)如下:
{
"name": "library-a",
"version": "1.0.1",
"dependencies": {
"library-b": "^1.0.0"
}
}
如果你在 project-1 下执行 npm install
, 你会得到一个如下所示的 node_modules 文件夹,甚至如果 library-b@1.4.4 在 NPM 上有版本的话:
node_modules/
library-a/ (1.0.1)
library-b/ (1.1.3)
尽管 library-b@1.4.4 满足 "1.0.0"
的语义化版本,但是 NPM 不会下载它,因此 1.1.3(被 project-1
安装)已经满足它。
但是 common/temp/package.json 并不能保证上述行为。相反,由于 project-2 的依赖,你可能会得到这样的结果:
node_modules/
project-1/
library-b/ (1.1.3)
library-a/ (1.0.1)
library-b/ (1.4.4)
这也是语义化版本的一个有效解决方案。当使用 Rush 和 NPM 的 peer dependencies 时,可能会出现相似的问题。
优先的版本
为了控制上述影响,Rush 引入了“优先版本”的概念,这些依赖会被显式的添加到 common/temp/package.json 顶层。
你可以通过配置文件 common-versions.json 来“固定”版本,例如:
common/config/rush/common-versions.json
{
"$schema": "https://developer.microsoft.com/json-schemas/rush/v5/common-versions.schema.json",
"preferredVersions": {
"css-loader": "1.2.3"
}
}
这将会导致 css-loader 添加到 common/temp/package.json 中,如下所示:
{
"name": "rush-common",
"description": "Temporary file generated by the Rush tool",
"private": true,
"version": "0.0.0",
"dependencies": {
"css-loader": "1.2.3",
"@rush-temp/project1": "file:./projects/project-1.tgz",
"@rush-temp/project2": "file:./projects/project-2.tgz"
}
}
注意:如果你发布一个包,当你添加优先版本时候应当非常小心,因为这可能会产生一个与普通用户通过 NPM 安装你的库的不同结果。
隐性的优先版本
默认情况下,Rush 会自动将你的所有项目的直接依赖添加到 common/temp/package.json 中。在上面的例子中,这些“隐性的优先版本”可能会像这样:
common/temp/package.json
{
"name": "rush-common",
"description": "Temporary file generated by the Rush tool",
"private": true,
"version": "0.0.0",
"dependencies": {
"css-loader": "1.2.3", // <---- 明确制定的优先版本
"library-a": "~1.0.0", // <---- 隐形的优先版本
"library-b": "1.1.3", // <---- 隐形的优先版本
"@rush-temp/project1": "file:./projects/project-1.tgz",
"@rush-temp/project2": "file:./projects/project-2.tgz",
}
}
对于某个依赖而言,除了在不同的项目中指定不同的版本范围外,Rush 会自动将所有的直接依赖添加到 common/temp/package.json 中。在上述示例中,Rush 不知道哪个版本应当被认为是隐性的优先。例如,如果 project1 和 project2 指定了不同的 library-b 版本,之后你可能需要使用 common-version.json 来解决问题。
对于较老的包管理器,自动添加这个这些条目会减少间接依赖的重复。然而,隐性的优先版本可能会导致某些不兼容 peerDependencies
范围的依赖出现问题。如果你遇到了同级依赖而导致的安装错误,建议通过设定 [common/config/rush/common-version.json] 中的 implicitlyPreferredVersions
为 false
来禁用这个行为。