<p>yarn可能不应该缓存使用文件路径解析的软件包</p>

创建于 2016-12-06  ·  75评论  ·  资料来源: yarnpkg/yarn

您是否要请求功能或报告错误

我猜是_bug_。

目前的行为是什么?
如果当前行为是错误,请提供重现步骤。

假设您具有以下项目结构:

component-foo/
└── package.json
└── index.js

yarn-test/
└── package.json

带有以下文件:

component-foo/package.json

{
  "name": "component-foo",
  "version": "1.0.0",
  "private": true,
  "main": "index.js"
}

component-foo/index.js

console.log('foo');

yarn-test/package.json

{
  "name": "yarn-test",
  "version": "1.0.0",
  "private": true,
  "dependencies": {
    "component-foo": "file:../component-foo"
  }
}

现在,您在$ yarn install内运行yarn-test/yarn-test/node_modules/component-foo/index.js是:

console.log('foo');

现在删除yarn-test/node_modules/yarn-test/yarn.lock并将component-foo/index.js更改为此:

console.log('bar');

现在,您再次在yarn-test/ $ yarn install内运行yarn-test/node_modules/component-foo/index.js将是:

console.log('foo');

它使用component-foo的缓存版本,但是component-foo/index.js已更改。

预期的行为是什么?

我希望yarn-test/node_modules/component-foo/index.js应该是这个:

console.log('bar');

如果我们无法弄清楚它们是否已更改,则也许根本不应该缓存安装有file:../类的本地路径的软件包。

(仅供参考:npm似乎没有缓存它们。)

请提及您的node.js,yarn和操作系统版本。

$ node -v
v6.9.1

$ yarn -V
0.18.0

macOS 10.12.1

最有用的评论

@hantuzun为什么要完全缓存本地依赖项? 它们无论如何都是本地的,因此无论是否缓存都将很快。

所有75条评论

这也骗了我。 必须有一种解决方法,而不必清除所有缓存。

我认为可以通过三种方式使纱线在这种情况下可用:

  1. @donaldpipowitch建议忽略所有本地依赖项。
  2. 如果其中的文件的修改晚于缓存,则重新安装本地依赖项。 这将要求我们保留此元数据。 对于本地依赖项,我们可以在“已解决”列中插入以下行: file://<path>@<cache_timestamp>
  3. 使用yarn cache rm <package>yarn cache add <package>命令按软件包名称忽略软件包。 对于所有依赖项。

我希望看到第二条建议得以实施。 除非,第三种选择对其他情况也可能有用。 例如, yarn cache add <package>可用于为已缓存的依赖项刷新缓存,以防在下载依赖项时出现问题。

@hantuzun为什么要完全缓存本地依赖项? 它们无论如何都是本地的,因此无论是否缓存都将很快。

@ satya164你是对的。 虽然,我更倾向于第三种方法,如果有意修改来自网络的依赖关系,将有所帮助。

yarn cache ignore <package>这样的东西会很有用。 但我认为它们不必相互排斥。 忽略软件包很有用,但是需要手动操作。 如果默认情况下忽略了文件依赖关系,则可以使其工作而无需任何额外的努力。

有人可以解释我的内部逻辑吗?

我的理解:
当遇到具有file:的依赖项时, file-resolver.js加入。它表示应该复制该依赖项,并且不要将其散列。 不是没有哈希意味着它不应该已经被缓存...? 但是copy-fetcher.js似乎将哈希设置为空字符串,而不是保留null ...这是问题吗?

@bestander@kittens也许您可以再解释一下...? 希望得到一点帮助来创建PR♥

哈希表示例如用于tarball-fetcher的md5哈希。
然后,将此散列添加到yarn.lock文件中以供将来验证,并且在将未压缩的文件夹保存在缓存中时,还附加到文件夹名称中。
您正在朝正确的方向发展,感谢您对此进行调查,非常欢迎公关。
您可能可以从添加损坏的单元测试的PR开始

您可能可以从添加损坏的单元测试的PR开始

好的,谢谢您的回复。 我应该ping您作为PR中的审阅者还是应该ping其他人(或没有人)...?

是的,ping我

@bestander可能尚未解决此问题,因为它尚未解决?

是的,应该重新打开它。 因为我在PR的标题中写了“ fixs#2165”,所以它关闭了。 一开始我以为这将是一个正在进行的PR,但是要解决此错误,我们需要两个PR:第一个PR添加了单元测试(失败的断言实际上不是活动的,因此CI不会崩溃),并且第二个实际上会解决它。

抱歉,合并PR时github关闭了问题

显然这仍然是一个问题吗? 老实说,和它一起开发很烦人。 在我个人的工作水平上,这给我造成了一些干扰,其中我利用file:创建一个模块化的开发环境。 该苏茨基的是,每一个本地包,我的编辑(使用file:路径package.json ),要求这样做,为了拉下刷新内容:

编辑我的eslint-config-base-eslint软件包的内容

yarn cache clean && rm -rf node_modules/eslint-config-base-eslint && yarn install --force && yarn lint

欢迎大家为该项目做出贡献。
可能是任何事情-为此案例提交损坏的集成测试,修复程序或说服某人进行修复。
如果您想讨论实现此目标的最佳方法,可以在不和谐频道上找到帮助。

我实际上认为该修补程序应该是10-15行代码,这可能会节省很多时间及早修复它

仅供参考:这可能与缓慢的linking dependencies步骤有关。 在这里查看我的评论: https :

抱歉。 我找不到时间为这个问题创建另一个PR :(我当时(现在仍然很忙)。

@bestander对我来说,这是一个非常大的阻止程序,致力于多模块项目。 如果我正确阅读了@donaldpipowitch的代码链接和注释,是否可以让文件解析器每次尝试解析时都创建一个新的hash (而不是null),以便强制重新安装? 说一个UUID或当前时间戳? 如果我缺少什么,请原谅我,我对代码的工作方式并不熟悉。

带有时间戳和uuid的新缓存听起来像是合理的破解。
理想情况下,我们应该直接复制文件而不使用缓存,但这可能是
更复杂的变化。
继续发送公关

在2017年3月7日星期二03:38,Matt Traynham [email protected]写道:

@bestander https://github.com/bestander这是一个很大的阻止者
对我来说,从事多模块项目。 如果我正在阅读@donaldpipowitch
https://github.com/donaldpipowitch的代码链接和注释
正确地,我们可以让文件解析器创建一个新的哈希(而不是
null),每次尝试解决时都会强制重新安装? 说一个UUID
还是当前时间戳? 如果我错过了什么,请原谅我,我不熟悉
代码的工作方式。

-
您收到此邮件是因为有人提到您。

直接回复此电子邮件,在GitHub上查看
https://github.com/yarnpkg/yarn/issues/2165#issuecomment-284612526或静音
线程
https://github.com/notifications/unsubscribe-auth/ACBdWDS3xSr8KNu1o9Zn8sA9xdO8pyHOks5rjNEmgaJpZM4LFbmf

@bestander关于您的最后评论:将其符号链接而不是复制文件更有意义吗? 还是有任何理由不这样做?

@danrot Windows似乎需要管理员进行符号链接。
也弄乱了递归查找节点模块

Symlink也忽略.npmignore东西。 (当前似乎也被忽略了。可能会有问题:https://github.com/yarnpkg/yarn/issues/1496#issuecomment-282688818)

目前是否有任何变通办法禁止清除整个缓存? 不幸的是,似乎没有yarn cache rm package kind-of命令。

@ rhys-e我使用这个小脚本:

#!/bin/sh
if [ $# != 1 ]
then
   echo Usage $0 package-name
   exit 1
else
    echo Reinstalling $1
fi

dir="node_modules/$1"

if [ -d $dir ]
then
    rm -fr $dir
fi

cache=`yarn cache dir`/npm-${1}*
#        echo $cache
rm -fr $cache && yarn install --force

曾经有人尝试过以yarn link全部在本地依赖性postinstall ? 看起来像是适当的解决方案,直到正确的修复程序着陆为止。

我想这个想法是不必为本地依赖项的每次更改都更新软件包的版本号。 纱线连接会迫使您这样做,对吗? (没有尝试)

在我这边,我最后要做的是在preInstall阶段调用一个脚本,该脚本比较source文件夹和node_modules文件夹中的内容是否具有本地依赖性。 如果检测到任何差异,它将删除缓存的依赖项并删除完整性文件(强制重新安装)。 因此,当没有任何变化时,yarn的安装会非常快(本地依赖项不多),并且如果存在过时的缓存版本,则不会使用。

@lucdew链接基本上会在

我已经测试了不同的组合,以解决本地包中未在./node_modules/下的父项目的已安装版本中更新的更改。 我发现只需这样做,无需删除./node_modules/第一:

yarn cache clean; yarn upgrade file:../<package>

毋庸置疑,为了更新/升级本地程序包,无需手动强制清除全局缓存。

@fungilation作为一种解决方法,您还可以使用npm安装本地依赖项,从而避免每次想要更新时都丢失整个缓存。

根据#2860及后续合并提交https://github.com/yarnpkg/yarn/commit/7241de13bb236526fa439a2528fbed319f60ef24 ,您现在可以使用以下方式“刷新” file:协议依赖

yarn install --force

编辑或升级特定的程序包(并没有意识到这是行得通的)。 如果依赖项版本未更改,则不会修改锁定文件,但仍会复制较新的版本。

yarn upgrade [file protocol package name]

PR更改将使缓存中的依赖项无效并在本地重新安装。 如果依赖项版本更改, yarn install也将起作用,这会使yarn.lock文件无效。 您不再需要清除缓存,也无需从本地安装中删除模块。

对我来说,很明显,有一个有效的RFC用于链接依赖关系,可能是使用link:协议。 在这里可以遵循, https://github.com/yarnpkg/rfcs/pull/34。

@mtraynham谢谢您的请求! 👌太棒了。 为什么需要--force ? 我现在什至不知道它现在到底在做什么,而无需查找它:)只是问一下,因为npm不需要--force标志,并且表现得像npm一样不错。

编辑看起来像yarn upgrade [dependency]也可以。 我要指出的是,这并不总是更改锁文件,而锁文件仅应反映package.json版本的更改。 我已经更新了原始帖子,因为升级可能更合适。


简短的版本是,如果锁定文件未更改,则Yarn不会对缓存解析器执行任何操作,因此我们需要跳过锁定文件检查,并询问缓存是否有较新的版本。 可以使用upgradeinstall --force

yarn install --force文档

“它将重新提取所有软件包,甚至以前安装的软件包”。

这确实意味着它将跳过锁定文件完整性检查。 如果您不更改package.json文件并妥善保释,则锁定文件完整性检查通常会通过。 跳过它会要求缓存检查锁定文件是否缺少/不匹配的依赖项,如果缺少则下载它们,然后在本地复制任何新的/缺少的依赖项。 然后运行npm install / postInstall脚本。

现在,PR更改将使高速缓存中的file:依赖关系无效,并将新版本复制到本地。 在此之前,它将永远不会使file:依赖关系无效。 对于其他协议,如果您不更改package.json文件,它们将保持不变(在缓存中和本地)。

那对我们意味着什么? 我对一个项目(从Angular到Webpack)有大约60个依赖项,其中一个具有file:依赖项。 在第二个install --force ,我只想刷新本地依赖项,它大约需要5秒钟( yarn install则需要1.5秒)。 对我而言,这几乎可以忽略不计,而实际上,纱线在整个过程中所尝试执行的工作量却很少。

如果还有另一个CLI命令可以跳过锁定文件检查,仅检查特定文件依赖项的缓存,那可能会更快,但是我还没有找到。


话虽如此,我还是称它为创可贴。 可以用更好的解决方案来代替,例如link: ; 我认为没有人真正在乎缓存本地依赖项。 至少,使用install --forceupgrade的额外开销在大多数情况下是疏忽大意的,您不再需要yarn cache clean; mv node_modules /tmp/

好答案。 👏感谢您写下来。

yarn是否会使用yarn缓存中的文件覆盖本地符号链接的项目文件? (因为看起来就是这样)

现在,PR更改将使文件:缓存中的依赖项无效,并将新版本复制到本地。

这是否意味着每当我在以"foo": "file:../"作为依赖的程序包中调用$ yarn "file:../"都会创建

例如,我有一个包含多个示例的软件包,这些示例也是软件包:

foo/
foo/examples/
foo/examples/example-1/
foo/examples/example-2/
foo/examples/example-3/
...
foo/examples/example-10/

看起来我现在在纱线高速缓存中有foo 10次​​。 我还在foo每个版本更改上测试了我的示例(并且我以这种方式配置了多个模块,而不仅仅是foo ),因此看起来我的纱线缓存当前增长很快。

这是正确的行为吗?

我认为这比在缓存中使用陈旧版本更好。
使用yarn 0.26,您可以使用link:创建符号链接,而不是复制文件。
另外,我们还在致力于自动创建符号链接的工作区, https://github.com/yarnpkg/yarn/issues/3294

是的,期待工作pac

link:尚不适用于npm,对吗? (因为https://github.com/npm/npm/pull/15900仍处于打开状态。)

npm 5 patchnote开始,文件现在自动使用file:语法进行符号链接:

npm install ./packages/subdir现在将创建一个符号链接,而不是常规安装。 file://path/to/tarball.tgz不会更改-只有目录是

是的,npm没有link

npm install ./packages/subdir现在将创建一个符号链接,而不是常规安装

有点不幸。 由于复制所有内容(包括node_modules )并且不遵守.npmignorefiles字段,因此文件部的行为从未相同。 现在,使用符号链接会更糟。

我认为file:和link:可以进一步改进,有不同的策略都有自己的PRO和CON,而Yarn应该允许人们选择一种。
例如,可以将knit RFC作为以下策略之一实施: https://github.com/yarnpkg/rfcs/blob/master/accepted/0000-yarn-knit.md

@旁观者

我认为这比在缓存中使用陈旧版本更好。

因此,您可能会相信,直到磁盘空间用完并发现您的Yarn缓存正在使用数十GB的数据来处理数百万个完全无用的文件
IMO使整个事情比以前更严重地被破坏了,因为您只有在暂时破坏了开发系统后才能发现。

大家好,您对此有何更新? 对于我们来说,这确实是一个巨大的问题,尤其是当我们同时处理依赖相同链接多重依赖关系的多个产品时。 在一天的开发中有数十亿个缓存,等等。您是否至少可以将其设置为可选,并禁用此类程序包的缓存?

@nikdojo将yarn link:协议用于依赖项,而不是file: ,它使用符号链接。 它是在0.26

或者,如果您有许多项目间依赖关系,则开始使用工作区

@mtraynham Thx作为提示,我试图在官方文档中找到任何信息abt link:协议,但似乎不存在。 现在尝试工作区。

如您所知, @ bestander btw,react-native不支持符号链接,因此,如果我们使用rn库,这仍然是一个大问题。

这从来没有解决过吗? 您必须使用linklocal(NPM软件包)链接本地软件包(这是使用本地文件系统中的软件包时yarn的标准操作方式-在Windows上使用结点或符号链接而不是缓存)。 然后,新的yarn install用缓存中的旧内容覆盖所有内容,您必须重新开始进行链接。

我们可以减少建筑宇航员的工作,而不必缓存本地软件包吗? 这个问题现在已有1.5年的历史了,每次我在another-local-package更改时,我都对运行yarn add ../<another-local-package>感到厌倦。

嗨@fungilation
我打开了另一个相关的问题:#6037

不起作用
我放入文件App.js
console.log('我们在这里'),但未输出。
然后删除所有文件,它仍然会从缓存中输出。
如何避免这种情况?

纱线确实使我在这个问题上失败了。 除此之外,它对其他所有方面都很棒。

我一直在尝试安装新版本的本地软件包以进行测试,无论做什么,我都会继续使用旧软件包。

我试过了:

  1. 清理纱线缓存( yarn cache clean package-name
  2. yarn add--force
  3. 再次删除node_modules/package-nameyarn add ing
  4. 更新本地软件包的版本号和文件名( yarn仍会安装旧版本的内容,即使它报告安装了较新的版本也是如此)
  5. 以上所有的组合

这太荒谬了,我一天的时间已经花了将近4个小时。

我们需要开发和重新安装本地软件包的能力。 我依靠yarn在.bin文件夹中安装文件,因此yarn link成为不可能。

@ Yarn开发人员:您是否可以安装本地软件包,对该本地软件包进行更改,然后通过再次安装使更改反映出来?

@gregjacobs我成功使用yarn install --force

@jonathantorley我刚刚用--force再次尝试

对于其他面临此问题的人:我以前实际使用过的一种解决方法是增加从属程序包的版本号。 有点烦人,您必须记住在每次更改时都执行此操作(除非您可以编写脚本)。

在安装本地软件包时, yarn绝对不应要求此解决方法

我在preinstall脚本中添加了yarn upgrade MY_PACKAGE_NAME ,它很好地升级到了最新的NPM版本。 (不过,我仍然需要手动更改NPM版本)。

现在看来yarn add file:PATH现在总是在yarn 1.13.0中升级新内容。
yarn install仍然没有。

@leavesster仍然不适合我。

我必须重命名tgz以便更新

尝试使用link命令: https :

yarn add file:PATH并未为我升级新内容。 此外,不尊重package.json和.npmignore中的文件。

您可以通过更改软件包的版本来使用。

如果希望yarn add file:PATH尊重package.json和.npmignore中的文件,则必须在本地软件包依赖项中运行yarn pack ,然后在其安装位置运行yarn add file:path-to-local-pacckage.tgz

尝试使用link命令: https :

yarn link不能回答相同的问题。 如果有人想要npm包(例如发布时尊重了package.json和.npmignore中的文件),那是不好的

@leavesster仍然不适合我。

我必须重命名tgz以便更新

我的软件包中没有tgz ,我使用yarn add file: PACKAGE_PAH将其添加到当前项目中。 我的包装里只有js代码。 也许tgz还是错?

也不适合我

@bestander为什么此问题已关闭? 纱线仍在缓存本地文件和tgz包。 在某些情况下,工作区不是解决方案,例如,如果一个程序包具有特定版本的deps,而另一个程序包具有与第一个相同的devDeps程序包,但是具有另一个版本,并且如果将一个程序包链接到另一个程序包,则您的项目已被破坏。

我和@gregjacobs有同样的问题。 yarn cache clean package没有帮助。 但是我发现,如果您安装yarn add path/to/package.tgz然后将archive替换为另一个,则可以安装新版本,只需更改yarn add path/to/../to/package.tgz路径,因此绝对路径是相同的,但是对于yarn不同。

我不了解其他纱线存储在哪里通过解析路径缓存的程序包,即使yarn cache list --pattern package是空的。

我认为问题出在这里https://github.com/yarnpkg/yarn/blob/eb2b565bb9b948e87b11119482ebc184a9d66141/src/resolvers/exotics/tarball-resolver.js#L58 -L63

发生了什么:

  • 从URL path/to/package.tgz生成哈希(这就是为什么path/to/package.tgzpath/to/../to/package.tgz会生成不同的哈希值的原因)
  • 使用该哈希值为程序包创建临时目录(像这样的/Users/kich/Library/Caches/Yarn/v4/.tmp/c019816ee7d10ed5e1fef4072e8cc617
  • 对于第一次运行isValidModuleDest返回false ,一切正常
  • 此目录中提取的Tarball软件包
  • 该目录中的文件安装到项目中
  • 您修改开发项目源,并使用与上一个相同的名称和位置构建/打包新的软件包tarball。
  • 然后,您尝试安装新的tarball,但是生成的哈希值与之前相同,并且第一次运行后未清除temp目录
  • 因此,这一次isValidModuleDest返回true
  • 并安装旧版本的纱包
  • 您运行yarn cache clean package ,但temp目录保持不变

@bestander我们可以在这里简单地删除临时目录https://github.com/yarnpkg/yarn/blob/master/src/config.js#L431吗?

面对相同的问题,在我处理本地文件一天后,temp文件夹下的缓存占用了10GB!

我们可以重新打开这个问题吗? 我们面临着同样的问题。 两个项目通过文件引用另一个包:。 在我们的CI / CD服务器中进行一些构建之后,缓存文件夹开始占用大量空间。

我认为链接协议是对此的最佳解决方案,file://不起作用,因为它仍然需要手动清理缓存并强制安装

https://github.com/yarnpkg/yarn/issues/2165#issuecomment -345825904

只是让你的依赖像这样

"<package>": "link:./libs/<package>"

@alxtz链接协议是否适用于tgz中的软件包?

我认为链接协议是对此的最佳解决方案,file://不起作用,因为它仍然需要手动清理缓存并强制安装

第2165章(评论)

只是让你的依赖像这样

"<package>": "link:./libs/<package>"

感谢这样做,它复制了NPM的行为,它将在node_modules符号链接file:..引用。 它似乎没有记录下来,至少在这里没有我希望找到的地方: https :

遗憾的是,不能在所有情况下都使用link

例如,我需要SDK包中的共享/同级依赖,当我进行更改时,我将链接以进行本地开发工作。
使用link ,yarn无法意识到该依赖项是共享/对等依赖项,而是使用符号链接所在的本地包,这是不正确的。

我一直在使用yarn packyarn add file:<path_to_packed_tgz>来解决这个问题。
虽然每次打包时我都可以继续重命名该程序包并将其粘贴到我的仓库中,以免产生相同的哈希值,但根据

我分叉了仓库,并在if语句中添加了一个额外的子句,以阻止yarn从其缓存中加载本地.tgz软件包(如果使用yarn add file:<path>

const dest = this.config.getTemp(crypto.hash(url));
// If specified using file: never load from cache
if (!url.match(/file:/) && (await this.config.isValidModuleDest(dest))) {
  // load from local cache
} else {
  // continue as if it's a new package
}

如果人们愿意,我可以进行公关,尽管我以前从未做过,这是一个很棘手的修复程序。
有人可以确认这种方法是否继续将本地包裹添加到yarn的缓存中吗?

@ojboj现在, yalc可能会有所帮助,直到获得正确的解决方案为止。 对我来说,在发布之前在本地测试软件包一直非常有效。

@souporserious正是我需要/想要的,非常感谢!

这么多年后,这仍然是一个疯狂的问题。

@wKich我相信! 我还没有亲自测试过它,但是看起来他们通过新的Portal协议解决了本地开发问题。

使用link:协议,我仍然收到“在同一目的地解压缩”错误,并且它引用了我的缓存目录,因此在我看来,yarn仍在缓存link:依赖项。 我引用的是同一本地软件包的2个副本,复制到使用它的每个应用程序的.deps/文件夹中- front-endrenderer ,出现以下错误。 (由于不相关的原因,无法链接到原件)

warning Pattern ["@horizon/common<strong i="11">@link</strong>:packages/front-end/.deps/@horizon/common"] is trying to unpack in the same destination "/home/garyo/.cache/yarn/v6/[email protected]/node_modules/@horizon/common" as pattern ["@horizon/common<strong i="12">@link</strong>:packages/renderer/.deps/@horizon/common"]. This could result in non-deterministic behavior, skipping.
此页面是否有帮助?
0 / 5 - 0 等级