3

前情提要

今天 npm 圈子鸡犬不宁,原因是一个不过 11 行的工具函数 left-pad 被作者从 npm 上撤下,所有直接和间接依赖它的包就这么齐刷刷挂了,包括 babel 和 react-native 这样每天安装数万的热门项目。

而 Azer 删除他所有的 npm 包又是另一个故事:Azer 写了一个工具叫 kik 发布在 npm 上,这天有个同名的公司律师找上门要求他删掉,Azer 不从,这律师就找上 npm,npm 把包的管理权限转给了这家公司——当然,Azer 就怒了,从 npm 上解放了所有自己发布的包。

是的,就是这样 ╮(╯_╰)╭

small module 的错?

babel 很快就发布了修正。然而抛开这两个故事不去讨论,鉴于现在各种组件的依赖树之深,这件事暴露出的问题(一直都在,只是没有这么痛地领悟过)已经让人无法安心地 npm install 了——更多的项目都不可能像 babel 这样活跃,第一时间发布修正。

各种担忧、质疑指向 npm 社区一直提倡和推动的 small module 和 semver 理念。这个方向错了么?也有人怪罪 npm unpublish 是万恶之源,这么想就有点表面了。

得救之道,就在其中

Isaacs 在 left-pad 的 Issue 里回复说“不要依赖于其他人”,附了关于 bundledDependencies 的链接,并且最后再次强调 small module 依然是合理的哲学。

这篇回复其实比较含糊,甚至看上去有点矛盾。Rollup 作者讲得更明白些,解决之道就一句话:

无论你是否面向浏览器,将所有依赖都打包进最终的发布代码。

这么做将使你的项目仅仅在打包的时候依赖那些 dependencies,一旦发布完成,就不再需要依赖树上的所有作者们保持他们的任何承诺。这就是 Isaacs 所说:不要依赖于其他

事实上 Atom 也在受影响之列,但除了 Atom 的开发者之外,用户是没有感觉的——就这么简单。

此原则除了可以解决这次的 left-pad 灾难之外,还有成堆的好处,哪怕每一项都不是杀手级的,这么堆起来也还是很可观的:

  • 节省 npm install 的时间。依次去下载整个依赖树是很耗时间的,而且还附带下载了更多的 README、package.json 之类。这些磁盘空间也可以省下来了。

  • 启动更快。你知道 Nodejs 的 require() 执行慢成狗么?

  • 你的包更加可靠。依赖树中的 bug 不能靠用户自行 npm update 来修复了,你得自己重新打包发版本,但是再也不用担心出 left-pad 这种幺蛾子,哪个更重要?

  • 也更加安全。理论上,npm 托管的那些代码随时可能被注入恶意代码,比如现在 Azer 撤下来的包,不少已经被其他人重新发布上去,可是天知道都是谁放了些什么代码……用户只不过 npm install 了一下。

  • 解除了用户为你的代码打包的负担。 负担其实并不是我们担心的,只是如果用户喜欢用 webpack 打包而我们的代码是 browserify 圈的呢?PouchDB 就碰上了这种情况

新的习惯

养成新的习惯,开始为你发布的代码做预打包吧。bundledDependencies 已经等候多时了。


Amio
1.3k 声望63 粉丝

The way we code the web will determine the way we live online. So we need to bake our values into our code. -- Brewster Kahle