我使用 yarn 直接从公司的 GitLab 安装软件包:
yarn add git+ssh://<user>@<host>:<repo>
对于一级依赖,我使用yarn --pure-lockfile
根据yarn.lock
重建我的node_modules
。
但是,对于二级依赖项,yarn 似乎总是安装最新版本。
因此,假设我依赖于使用特定版本的B
进行测试的A
。在 A 的package.json
中,我没有指定版本,但它包含在yarn.lock
中。
当我现在安装软件包A
纱线将获得最新版本的B
尽管有条目A/yarn.lock
我知道我可能会通过在A/package.json
中传递特定版本来解决此问题(至少我认为)。
但是有没有一个选项可以告诉纱线查看依赖关系yarn.lock
?
TLDR:
当您在 应用程序,只考虑您自己的 yarn.lock 文件。锁定文件 在您的依赖项中将被忽略。参考
让我们先弄清楚一些事情:
--pure-lockfile
与普通纱线安装相同,只是它不会生成yarn.lock
文件或更新文件(如果存在)。- 默认情况下,Yarn 始终从
yarn.lock
读取以在安装时解析依赖项,除非随--no-lockfile
提供。因此,无需告诉它从yarn.lock
中读取.
yarn.lock
是做什么用的?
yarn.lock
用于解决应获取哪些version
给定模块在package.json
中的semver version
.它不用于确定模块应解析为哪个semver version
。这根本不是它的用例。
如纱线文档所述:为了保持一致 跨机器安装,Yarn 需要比 在包 JSON 中配置的依赖项。纱线需要储存 确切地安装了每个依赖项的哪些版本。
为此,Yarn 在项目的根目录中使用
yarn.lock
文件。
因此,为了解决依赖关系semver version
,纱线始终取决于package.json
。对于给定的semver version
,yarn 会检查yarn.lock
文件,看看它应该获取什么version
。这就是纱线确定性的原因(使用npm-shrinkwrap.json
的纱线npm
使用相同的技术)。
示例:像^1.2.4
这样的Semver版本可以解析为>= 1.2.3 and < 2.0.0
的任何版本号。如果没有 yarn,npm 会在一台机器上安装1.2.4
,但在另一台机器上1.9.9
,具体取决于安装时存在的最新版本。这是纱线使用yarn.lock
解决的问题。
semver version
由package.json
文件。yarn.lock
文件只是一个查找版本并提交要为给定semver version
编号安装的哈希。
yarn 如何在给定模块的 semver 版本的情况下解析模块的版本?
假设当前我们的yarn.lock文件如下所示:
bluebird@2.9.6:
version "2.9.6"
resolved "https://<...>/bluebird-2.9.6.tgz#1fc3a6b1685267dc121b5ec89b32ce069d81ab7d"
bluebird@^2.9.30:
version "2.11.0"
resolved "https://<...>/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1"
...
myModule@5.1.0:
version "5.1.0"
resolved "https://<...>/moduleA-5.1.0.tgz#ce97130858add59d616ee80675383b0c127290a0"
dependencies:
bluebird "^1.0.0"
- 如果 package.json 有
bluebird: "^2.9.30"
,yarn 会在锁文件中查找bluebird@^2.9.30
条目。它存在,因此决心version=2.11.0
。 - 如果 package.json 有
bluebird: "^2.9.0"
,yarn 会在锁文件中查找bluebird@^2.9.0
条目。它不存在。假设满足 semver 标准的最新稳定版本是2.13.0
,那么 yarn 为bluebird@^2.9.0
添加一个条目,解析为2.13.0
。在解析给定semver version
的蓝鸟版本时,锁文件中模块 A 的依赖项中蓝鸟存在什么条目并不重要。
Semver Version
不受条目的影响 存在于yarn.lock
文件中模块的依赖项映射中。
因此,如果 package.json 有bluebird: ""
,yarn 会在锁文件中查找bluebird@
条目,但找不到它。因此,它bluebird: ""
解析为最新版本,假设3.5.0
.现在,yarn 将添加一个条目,用于bluebird@
解析为3.5.0
。
bluebird@:
version "3.5.0"
resolved "https://<...>/bluebird-3.5.0.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9"
现在,每当纱线遇到{bluebird: ""}
时,它都会在锁文件中找到bluebird@
的条目,因此总是会将其解析为3.5.0
。
解决您的问题
要解析B: ""
版本(例如1.0.0
),您需要有一个条目用于B@
yarn.lock
解析为1.0.0
。一旦,yarn.lock
有一个B@
条目,所有连续的安装将始终获取版本1.0.0
用于B=""
。
以下是完成相同操作所需执行的步骤:
方法 1(推荐)
如果您希望 B 解析为最新版本:
- 在 A 的包中添加
B:""
.json - 运行
yarn install
.这将添加一个条目,用于B@
解析为最新版本。 - 推送
yarn.lock
文件。 - 现在开始,无论谁运行
yarn install
都将获得相同的版本。
方法2
如果您希望 B 具有旧版本:(强烈不推荐)
- 在 A 的 package.json 中添加
B: 1.0.0
。 - 运行
yarn install
.这将在锁定文件中添加一个条目B@1.0.0
。 - 在 yarn.lock 中与
B@1.0.0
一起添加B@
。B@, B@1.0.0: ...
- 将 B 的版本更改为 A 的 package.json 中的
""
。 - 推送
yarn.lock
文件。 - 现在形成,无论谁运行
yarn install
都将获得 B 的版本作为1.0.0
。
这种方法非常危险,因为您很容易破坏某些东西。您的 yarn.lock 文件应始终由 yarn 管理。
方法 3(推荐)
如果您希望 B 保持在 1.0.0
- 将 B 的版本修复为 A 的 package.json 中的
1.0.0
。 - 运行
yarn install
.这将在锁定文件中添加一个条目B@1.0.0
。 - 推送纱线锁定文件
- 现在开始形成,无论谁运行
yarn install
都将获得 B 的版本作为1.0.0
.
编辑:使用依赖项中存在的 yarn.lock 文件
如果你检查这个doc:,他们已经明确提到yarn将只使用顶级yarn.lock文件,而忽略依赖项中存在的锁定文件。
目前没有办法使用其中存在的 yarn.lock 锁定二级依赖项。我认为没有必要。事实上,纱线的创造者在这里解释了为什么会这样。原因是:
- 要为二级依赖项安装的版本可以是 正如我所解释的,被顶级 yarn.lock 文件捕获得很好 以上。
- 直接使用子依赖项时,您将永远无法更新自己的应用程序中子依赖项的版本,因为它们会被其他 yarn.lock 文件锁定。你可以通过我对纱线如何解决依赖关系的解释来验证这一点。
- Yarn 永远无法折叠(删除重复)依赖项,以便兼容的版本范围仅安装单个版本。
此外,就像在您的用例中一样,如果 A 有一个仅适用于版本1.0.0
的依赖项 B,则 A 的 package.json 应该将 B 的版本称为1.0.0
而不是 "。您始终可以修复顶级yarn.lock
以添加B@
解析为1.0.0
的条目,但不建议像我上面提到的手动修复 yarn.lock 文件。
希望这有帮助!如有任何疑问,请在评论中 ping 我。