yarn 运行命令(yarn 运行命令卡住)

yarn 运行命令(yarn 运行命令卡住)最近有个想法 希望在一个 yarn workspace 项目中实现任意一个子包中安装依赖时 都执行一些类似于初始化 同步配置的动作 然而在操作过程中遇到了一个关于 有趣的问题 特地记录下来 希望能对后来者有所帮助 先交代一下我们项目的基本情况 它是一个通过 yarn workspace 管理的 monorepo 项目 使用的是 yarn v1 22 11 版本 目录结构大致如下 其中 和 都使用了 这个共享包 我们需要在根目录的 中的 钩子做一些初始化操作 此时我们在根目录执行



最近有个想法,希望在一个 yarn workspace 项目中实现任意一个子包中安装依赖时,都执行一些类似于初始化、同步配置的动作。

然而在操作过程中遇到了一个关于 有趣的问题,特地记录下来,希望能对后来者有所帮助。

先交代一下我们项目的基本情况,它是一个通过 yarn workspace 管理的 monorepo 项目,使用的是 yarn v1.22.11 版本,目录结构大致如下:

其中 和 都使用了 这个共享包:

我们需要在根目录的 中的 钩子做一些初始化操作:

此时我们在根目录执行 或者 ,都会触发 这个钩子,但在 中执行 是不会触发根目录的 钩子的。

因此,我们需要分别在每个子包上都加上这行,也即在每个子包安装依赖时都执行一下根目录的 命令:

于是,奇怪的事情就发生了,当我在 中执行 的时候,它停留在安装 的阶段,同时我的电脑明显变得卡顿,于是打开 一看,好家伙,满屏都是:

CPU 占用率直接达到 100%,吓得我赶紧 kill 掉这些进程:

惊吓过后,来分析一下原因,很显然这段命令陷入了死循环,导致越来越多进程,于是尝试在每个子包中都手动执行一遍 后,发现一切正常,那问题出在哪呢?

于是我再执行了一遍 ,并且用以下命令将进程信息复制出来,以便分析:

随后验证我刚刚的猜测,的确是这个命令在不断触发自己,导致死循环:

由于三个分包执行的命令都一样,不清楚是不是由于某个分包引起,于是修改一下命令以便区分:

随后发现问题是出现在 这个子包,于是我把这个子包的 命令去掉,果然没有这个问题了,非常奇怪。

难道是 这个路径有问题?验证一下,把命令改成这样:

发现 输出是这样子的:

从这里的输出我们发现了两个问题,第一个问题是:

  • yarn workspace 共享包的 被执行的时候,其实已经被拷贝到 的 中,而不是在当前目录,因此 并不指向项目根目录。

这一点比较好理解,毕竟 作为一个依赖包,确实应该被拷贝到应用的 。

而第二个问题就不太理解了,为什么明明设置了 ,却依然在当前目录执行呢?按照预期 cwd 的指向应该是:

难道是我对 cwd 参数的理解有偏差?看一下 yarn 的文档中对 cwd 描述:

Specifies a current working directory, instead of the default https://bianchenghao.cn/article/. Use this flag to perform an operation in a working directory that is not the current one.

This can make scripts nicer by avoiding the need to cd into a folder and then cd back out.

从文档的描述来看,cwd 的作用不就是代替 吗,但现在的结果看来 并不等价于 。

这就不得不让人疑惑 cwd 的定位方式了,在网上搜寻一番没找到相关的讨论,那只能自己动手丰衣足食,直接从 yarn 源码中寻找答案。

前面我们说到,我们使用的是 yarn v1.22.11,在 yarn 的 GitHub 仓库中发现 v1 版本的最新版本停留在 v1.23.0-0,那我们就从这个版本的源码来进行分析,首先克隆代码到本地:

然后安装依赖并运行起来:

这时候它就会自动监听代码修改然后重新编译,我们查看 发现 yarn 的 bin 主要是调用 :

也就是我们直接执行 的效果就如同执行 ,试一下查看版本:

PS:当然你也可以在项目目录下使用 把它挂载到本地中。

接下就是一番调试,终于定位到可以回答我们疑问的代码,在这里:

可以看到 cwd 的定位方式是从当前目录寻找是否存在 ,若存在,则返回此目录,否则将目录经过 处理一遍,继续寻找,直到寻找到最外层。

那么这里最关键的是 的返回值,我们先看一下文档对于它的描述:

The path.dirname() method returns the directory name of a path, similar to the Unix dirname command. Trailing directory separators are ignored,

就是返回一个路径中的目录部分,作用与 unix 下的 dirname 命令一致,通常是这么使用的:

是不是会肤浅地认为它的作用就是返回一个路径的上一级目录?如果传入的是一个绝对路径,确实可以这么肤浅地认为,然而当传入的是一个相对路径时,情况就不一样了:

问: 会返回什么呢?

答案是:,也就是当前目录。

那这里就能回答我们之前的问题,为什么在 中使用 却在当前目录执行,因为它的上一级 不存在 ,所以经过 处理后 cwd 的指向就是当前目录。

如果对 node.js 中 的实现方式感兴趣,可以看这里 path.js#L538-L554。

摸清楚原因后,那解决这个问题也不是难事,只要我们把相对路径改成绝对路径,是不是就能解决这个问题了?

思考一下,其实 ,把 改成绝对路径行不行呢?比如在本文的场景, 其实就是项目的根目录,那我们完全可以通过别的方式获取到项目的根目录,比如 在 git 中:

所以,我们把命令改成这样,问题就迎刃而解了:

那就不得不提一下,其实在 yarn v2 中新增了一个 属性,它的作用刚好就是为了解决这个问题。

其实我们再回过头来想,在本文的例子中,根本不需要在 目录中添加 这个钩子,因为它作为共享包,每次修改都必然要在其它使用这个包的地方,重新安装一次,所以只要确保这些地方会执行 就可以了,那也就意味着不会出现本文遇到的问题。

不过,多踩坑也不是坏事,只要搞清楚背后的原因,问题也就不是问题。

以上就是yarn 命令死循环问题分析解决的详细内容,更多关于yarn 命令死循环的资料请关注Java架构师必看其它相关文章!

今天的文章 yarn 运行命令(yarn 运行命令卡住)分享到此就结束了,感谢您的阅读。
编程小号
上一篇 2026-01-18 22:33
下一篇 2025-04-06 11:06

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ri-ji/33397.html