依赖管理人员不管理您的依赖项

2021-05-06 08:19:20

倾听或观看这一集。您还可以通过Apple Podcasts,Pocket Casts等,或者其他。

我答应写Tech,让我们开始建立我们的JavaScript基础设施肌肉。在接下来的几个博客帖子中,我将介绍依赖管理的介绍主题,jest,可操作的技巧的故事,使您的基础架构更好,以及对JavaScript工具的未来的预测。我们将慢慢发展我们的共享理解,以便我们可以更深入地讨论JavaScript基础架构:

JavaScript依赖管理人员(如NPM,YARN或PNPM)对JavaScript Ecosystem的演变产生了巨大影响。它们可以在前端空间中持续搜索新的解决方案。然而,他们的易用性和包装的高模块化具有许多缺点。现有的JavaScript依赖关系管理器实际上不是在管理依赖项时不太擅长。相反,它们主要是下载和提取文物的便捷工具,其中包含一些任务跑步者功能洒在一起。

本文无法解决包管理人员的根本问题。相反,我希望能够提供明确的指南,以避免硬盘驱动器1上的黑洞,并控制您的第三方依赖项。

许多工具将分析,解析,处理或在Node_Modules文件夹中的文件中执行某些内容。添加许多大型依赖性往往会减慢安装时间2,并使所有业务在全球范围内慢,即使个人仅在项目中使用工具子集。应用以下方法将第三方依赖性的大小减少了幅度的反应本地码库中的第三方依赖项,通过相等的因素改进了安装时间,并持续了胜利。

如果我们夺得我们的依赖关系,它会看起来像什么?正如上一篇关于开发人员经验原则的帖子中所讨论的:

[A]示例正在减少外部依赖关系或更仔细地选择它们。是的,第三方依赖无疑可以帮助我们最初移动,但使用它们意味着我们对我们的堆栈失去了控制。我们通过删除依赖项或积极维护它们来获得选项值和控制。

本指南主要集中在纱线1上,但许多建议将同样适用于其他套餐管理人员。要记住的一件事是一些包裹管理人员将使用符号链接,硬链接或其他棘手的棘手和不透明的方式来避免直接安装依赖项。我已经尝试过其中一些,并参与了另一个人的创造。我也看到了千分之一的死亡,与这些解决方案的规模。让我们认为它是理所当然的文件系统上的物化文件是唯一的方法,就像第一方代码存储在文件系统和版本控制中。好的?让我们潜入!

首先,我们需要了解Node_Modules文件夹中的类型的包。我们将使用各种方法分析我们的依赖项。我没有找到一个良好的一体化解决方案来分析一个node_modules文件夹,所以我们将使用四个不同的解决方案:

磁盘库存x和du -sh ./node_modules/* | sort -nr | grep' \ dm。*' 3分析node_modules中依赖关系的大小。

纱线为什么< packageName&gt ;:此命令解释为什么特定包在依赖树中最终结束。它列出了依赖于它的所有其他软件包以及它们依赖的版本。

它看起来很明显,但很多项目都带来了很多死亡。添加依赖项比删除它们要容易得多。您可能有多个依赖关系,即使您没有使用它们,也可能保持升级。我建议审核Package.json文件中列出的所有现有依赖项,以查看要删除的所有依赖项。此分析通常是手动过程,因为静态分析工具可能会错过一些动态用例。我建议使用RIPGREP或在编辑器中使用搜索功能。假设您想检查您是否已从时刻迁移到Date-fns,因此您可以删除时刻。您可以为终端中的JavaScript需要或导入/导出语句运行这样的内容:

如果上面没有显示任何结果,我通常通过RG&#39检查确切的字符串;矩'并扫描我是否错过了一些明显的东西。考虑一些用于Babel,Eslint或Jest等工具的配置文件可以直接拍摄模块名称。如果删除其中一个依赖项,则可能会在项目中打破一些东西。

确认包不在使用后,将其从package.json删除并运行纱线。在依赖项和devdependencies中对每个包重复此过程。您可以使用Depcheck等工具以更具自动化的方式通过NPX Depcheck执行此操作,但相同的警告适用。

你有没有经历过“升级悬崖”?这是依赖的版本到目前为止,升级需要大量努力并减慢整个工程团队。我发现升级每个人的持续责任随着时间的推移和工程组织摊销这一成本。通过这种方法,人们平均会稍微慢一点,但它们永远不会面临卡住,因为它太难克服了破坏的变化。

保持所有依赖项最新将使远离旧封装并通过本指南的后续步骤更轻松地远离旧版包。您可以使用纱线过时和纱线升级互动,以检查并将依赖项升级到最新版本。 5但是,注意突破变化和错误 - 您必须增加自动化测试,以增加您的信心,您可以靠近最新版本的依赖项。为了在最新版本的情况下,没有理解变化并导致生产中的问题,没有什么比升级包裹更糟糕了。

例如,我曾经通过构建一个系统以将新生产捆绑包与以前的版本进行比较所有React Native的产品代码(数百万的代码行数)来跟踪Babel的版本。它允许我充满自信地发货更新,在某些情况下,我设法将新版本的Babel部署到八个小时内的十亿用户。

某些JavaScript包管理器中使用的算法不连续优化依赖关系图。您可能有一个锁定文件,该文件负责安装同一包的多个版本,即使只有单个版本也是同样满足预期的语义版本(SEMV)范围。纱线重复数据删除可以用于在这些情况下优化锁定文件,并且我通常建议每次添加,更新或删除包时运行它:NPX纱线 - 重复数据删除yarn.lock。您还可以为您的持续积分(CI)管道添加验证步骤,如纱线重复数据删除yarn.lock --list --fail。

对此问题产生最大问题的工具是Monorepo Toolchains,如Babel或Jest。我正在研究我们有四个版本的Babel的Parser,两个版本的几乎所有Babel插件的项目,以及三个版本的各种Jest软件包。纱 - 重复扣款在某种程度上工作,但没有好方法可以更新所有这些包以使用最新版本。我试过了:

使用纱线分辨率来覆盖语​​义版本控制约束,并将所有包锁定到最新版本。

这些都没有良好的工作,并且经常让事情变得更糟。我发现只有一种可靠的方法来确保每个Babel升级只安装了一个可靠的每个Babel包的一个版本:在每个Babel升级中,从youbel /开始手动删除yarn.lock文件的所有条目。从其依赖关系图的子集开始。您将结束每个Babel包的单个版本 - 最新版本。 6.

另一个建议是探索您依赖的软件包的范围,并发送提取请求以升级其依赖关系或更改固定版本以接受SEMVER范围,以便下游项目可以从更多的重复中受益。

在一个大型项目上,您可能最终有多个包服务相同的目的,有时您可能最终有多个主要版本的相同包装。我发现在更大的球队上,有人可能会掌握大依赖性并恰好使用它一次,膨胀生产捆绑包,虽然已经广泛使用了类似和更小的包装。您可以使用严格的风格指南,文档和代码审查来避免此问题。仍然,即使在最佳环境中,也通过直接依赖性包括类似的及物依赖性进一步加剧。例如,两个直接依赖项可以包括与Parse命令行选项不同的包,该选项与项目使用的命令行选项不同。分析您的node_modules中已有的包并对齐每个目的,它可能有意义。

在某些情况下,包裹不明,或者它们太臃肿或移动得太慢。阻止您公司的产品功能并没有意义,因为您正在等待第三方开源维护者,以向您使用的包裹发布。我注意到人们犹豫了叉子包装。我建议在Github上的Fork按钮更自由,并发布您的自定义版本的包。叉子不必长期生活。它们可以为单一的目的服务,例如拉向某些东西进行修复,可以稍后删除。是的,可以添加维护负担,但它还可以控制您在项目中运行的更多代码。 7.

我们可以使用纱线分辨率将现有包与自定义叉子交换。在您的package.json中:

我之前用一个流行的包裹做到了一揽子计划,只需大约2个MIB即可填写20米的东西。我们曾经有三个这个包装。对齐在单个版本上并转到叉子减少了从60 MIB占用的空间到2个MIB。

通常,在分叉包后,我会向原始包裹发送拉请求。例如,对评论棱镜的这种改进将包装的尺寸从10.7 MIB降低到0.03 miB。大多数时候,我打算留下叉子。有时,更改可能与包所有者有所不同,我将保留叉子版本,这很好。

很高兴减少依赖性的数量和大小,但最好长期维持胜利。我建议在yarn.lock或package.json文件更改时使用项目中的du-sh node_modules等内容来设置分析node_modules的大小。使CI步骤在每个拉拉请求上运行,如果与主设备相比尺寸的增加,请提醒某人查看。

虽然您可以无疑可以构建自动化以防止人员检查新模块,但我发现最好的结果可以通过与人交谈并在与同一代码库一起使用的每个人身上建立共同的责任感来实现。毕竟,很难知道是否有一个有充分的理由添加依赖性,而且你不想最终成为一名守门人。相反,指出,添加大依赖性将使每个人或指向您正在使用的类似包的人来说,这是有用的。大多数时候,事实证明,人们只是不知道更好,他们将欣赏帮助。

例如,我最近遇到了某人添加了几个包的案例,该软件包将增加了node_modules文件夹的大小。简单地指出,解释为什么它并不理想,并给予它们两种或三种解决他们的问题的方法有助于避免在该状态下运送拉出请求。以这种方式思考:如果有人增加了一百行代码,我们会在代码审查期间通过很多审查将该代码放在很大程度上。如果某人将单行添加到Package.json文件中将100 MIB的代码拉到一个项目中,膨胀生产捆绑,并减慢工具,我们通常只是通过扫盲,因为我们没有看到对拉的影响请求本身。 8您可以通过将第三方依赖性直接检查为版本控制来避免此问题。

yarn有一个autoclan命令,可以自动删除与排除列表匹配的文件。您可以使用它来删除与您的项目无关的任何内容,例如示例,测试,标记文件和其他。您可以通过运行yarn autoclan --init并将结果的.yarnclean文件进行启用并将其调入版本控制。不幸的是,这个命令在安装依赖关系而不是安装期间后运行,这意味着纱线的每次调用都会慢,有时甚至多秒钟。这是一个很好的功能,但我只推荐它为检查Node_Modules进入版本控制的项目。

上述建议的程度将适用于您的项目和团队。至少,您将获得更多对项目的控制,并降低第三方依赖的不受控制的增长。最多,您将防止工作流程在性能中回归,并且始终保持精益和快速。接下来:重新思考JavaScript基础架构。

您所在的网站现在在其node_modules文件夹中有超过40,000个文件,重量超过570 mib😬↩

在我的经验中,随着依赖图的复杂性增加,安装时间以上面的线性速率增长。即使套餐更大,较少的包裹将导致更快的安装时间。 ↩

prisma很棒,但也许它不应该在三个文件夹中复制相同的大型二进制文件? ↩

您可以在GitHub上使用indedabot,但从我的经验中,人们花费更少的时间验证更改,而不是手动进行。 ↩ 当然,否则您有需要特定版本的依赖项,在这种情况下,升级这些依赖项首先或使用纱线分辨率覆盖约束是有意义的。 ↩ 关于这篇文章的推文,或与您的朋友分享。 与社区讨论或给我发电子邮件。 谢谢你的阅读,祝你有美好的一天!