【译文】pnpm 的严格性有助于避免愚蠢的错误

287 阅读4分钟

原链接 :www.kochan.io/nodejs/pnpm…

pnpm是node.js的一个包管理工具。早前我写过一篇《为什么应该用pnpm》.在这篇文章中,我想说明如何使用pnpm来避免一些愚蠢错误。

当使用npm时,你可以使用那些你没有在项目的package.json中引用到的package.这是可能的,因为npm创建了一个打平所有依赖的node_modules文件夹.

让我们举个例子解释:

  • 创建一个空项目:mkdir project && npm init -y
  • 执行npm install express --save
  • cd到node_modules文件夹
  • 执行ls -1

你将获得一个类似下面的输出:

accepts
array-flatten
content-disposition
content-type
cookie
cookie-signature
debug
depd
destroy
ee-first
encodeurl
escape-html
etag
express
finalhandler
forwarded
fresh
http-errors
inherits
ipaddr.js
media-typer
merge-descriptors
methods
mime
mime-db
mime-types
ms
negotiator
on-finished
parseurl
path-to-regexp
proxy-addr
qs
range-parser
send
serve-static
setprototypeof
statuses
type-is
unpipe
utils-merge
vary

可以看到,即使你只是安装了express这个包,在node_modules中,很多包都是能用的。Node.js不在乎你的package.json文件,你可以使用node_moduls根目录下所有的包。你不需要显式地去安装,就能使用上面所有的包。

让我们假设一下,你的项目需要debug(包).你开始使用它,但忘记把它加入package.json.项目将正常运行。你提交了你的修改并且发布到了生产环境。甚至在生产环境项目都是正常运行的。然而,经过了几周或几个月,可能会发生以下一两件事:

  1. debug的一个新的主要版本,带着新的API发布了。你的之前的代码是基于debug@1写的,现在需要进行一些更新才能跟debug@2一起用。目前来说express使用debug@1是安全的,因为debug@1被安装在node_modules根目录下。然而,express可以随时更新它自己的依赖,修复debug上所有的用法,然后发布一个新的patch.(是patch,因为express不会有任何breaking change)。下一次你执行npm install,express会将debug@2安装在node_modules根目录下。此时,项目就会出问题,即使没有改任何代码。

  2. 另一种可能是express停止使用debug(包)。它可以从依赖中移除debug并且发布新的版本。然后当你更新express后,你的代码就会有问题,因为debug这个包将不再存在于node_modules下了.

现在,想象一下你的项目不是一个web app,而是一个提供给很多人用的包。如果你没有在package.json中引入代码中用的包,你的包就是一个定时炸弹。还记得left-pad吗?可以想象,因为忘记依赖中的一个包,而在未来发生这种类似的灾难。

pnpm时如何帮助避免这些类型的的bug呢?

跟npm不一样的是,pnpm不会尝试去移动node_modules根目录下的任何东西。如果你移除了前面例子中npm创建的node_modules文件夹,然后执行pnpm install expressls -1后你会看到node_modules文件夹下只能打印出一个符号链接(symlink):express而不是debug!

在下一次执行中,你的app将马上报错,因为它找不到debug.这是理所应当的。想要修复这个问题,你仅需执行pnpm install debug(pnpm默认保存包到package.json,即使没有使用--save参数),此时debug会添加到package.json的依赖中,可以确定它将始终安装在node_modules下,项目将如预期那样执行。

pnpm有很多open状态的issue,因为一些包/工具不管用。这些issue大多会在包or工具的package.json中缺失依赖的情况下发生。一些开发者甚至认为这没关系,因为在npm或者yarn管理下,package.json中缺失依赖也是行得通的。其实这是不ok的,可能今天还是正常的,明天就不行了。

你可能不使用pnpm.但是,请发布有效的包。如果你不用pnpm,可以在发布到registry之前,用一些像dependency-check的工具去校验、检查你的package,

npm的global-style安装

在这篇文章发布一个月后,我发现使用npm同样也可以避免这类bug。当然这不是默认行为,npm可以安装node_modules为一个不同的结构,即“只有直接依赖能够出现在node_modules中,这些直接依赖的依赖会被平铺列在他们自己的node_modules文件夹下”。

想要达到这一点,可以执行npm install xxx -global-style,或者通过下面的配置改变:npm c set global-style true

你想尝试pnpm吗?

通过以下命令即可安装pnpm:npm install -g pnpm. 使用pnpm安装:pnpm i foo.