NPM 7:这才算是真正的更新

2020 年 12 月 6 日 InfoQ

作者 | Fernando Doglio

译者 | 王强

策划 | 李俊辰

备受我们信赖的 NPM 上一次迎来重大更新后已经过了一段时间了。终于,在 Node 的最新版本(版本 15)中,我们等到了 NPM 的版本 7。这一版本对其内部架构进行了重大改进,并提供了一些非常有趣的新特性。

在本文中,我会介绍两个引起我注意并激发我的想象力的新特性。第一个特性会改变我们处理所有项目依赖项的方式,而第二个特性会优化一个之前必须手动完成的流程。

当然,我指的就是 工作区(workspaces) 和自动安装 对等依赖项(peer dependencies) 的能力。是不是来兴趣了?反正我心情很激动!

工作区

我最近分享了一篇文章,其中介绍了两种 NPM 客户端,它们都想要解决官方客户端当前实现中的一个主要问题:npm_modules 文件夹已经成为了一个磁盘空间黑洞。

https://blog.bitsrc.io/npm-clients-that-are-better-than-the-original-cd54ed0f5fe7

这两种选项都有自己的独特解决方案,但总体来说它们都会将所有模块保存在一个共享文件夹中,让各个项目之间能够更容易共享软件包。而随着 NPM 最新版本的发布和 Arborist 的引入(一个新项目,包含了负责遍历和分析 npm_modules 文件夹内模块目录树的逻辑),我们看到了官方对这种方法的回应:工作区

请注意,这并不是一个全新的概念,其他包管理器(例如 Yarn 和 pnpm)已经有了自己的工作区实现。因此,你可以说这只是官方的一个工作区版本而已。

这是什么?

你可以将它视为在预定义和通用上下文内的项目之间共享软件包的一种方式。这并不是说软件包是完全通用的,或者所有内容都要放进同一个下载位置。这个方案确实可以解决一遍又一遍地复制模块的麻烦,还能让你控制我们的模块要共享给哪些项目。

创建工作区后,你就可以明确地告诉 NPM,你的程序包将存放在何处。并且由于新版客户端可以感知工作区,因此它会正确安装依赖项,而不会复制那些通用的依赖。

使用其他包管理器时这个功能也非常有用。例如,可以在单个 NPM 工作区中管理的多个项目之间共享一个 Bit 组件。修改共享组件时,可以用工作区从多个项目中获得即时反馈(查看是否有哪里出现了中断)。

它向后兼容吗?

可惜不行!工作区不是区区配置更改那么简单,它还要求你用新的方式来构造项目。因此向后兼容是做不到的,你不能运行一条 npm 命令就一次性规范化 10 个项目。但是,你可以在重新考虑所有这些项目的结构并正确更改配置之后,将这些项目的依赖项重新安装到一个位置里,这样就可以对所有内容执行重复数据删除操作了。在我看来,这确实是一项巨大的进步!

这个新特性会强制你考虑工作区的实际结构,以及不同项目之间的相互关系,这还会帮助你改善项目的内部组织架构。

考虑下面的例子

有很多介绍工作区的文章,但它们提供的示例在我看来没什么用,所以这里我举一个例子,希望能对 Node.js 开发人员更有帮助。

考虑以下文件夹结构:

基本上,我们将要处理一组 REST API,其中每个 API 的实际代码都会放在“apis”工作区内,而通用代码和共享包将在“core”工作区。

我们如何做到这一点呢?了解了它的工作原理后,配置过程实际上非常简单。这里的重点是你需要在声明工作区的根级别(在 REST-APIS 文件夹内)定义一个 package.json 文件。准备好之后,你要做的就是在每个项目中都创建一个 package.json,并在其中声明其所需的依赖项。

然后,你从根文件夹运行 npm install,让 NPM 完成剩余的工作。下面是根文件夹中的 package.json 文件:

你要做的只有这些,你当然可以定义其他属性,但是对于这个新特性来说,“workspaces”键就足够了。在其中,你可以定义(如示例所示)一个路径列表(还有包含的通配符格式),这些路径引用了工作区所在的文件夹。

在这些文件夹中,你只需声明自己的 package.json 文件,而每个文件都声明它自己的依赖项。

你可以看到,各个 API 文件夹的 JSON 文件实际上区别只有名称和依赖项。core 文件夹也是如此,我们在其中将 Express 声明为其主要共享依赖项:

现在,我们可以从根文件夹运行 npm install,你觉得会发生什么呢?它将在一个通用的 node_modules 文件夹中安装所有这些工作区所需的所有内容。因此,重复的依赖项不会占用多份空间。

有了这些命令和文件夹结构后,你在根目录级别的 node_modules 文件夹中安装了所有三个模块(及其必需的依赖项)。但是,其层次结构内的任何文件都能访问所有这三个文件。

看看 apis/api2/ 文件夹中的这个文件:
const express = require('express')const app = express()const port = 3000const winston = require("winston")const flat = require("flat")app.get('/', (req, res) => {  res.send('Hello World!')})app.listen(port, () => {  console.log(`Example API (#2) listening at http://localhost:${port}`)})

它用上了所有三个依赖项,而在以前它本来是找不到它们的,这太棒了!

你需要工作区吗?

好吧,如果你正在处理的是单个项目,或者是一些互不相关的项目,那么工作区可能对你来说并没什么用途。它们的需求可能会随时改变,结果让工作区带来的好处烟消云散。

但是,如果你在参与团队中多个相关项目(也许你正在设计一个基于微服务的架构),那么工作区可能会是你非常需要的功能。如果你有一个包含 100 个微服务的架构,所有微服务都依赖同一组模块,那么你可以想想这个新特性会为你节省多少磁盘空间。这个特性的用武之地就是类似这样的场景!

PeerDependencies 自动安装

我今天要介绍的第二大特性就是它。之前我们必须手动安装对等依赖项,以后就用不着了。但是首先,到底什么是对等依赖项呢?

如果你不太熟悉这个术语(以前我也不熟),这里就简单介绍一下:对等依赖项和普通的依赖项几乎没什么区别,它们并没有定义一个严格的要求,而是声明:

  • 你的软件包与另一个模块的特定版本兼容。

  • 如果该模块已经安装并且是正确的版本,则不要执行任何操作。

  • 如果找不到该模块或版本存在冲突,则向开发人员显示一条消息,警告他们这一事实,此外什么也不做。

理论上讲这都没什么问题,但如果你要自动安装这些依赖项,那么当你添加两个具有相同依赖项但版本不同的软件包时,两个版本就会同时安装(其中一个位于常规的 node_modules 文件夹中,另一个作为需要它的包的子依赖项)。

这可能会导致不兼容的问题,想象一下,我们把依赖模块 B 的模块 A(模块 A 又依赖 React@15)添加到依赖 React@16 的项目中。因为 A 需要版本 15,所以它也将会把版本 15 添加为依赖项,最后依赖项树会变成这个样子:
- React@15- A- B  +- React@16

也就是说你得安装两个不同版本的 React,仅仅因为你需要模块 A。但现在我们有了 Arborist,它可以分析整个树并考虑对等依赖,如果出现冲突它就会显示对应的错误信息,并且中止流程。本质上来说,NPM 现在替开发人员完成了这部分工作,并帮助后者决定是否安装这一对等依赖项。考虑到依赖管理的工作也许会浪费一整天的时间,这绝对是一个非常有用的功能。

以前你遇到过这样的坑吗?这个新特性是不是让你非常激动?

NPM 版本 7 已发布,其中包含一些新特性和改进。这两项特性尤其吸引了我的注意,我很快就去尝试它们了。当处理具有多个共享依赖项的大型组合项目时,工作区可以从根本上改善开发人员的体验。

对等依赖管理的改进肯定会为使用基于 NPM 的工具的 React 开发人员带来好处,因为这一特性在这个生态系统中是非常常用的。

你喜欢这些特性吗?还有哪些更新你觉得是很有用的?请在下方留言并分享你的看法。

延伸阅读
https://blog.bitsrc.io/npm-7-this-is-what-i-call-an-update-de17a34ab787

InfoQ 写作平台欢迎所有热爱技术、热爱创作、热爱分享的内容创作者入驻!

还有更多超值活动等你来!

扫描下方二维码

填写申请,成为作者

开启你的创作之路吧~

点个在看少个 bug 👇

登录查看更多
0

相关内容

JSON( Java Script Object Notation)是一种轻量级的资料交换语言,以文字为基础,且易于让人阅读。尽管 JSON 是在 JavaScript 的一個子集,但 JSON 是独立于语言的文本格式,並且采用了类似于 C 语言家族的一些习惯。
【2021新书】编码艺术,Coding Art,284页pdf
专知会员服务
73+阅读 · 2021年1月10日
【2020新书】操作反模式: DevOps解决方案, 322页pdf
专知会员服务
30+阅读 · 2020年11月8日
【2020新书】C语言编程傻瓜式入门,第二版,464页pdf
专知会员服务
60+阅读 · 2020年10月15日
【2020干货书】Python3基础导论介绍,98页pdf
专知会员服务
99+阅读 · 2020年10月11日
【2020新书】C++20快速语法参考,第4版,209页pdf
专知会员服务
71+阅读 · 2020年8月5日
【2020新书】实战R语言4,323页pdf
专知会员服务
98+阅读 · 2020年7月1日
Python导论,476页pdf,现代Python计算
专知会员服务
254+阅读 · 2020年5月17日
【Google-CMU】元伪标签的元学习,Meta Pseudo Labels
专知会员服务
31+阅读 · 2020年3月30日
机器学习速查手册,135页pdf
专知会员服务
336+阅读 · 2020年3月15日
OpenDrop: 一个开源AirDrop实现
Python程序员
6+阅读 · 2019年9月1日
用Now轻松部署无服务器Node应用程序
前端之巅
16+阅读 · 2019年6月19日
这么多年,终于知道为啥右指针不能往回走了
九章算法
5+阅读 · 2019年4月15日
抖音爬虫
专知
3+阅读 · 2019年2月11日
都说 AllenNLP 好用,我们跑一遍看看究竟多好用
Python为啥这么牛?
Python程序员
3+阅读 · 2018年3月30日
如何运用Python建一个聊天机器人?
七月在线实验室
17+阅读 · 2018年1月23日
Arxiv
3+阅读 · 2019年3月1日
Arxiv
7+阅读 · 2018年6月19日
Arxiv
3+阅读 · 2018年4月3日
Arxiv
6+阅读 · 2018年2月26日
Arxiv
4+阅读 · 2017年7月25日
VIP会员
相关VIP内容
【2021新书】编码艺术,Coding Art,284页pdf
专知会员服务
73+阅读 · 2021年1月10日
【2020新书】操作反模式: DevOps解决方案, 322页pdf
专知会员服务
30+阅读 · 2020年11月8日
【2020新书】C语言编程傻瓜式入门,第二版,464页pdf
专知会员服务
60+阅读 · 2020年10月15日
【2020干货书】Python3基础导论介绍,98页pdf
专知会员服务
99+阅读 · 2020年10月11日
【2020新书】C++20快速语法参考,第4版,209页pdf
专知会员服务
71+阅读 · 2020年8月5日
【2020新书】实战R语言4,323页pdf
专知会员服务
98+阅读 · 2020年7月1日
Python导论,476页pdf,现代Python计算
专知会员服务
254+阅读 · 2020年5月17日
【Google-CMU】元伪标签的元学习,Meta Pseudo Labels
专知会员服务
31+阅读 · 2020年3月30日
机器学习速查手册,135页pdf
专知会员服务
336+阅读 · 2020年3月15日
相关资讯
OpenDrop: 一个开源AirDrop实现
Python程序员
6+阅读 · 2019年9月1日
用Now轻松部署无服务器Node应用程序
前端之巅
16+阅读 · 2019年6月19日
这么多年,终于知道为啥右指针不能往回走了
九章算法
5+阅读 · 2019年4月15日
抖音爬虫
专知
3+阅读 · 2019年2月11日
都说 AllenNLP 好用,我们跑一遍看看究竟多好用
Python为啥这么牛?
Python程序员
3+阅读 · 2018年3月30日
如何运用Python建一个聊天机器人?
七月在线实验室
17+阅读 · 2018年1月23日
相关论文
Top
微信扫码咨询专知VIP会员