本文翻译补充自-Yarn:AnewpackagemanagerforJavaScript。在Javascript社区中,开发者共享了数以千计的源代码,这样我们就可以节省重新发明轮子的时间,而无需重新发明库、框架、组件等。每一段源代码都可能依赖于另一段源代码,而这些依赖代码通常通过包管理器进行管理。其中,在Javascript中,最流行的是npm。上面有500万开发者,包库提供超过30万个模块。更惊人的是,每月下载量超过5亿次。Facebook团队多年来一直在使用npm客户端工具。随着源代码的显着增长,我们开始遇到一些问题,包括一致性、安全性和性能。在尝试解决我们遇到的每个问题之后,我们着手创建一组新的、更可靠的解决方案来帮助我们管理依赖关系。它称为Yarn——一种快速、可靠且更安全的npm客户端替代品。我们很高兴与Exponent、Google和Tilde合作,将Yarn作为开源项目发布。使用Yarn,开发者仍然可以访问npm包库(npmregistry),但可以更快速地安装和管理包,保持包的一致性,并提供可靠的离线环境安全性。Yarn让开发者在使用这些共享的开源代码时可以放心地更新和替换,这样开发者就可以专注于他们的任务——开发产品和功能。npmregistry收集了开发者提供的模块的archives及其对应的信息列表,译为registry,但译者认为packagelibrary更能表达其意思。Facebook管理Javascript模块的演变在使用包管理之前,Javascript开发人员通常通过CDN直接访问依赖片段的源代码。npm的第一个版本是在Nodejs出现后不久开发的,它很快成为世界上最流行的包管理工具。数以千计的新开源项目被创建,并且比以往更多的开发人员分享了他们的工作。许多像React这样的Facebook项目也依赖于npm上的代码。但是,当我们内部的成员变多了,当不同的成员和机器要安装这些依赖模块的时候,我们就开始面临一致性问题,大量的时间花在了处理依赖模块的安装上。同时由于npm会自动执行一些依赖的代码,所以会伴随安全问题。所以我们试图开发一个解决方案来处理这些问题。尝试扩展npm客户端工具(npmclient)起初,按照官方的最佳实践,我们只检查package.json,让开发者手动执行npminstall。这对开发人员来说工作正常,但在我们的持续集成环境中存在问题,这些环境处于沙盒模式并且出于安全原因未连接到外部网络。那么我们的解决方案就是检查所有的node_modules,并保存在archiverepository(registry)中。虽然它有效,但它也使一些简单的操作变得非常困难。例如,更新babel的次要版本可以产生多达800,000行的提交,从而导致完整下载,执行lint规则来检查诸如不兼容的utf8字节序列、windows行尾、非png压缩图像等内容。这些任务变得很难完成。合并node_modules更改很容易占用开发人员一整天的时间。我们的版本控制团队还指出,我们签入的node_modules目录包含过多的元数据。示例:ReactNative的package.json现在有68个依赖模块,npminstall后node_modules目录包含121,358个文件。我们做了最后的努力——强化npm客户端以供Facebook工程师使用。帮助我们安装大量代码。我们决定压缩整个node_modules目录并将其上传到内部CDN,开发人员和持续集成环境都可以在其中下载相同的存档。这允许我们从版本控制中删除数千个文件,但为了做到这一点,开发人员在提取和构建时需要内部访问权限。另外,我们在处理问题的时候也会需要用到shrinkwrap函数,它可以让我们锁定特定依赖包的版本。默认情况下不会生产shrinkwrap,所以如果工程师忘记输入命令,版本会不一致,所以我们写了一个工具来验证shrinkwrap的文件内容是否和node_modules一致。这些存档是非常大的JSONblob,并且键没有排序,因此修改它们势必会产生大量输出,然后很难审查提交。为了解决这个问题,我们需要添加一个额外的脚本来对它们进行排序。最后,使用某些版本的npm更新单个依赖包也可能会更新不相关的文件。这将导致每次更新都大于预期,并且必须成为提交node_modules或更新到CDN的整个过程的一部分,这不是开发人员希望看到的情况。我们没有开发新的客户端工具(client),而是选择尝试更全面地看待这些问题,而不是继续增强npm客户端工具。如果我们开发一个全新的客户端工具,可以彻底解决我们遇到的这些问题呢?我们伦敦办公室的SebastianMcKenzie开始挑战这个想法,我们对其潜力感到兴奋。一开始,我们开始询问业内的开发者,发现他们都面临着一系列类似的问题,尝试使用类似的解决方案,一次解决遇到的问题。很明显,社区正在共同努力解决这组问题,我们可以开发出适用于任何人的解决方案。在Exponent、Google、Tilde的工程师协助下,我们开发了Yarn,并在各种主流JS框架中测试验证了其性能,包括Facebook以外的开发团队的使用场景。今天(2016-10-11)我们很高兴与社区分享这一成就。Yarn简介Yarn是一个新的包管理工具,主要用于替代现有工作流程中的npm客户端或其他包管理工具的部分(安装、更新、删除包等指令集),并兼容现有的npm注册表。大部分功能和操作与现有流程相同,更快、更安全、更可靠。任何包管理工具的主要功能都是将模块包——一段特定用途的代码——从全球可用的包注册中心(registry)安装到开发者的本地环境中。每个包可能依赖于其他包。一个典型的项目可能有几十个、几百个甚至几千个依赖模块。这些依赖模块有一个版本号,并根据语义版本控制规范(semver)安装或更新。语义版本规范了版本号的含义和相关符号的规则。这些规则可以让我们知道这个版本是否兼容之前的版本,是属于增加新功能,还是只是修复bug,然后根据这些规则来确认是否可以Update或者更新到什么版本号。然而,语义版本控制(semver)依赖于包开发人员不要犯任何错误-如果依赖包的版本未锁定,则更有可能安装新的错误或错误的修复程序。在Node生态中构建,依赖的模块会放在项目下的node_modules目录下。但是随着合并重复模块的情况,这个文件结构可能和真实的目录结构不一样译者补充:npm显示的依赖层次结构和实际的目录结构不一样。npm客户端工具将依赖模块安装到node_modules目录中,而不依赖于模块结构(不确定)。意味着它只会按顺序安装模块,node_modules目录中的结构可能因人而异。这些差异可能是最“我能跑”的情况,通常需要很长时间才能找到问题所在。Yarn通过lockfiles(yarn.lock)锁定机制和一套安装逻辑解决了这些关于版本和不确定性的问题,使其具有可靠性和确定性。这些锁文件将已安装的依赖项锁定到特定版本,确保每台机器上安装的结果node_modules是一致的。锁文件使用精确格式化和排序的键(keys)来确保修改动作最小化并且在审计时相对简单。整个安装过程分为以下三个步骤:识别:Yarn通过向包仓库(registry)发送请求开始解析依赖的包模块,然后逐层递归检查每个模块的依赖关系。检索:接下来,Yarn检查全局缓存目录以查看是否已下载任何所需的包。如果没有,Yarn就开始下载模块的压缩包(tarball),存放在全局缓存的目录下,这样就意味着我们可以离线工作了,同一个模块不需要下载两次。也可以将依赖模块以压缩文件的形式加入版本控制,实现完全离线安装。链接:最后,Yarn将需要的文件从全局缓存中复制到本地的node_modules中,完成这个过程。通过明确拆分这些步骤并确保一致的结果,Yarn能够并行处理每个操作,从而使整个安装过程更快。在某些Facebook项目上,Yarn将整个安装过程从几分钟简化为几秒钟。Yarn还提供了互斥机制,保证多条执行的指令不会相互干扰。Yarn会严格把控整个安装过程,帮你把控安装过程。包检查信息将存储在锁文件(yarn.lock)中,以确保每次安装相同的包模块。特性除了确保更快、更可靠的安装过程外,Yarn还支持其他特性,使我们能够更轻松地管理依赖项并简化工作流程。兼容npm和bower,也支持不同的包库(registry)严格限制安装包的Licenses和输出相关信息提供API帮助构建工具获取输出部分工具的信息更多信息参考本Issue)精简有意义且漂亮的命令输出信息在正式环境下使用Yarn在Facebook,我们在正式产品中使用了Yarn,并且效果很好。使许多项目更容易管理依赖项。我们允许工程师即使在移动中也能快速离线构建,从而加速整个工作流程。你可以看到Yarn和npm安装ReactNative的时间差距。有关详细信息,您可以在此处查看。最快的入门方法是执行$npminstall-gyarn$yarn#或参考官方文档:https://yarnpkg.com/en/docs/installyarn将工作流程中的npm替换为相同或相似的命令.npminstall->yarn这个命令不需要任何参数,yarn会读取package.json然后从npmregistry中提取包并安装到node_modules。使用npminstall等。npminstall--save
