
原文在知乎,欢迎交(tu)流(cao)
我终于知道为什么 npm install 总是动不动就下载 300 Mb 的东西了,Node.js 社区强调的 DRY 文化使得
node_modules臃肿不堪,因为有的库引用了 is-object,有的库引用了 isobject,还有的库引用了 isObject,每个包看起来很 DRY,但是合起来就 wet 得不行了,呵呵。
我一直以为 npm 里下载量较大的 package 是 React 这样不错的包。
今天我才知道我错了。
目前 React 每周下载量是 240 万次。
然而下面我要说的几个包的下载量全都大于 React !
is-odd,每周下载 300 万次
源代码如下:
'use strict'; var isNumber = require('is-number'); module.exports = function isOdd(i) { if (!isNumber(i)) { throw new TypeError('is-odd expects a number.'); } if (Number(i) !== Math.floor(i)) { throw new RangeError('is-odd expects an integer.'); } return !!(~~i & 1); }; 你没有看错,五行核心代码,还依赖了一个 is-number 库。
这个 is-number 库更厉害,每周下载 1000 万次
源代码如下:
'use strict'; module.exports = function isNumber(num) { var number = +num; if ((number - number) !== 0) { // Discard Infinity and NaN return false; } if (number === num) { return true; } if (typeof num === 'string') { // String parsed, both a non-empty whitespace string and an empty string // will have been coerced to 0\. If 0 trim the string and see if its empty. if (number === 0 && num.trim() === '') { return false; } return true; } return false; }; 后来我发现这两个库的作者是同一个人(该作者水平很高),这个人还写了另外几个库:
需要指出的是
这件事对我的启发:
我终于知道为什么 npm install 总是动不动就下载 300 Mb 的东西了,Node.js 社区强调的 DRY 文化使得 node_modules 臃肿不堪,因为有的库引用了 is-object,有的库引用了 isobject,还有的库引用了 isObject,每个包看起来很 DRY,但是合起来就 wet 得不行了,呵呵。
Node 社区跟我想得不太一样,说不上好也说不上坏,反正不是很适合我。
以下是扯淡。
我是看到 Medium 上的一篇《混乱又危险的 Node.js 生态》才知道这些的,这篇文章里的一个评论我很赞同:

如果你不能在十秒钟内写出一个判断奇数的函数,要么你是一个糟糕的打字员,要么你就不应该当程序员!
还有一些颇为搞笑的评论:




看到那个既不是奇数也不是偶数的那个库 我躲在被窝里笑出了猪声 hhhhhhhhhh |
2 FrankFang128 OP @Dawnki 讽刺 JS 程序员写代码不带脑子哈哈,说实话我从写代码第一天就是用 n % 2 === 1 来判断奇数,到底是什么人才会想要去引用一个库……是因为不会 % 运算符吗…… |
3 3IOhG7M0knRu5UlC 2018-04-19 01:42:11 +08:00 via Android 有找包的时间早写了,我这俩月上业务一些 nodejs 就连续碰到三次因为基础库的基础库的基础库更新不兼容故障,就是几行代码,结果自下而上崩塌了。我现在很喜欢用 docker 包装 go |
4 3IOhG7M0knRu5UlC 2018-04-19 01:45:24 +08:00 via Android 一个 4000 + star 依赖了一个 20 + star 的库,那个库粗制滥造也没有测试说改就改 也不发大版本 |
5 FrankFang128 OP @GooMS nodejs 找包确实很费时间,经常遇到名字类似功能类似的,大部分时候完全在浪费时间。 |
6 FrankFang128 OP @GooMS 听起来很符合 Node.js 社区的风格 |
7 billlee 2018-04-19 01:49:24 +08:00 is-primitive, 点进去之前我还以为是判断素数的 |
8 FrankFang128 OP @billlee 我觉得 JS 程序员平时用不到这么复杂的算法(误 |
9 Luckyray 2018-04-19 02:01:55 +08:00 via iPhone 哈哈哈哈哈说的好有道理 |
10 QK8wAUi0yXBY1pT7 2018-04-19 02:22:31 +08:00 人家活在无墙的世界,300M 不是问题 |
11 crysislinux 2018-04-19 06:50:44 +08:00 via Android 还真别笑,你写的和这些库跑的测试用例并不一样。所以说起来好像实现的是相同功能,但实际上并不一样 |
12 woodensail 2018-04-19 08:48:51 +08:00 DRY 又不是 node 特有的,事实上 DRY 理念的提出比 node.js 的历史还要长。 |
13 ghostheaven 2018-04-19 08:49:26 +08:00 via Android 好多都是 JS 语法本身的坑,比如判断是不是字符串,是不是函数这种最基本的,都没有简单的方法。再加上早期核心对象的方法缺失,虽然后来补上了,导致某些常用功能要做额外的判断方法是否存在,或者要做 polyfill,比如字符串的 trim 这种。还有现在 ES2015+更新的语法和标准函数对象的快速增加,不得不同时采用 polyfill 和 babel 这种语法转换工具,以兼容比较老的浏览器版本。 |
14 houbaron 2018-04-19 08:53:42 +08:00 via Android 我们弱类型语言就是这样的,只能靠隐式类型转换才能维持生活这样子的。 |
15 woodensail 2018-04-19 08:56:02 +08:00 顺便一提,你以为动不动就下载 300M 是 node 特有的问题? 事实上每个包管理工具都是这样的。pip,maven,npm 无一例外。这种现象的出现时由于依赖库太多或太重。另外,包括 npm 在内的所有包管理工具都是有本地仓库做缓存的。所以事实上日常使用中大部分情况都是走缓存,很少需要下载新包。 npm 真正存在的问题是所有依赖文件全部会复制一份到项目文件夹,项目启动时所有依赖资源打包在项目内。而不是其他工具一样,将包留在本地仓库中,解析依赖时从仓库进行加载。 |
18 ywgx 2018-04-19 09:03:03 +08:00 就是因为这点,才彻底看衰 node.js |
19 linxl 2018-04-19 09:10:05 +08:00 想到上次看到一个 json 解码的 node 包。。 很费解 |
20 kerr92 2018-04-19 09:11:00 +08:00 哈哈,不知道大家怎么看待用到 isArray, isUndefined 必须得引入 lodash 的前端程序员 |
21 mooo 2018-04-19 09:18:45 +08:00 动不动下载 300M 和这个还真没关系。 |
22 viko16 2018-04-19 09:23:49 +08:00 via Android 面向 npm install 编程的我含泪点赞… |
23 crist 2018-04-19 09:26:07 +08:00 最好语言 PHP 欢迎你! |
24 misaka19000 2018-04-19 09:27:33 +08:00 |
25 zhouxuchen 2018-04-19 09:32:13 +08:00 每一次 npm install 都是奇妙的旅行…… |
26 LuoyeBug 2018-04-19 09:33:49 +08:00 php 现在的包管理也是动不动依赖一堆 |
27 qiqico 2018-04-19 09:38:01 +08:00 基本同意楼主观点 不过也不是所有人都这样的,比如我就不喜欢用 lodash 这种库,现在用 babel 的情况下 |
28 janxin 2018-04-19 09:40:16 +08:00 一行代码都不写你都可以拉 300M 下来 |
29 LxRuzx 2018-04-19 09:40:17 +08:00 为啥这个页面是 黑的??? |
30 dany813 2018-04-19 10:10:37 +08:00 老哥 cnode 发一遍 这边发一遍 好闲啊 |
31 soulmine 2018-04-19 10:41:46 +08:00 你们 node 不都是写个 hello world 然后下了 1000+的包么 |
33 Wolfpancake 2018-04-19 11:36:10 +08:00 is-thirteen 了解一下 https://www.npmjs.com/package/is-thirteen |
34 Mitt 2018-04-19 11:56:12 +08:00 via iPhone 这是一个问题 但这不是一个大问题 它既不影响你开发也不影响你运行和部署 它只是让你看起来很糟糕 |
35 zachguo 2018-04-19 12:07:47 +08:00 via Android - 跟 DRY 没有关系 - JS 打包和发布太容易了 - ES5 之前的历史遗留问题 - 这个问题不难解决 |
36 StickmY 2018-04-19 12:07:51 +08:00 via iPhone @FrankFang128 这样这有很明显的问题,因为 js 的弱类型特征,需要做很多判断 |
37 lxy 2018-04-19 12:17:28 +08:00 一次同事突发奇想要打包( rar )项目的 .node_models,电脑是固态硬盘,结果我们出去吃饭半小时回来了还没打包完.. |
38 xiaojie668329 2018-04-19 12:22:52 +08:0 via iPhone 神烦那些什么都要引入一个包的人,为了一个方法引入整个 lodash。还有一些很简单的库,明明写一个也不用多少时间。他引入了,为了确保准确,还得去找这个包来看 api 作用。 |
39 leetom 2018-04-19 12:23:20 +08:00 记得看到过一个一行代码的包,下载量也是惊人。关键是都在鼓吹 NPM 有多先进。不能理解,但还是得用。 |
40 rrfeng 2018-04-19 12:23:57 +08:00 via Android 就不说我们一个项目有 800M 了...(为了安全只能把 modules 也打包进去) |
41 POPOEVER 2018-04-19 12:27:23 +08:00 @Wolfpancake 被 license 笑死 |
42 yushiro 2018-04-19 12:33:02 +08:00 via iPhone 人家库的源代码都写的很明白了,你自己写一句简单的奇偶判断,有考虑到源码里面的那些情况吗?如果没有,那就好好的学习别人的思路吧。 |
43 Yuiham 2018-04-19 13:29:01 +08:00 via Android 很多 npm 包的粒度控制得不好,并不是说 leftpad 和 rightpad 分开就 dry 吧 |
44 lujiajing1126 2018-04-19 13:36:24 +08:00 没什么问题啊,如果别人的包更健壮,为什么不用? 楼主怕是从 ES6 才开始学 JS 的吧 |
45 FrankFang128 OP @lujiajing1126 你会用么 |
46 FrankFang128 OP @yushiro 你会考虑用这个库么? |
47 FrankFang128 OP @lujiajing1126 你会考虑用这个库么? |
48 jzz7280 2018-04-19 13:54:14 +08:00 确实乱 |
50 chairuosen 2018-04-19 14:28:56 +08:00 |
51 learnshare 2018-04-19 14:34:04 +08:00 当你需要一个功能的时候,必然有一个 npm 包在那里 |
52 mooo 2018-04-19 14:43:35 +08:00 @FrankFang128 > 1.原来有这么多 JS 程序员不会判断奇数 is-odd 每周下载 300 万是因为[nanomatch]( https://www.npmjs.com/package/nanomatch) 中引用了, 引用的原因看这个(pul requests)[https://github.com/micromatch/nanomatch/pull/7] > 讽刺 JS 程序员写代码不带脑子哈哈.. 明显是编程风格问题, 楼主提高到 JS 程序员的角度不知道楼主提问题带不带脑子 |
54 myyou 2018-04-19 14:54:34 +08:00 这些东西应该整体做一个工具集,而不应该单独发布 |
55 Pastsong 2018-04-19 15:01:15 +08:00 工具集不符合社区推崇的是最小化 import,如果 is-odd 被项目里的 100 个包引用了,那最终产出的相关逻辑代码只有一份,但如果每个包自己实现了 is-odd,你在最后项目里就有 100 份相同代码 |
56 mooo 2018-04-19 15:17:07 +08:00 |
58 FrankFang128 OP @kerr92 lodash 提供的其他 API 很好用的。 |
59 ke1vin 2018-04-19 15:25:25 +08:00 @Wolfpancake 为什么那么多 star ???? |
60 FrankFang128 OP @mooo 看了,原因是他是模块化的粉丝,也就是「他喜欢这么做」。 |
61 FrankFang128 OP @mooo 不带脑子算是我留的喷点啦,吐槽而已~ |
62 mooo 2018-04-19 15:34:08 +08:00 @ke1vin 娱乐项目 这个星更多 https://github.com/kelseyhightower/nocode |
63 EyreFree 2018-04-19 15:37:10 +08:00 围观,[吃瓜] |
64 LeungJZ 2018-04-19 17:12:35 +08:00 换个地方,再一次坐等打脸? |
65 LeungJZ 2018-04-19 17:12:40 +08:00 |
66 lihongjie0209 2018-04-19 17:17:11 +08:00 @woodensail #15 你确定 maven 中会有这种垃圾库并且还有人用?? |
67 lwbjing 2018-04-19 17:27:42 +08:00 驳《我不是很懂 Node.js 社区的 DRY 文化》 https://mp.weixin.qq.com/s/OQsXOeah0ENK7Y6anAbXgg @justjavac @FrankFang128 我只是转一下,大家别打我。。 |
68 yushiro 2018-04-19 17:27:46 +08:00 via iPhone @FrankFang128 用不用这种总结前人经验的库,看你自己对自己的期望了。如果只是为了完成一份工作,那就自己写个简单的功能代码即可,万一出问题了,debug 解决呗。 如果是想成为一个优秀的开发者,这种库肯定要用啊,这是别人的经验,都已经帮你把坑都填了,非要自己再去踩坑? |
69 woodensail 2018-04-19 17:29:27 +08:00 @lihongjie0209 我只是针对 300M 这一点而已。其他的我不予置评,但是 300M 的问题在任何包管理工具上都有。 |
70 lihongjie0209 2018-04-19 17:35:36 +08:00 @lwbjing #67 这篇文章强调了一个函数的正确性和性能,但是却没有说明一个好的模块不是由一个函数组成的, 而是由一系列高级抽象组成的, 到最后只会导致越来越多的臃肿代码 |
71 lihongjie0209 2018-04-19 17:48:51 +08:00 @Pastsong #55 最小化是有一个阈值的, 以函数为最小单位发包必定会导致依赖管理异常复杂. |
72 LadyChunsKite 2018-04-19 17:51:53 +08:00 转发:驳《我不是很懂 Node.js 社区的 DRY 文化》 https://segmentfault.com/a/1190000014480379?utm_source=index-hottest |
73 clino 2018-04-19 17:57:58 +08:00 @Wolfpancake #33 370 commits 103 contributors ... 大家好闲啊... |
74 overflowHidden 2018-04-19 18:03:12 +08:00 @LadyChunsKite #72 “在回过头来看看 is-number 库,不仅仅有 100 多行的 test case,还有一个目录 benchmark。这里面的代码我没有数,但是光看文件数量就有 10 个以上。也就是说作者不仅仅保证了这个函数的运行结果没有问题,更保证了这个函数的性能。 我们为什么要使用这个库,因为作者为了他的 10 行代码,写了几百行的其它代码来保证质量。” 惊呆了。。。 |
75 clino 2018-04-19 18:18:48 +08:00 @LadyChunsKite #72 http://zhuanlan.zhihu.com/p/35870240 驳《驳《我不是很懂 Node.js 社区的 DRY 文化》》 https://zhuanlan.zhihu.com/p/35880323 请 Node.js 社区正面回答 |
76 quxiangxuanqxx 2018-04-19 18:35:42 +08:00 楼主说的挺好 就是那三句结论,全文最大的败笔呀,程序猿写结论的时候不应该开这种逻辑明显错误还迎战的玩笑 所以我的结论是 楼主文章没错,指出了 node 社区的问题,但是结论涉及引战 这对讨论问题没有任何帮助,你要是真想好好讨论问题,就别写这种槽点满满的结论 除非,你只是为了制造热度 |
77 easylee 2018-04-19 18:42:41 +08:00 这些算法都算不上的代码 实现都不会是怎么找到工作的? |
78 mkeith 2018-04-19 18:49:27 +08:00 via iPhone 现在 nodejs 已经从服务端语言又变回浏览器端了 |
79 FrankFang128 OP @quxiangxuanqxx 250 多万 is-odd 的下载量得出这个结论我不觉得很过分,他们就是不会写判断奇数…… |
80 FrankFang128 OP @easylee 同疑惑 |
82 FrankFang128 OP @welkinzh 看起来是开玩笑的 |
83 MeteorCat 2018-04-19 20:45:42 +08:00 可能是缺少一个大头来做库收集和论证 就像 C++的的 stl 和 boost 库一样,每个轮子都需要先进 boost 论证完才能进入 stl 库 有权威人士为其使用代价来背书 而 node.js 则是过于强调个人,这个作用用了 XXX 库,"你看作者这么牛逼,应该采用他写的库"; 而且第二天另外一个作者也做了相同功能,"你看那个作者写的这么牛逼,这些库我们也得引用" 实际上通过权威来论证他们合理性和坑点之后,其他人看到之后也就会自然而然的规范自己使用方式 (当然很多开发都是喜欢自己造轮子的,比如很多著名的 C/C++都是自己搞自己的字符串库) |
84 mooo 2018-04-19 21:38:23 +08:00 @FrankFang128 没有 300M 吧 我这依赖都是 100 多 M, 感觉是来故意引战的。。。 |
85 hjdtl 2018-04-19 21:47:07 +08:00 我要指出一点,这个作者一边到处贬低 js 或者前端,一边搞培训教前端。他说的不无道理,只是一些言论很夸张,想搞个大新闻,从中获利(? |
86 mooo 2018-04-19 22:23:08 +08:00 @FrankFang128 1。250 多万 is-odd 的下载量得出这个结论我不觉得很过分,他们就是不会写判断奇数…… s-odd 300W 的下载量来自 nanomatch, 很明显 nanomatch 的人不会判断奇偶性(虽然是一个人写的。。。 2. 动不动就下载 300 Mb 的东西, 是的,引用 4000 多字节的 is-odd 会让我们的依赖越来越大,所以我们要多用 24K 的 lodash. 3. 我终于知道为什么 npm install 总是动不动就下载 300 Mb 的东西了,Node.js 社区强调的 DRY 文化使得 node_modules 臃肿不堪,因为有的库引用了 is-object,有的库引用了 isobject,还有的库引用了 isObject, 麻烦楼主给个分析, 你 300 Mb 的依赖到底是来自各种各样的 isobject,is-number 这种仓库还是来自别的地方 4. 成堆的 one-line lib,用的人还贼多, 142 引用 的 is-number 用的人贼多 65955 引用 的 lodash 没人用 你们 node 社区都爱用 is-number 这种 one-line lib 5.关键是大部分库名称类似、质量还不高 module.exports = function isOdd(i) { if (!isNumber(i)) { throw new TypeError('is-odd expects a number.'); } if (Number(i) !== Math.floor(i)) { throw new RangeError('is-odd expects an integer.'); } return !!(~~i & 1); }; 这种质量太差了, 明显不如 %2 质量高 6. 每个库引用了不同的 one-line lib,导致代码非常重复,而且使用者还没法分析重复在哪 麻烦楼主贴一下, 到底这些 one-line lib 怎么重复的,让你的依赖到了 300m |
87 royhan 2018-04-19 22:29:07 +08:00 十行代码,形式化验证都能保证正确性了,居然写了几百行的测试?(逃 |
88 msg7086 2018-04-19 22:53:17 +08:00 判断奇偶性的函数,没看过这个包的源代码,你确定你写得出来? 反正我是写不出来的,最多只写得出一个 % 2 === 1 然后回头被其他人骂到死。 |
90 zhuangzhuang1988 2018-04-19 23:03:23 +08:00 |
91 Kongtou 2018-04-19 23:31:25 +08:00 via Android 前端已凉,同学们! |
92 stzz 2018-04-19 23:52:35 +08:00 via Android 不会写奇偶的菜鸡路过 !!(~~i & 1),前面不是判断过整数么,为何还要两次取反… |
93 lolizeppelin 2018-04-20 00:24:32 +08:00 via Android js 为了在浏览器里怎么也不崩溃 代码依赖都没下完都能跑 所以才那么乱的 从骨子里就不适合严格的编程 那个奇数计算里的各种判断就是 tm 多余的 哪个动态语言每次计算有要先判断类型的 要判断也是数据入口做 独立出 type 验证方法 而不是写在计算里 这种库就是在浪费性能 |
94 mrcode 2018-04-20 00:25:15 +08:00 我觉得你说的这些不算 npm 的痛点,npm 的痛点在于项目之间的 package 不能共享 |
95 FrankFang128 OP |
97 nikolai 2018-04-20 01:17:36 +08:00 |
98 FrankFang128 OP @nikolai 明明是 + 号的坑,非要用 is-number 来弥补。 不要用 +[] 这样的代码就好了,用 parseInt |
99 xqdoo00o 2018-04-20 11:51:28 +08:00 这难道 不是弱类型语言 隐式转换的锅吗? 前端 TS,后端 ts-node 不就行了吗 |
100 sammo 2018-04-20 11:54:58 +08:00 via iPhone js 的用法好像机器语言阿 ... 其他人为了解决机器语言不好写的问题,发明了高级语言 M$ 为了解决机器语言不好写的问题 发明了 高级语言 TypeScript “另一些人” (也就是 Node.js 社区的人) 为了解决机器语言不好写的问题,发明了 “高级机器语言” https://zh.m.wikipedia.org/wiki/TypeScript 不同方向走向了不同的地方 ... |