在之前的帖子中,我们关注了运行时性能,我认为现在看看 Node
模块的安装时间也很有趣。关于各种算法优化或使用更高效的系统调用已经有很多文章,但我们为什么一开始就有这个问题呢?为什么每个 node_modules
文件夹都这么大?这些依赖都是从哪里来的?
一切都始于我的一个朋友注意到他的项目的依赖树有点奇怪。每当他更新一个依赖项时,它都会引入几个新的依赖项,随着每次后续更新,总依赖数量逐渐增加。
1 | ├─┬ arraybuffer.prototype.slice 1.0.2 |
公平地说,一个包可能依赖于其他附加的依赖项是有合理理由的。然而,在这里,我们开始注意到一个模式:新的依赖项都是为 JavaScript
函数提供的 polyfill
,而这些函数在所有地方早已得到支持。例如,Object.defineProperties
方法是作为 Node 0.10.0
的第一个公共版本的一部分发布的,可以追溯到2013年。甚至连 Internet Explorer 9
都支持它。然而,许多包都依赖于它的 polyfill
。
在引入 define-properties
的各种包中,有一个引起了我的注意,那就是 eslint-plugin-react
。它引入了 Object.defineProperties
的 polyfill
,但没有 JavaScript
引擎是没有内置它的。
Polyfills是无效的
阅读这些包的源代码揭示了更奇怪的事情:这些 polyfill
函数是直接导入和调用的,而不是在运行时环境中补丁缺失的功能。polyfill
的整个目的是对用户的代码是透明的。它应该检查要补丁的函数或方法是否可用,并仅在缺失时添加它。当不需要 polyfill
时,它应该什么都不做。对我来说奇怪的是,这些函数被直接使用,就像是库中的函数。
1 | // Why is the `define` function imported directly? |
相反,它们应该直接调用 Object.defineProperties
。polyfill
的整个目的是对环境进行补丁,而不是直接调用。将其与 Object.defineProperties
的 polyfill
应该是什么样子进行比较:
1 | // Check if the current environment already supports |
最常见的使用 define-properties 的地方讽刺的是在其他polyfill
中,而这些 polyfill
又加载了更多的 polyfill
。在你问之前,define-properties
包依赖的不仅仅是它自己。
1 | var keys = require("object-keys"); |
在 eslint-plugin-react
内,通过对 Object.entries()
的 polyfill
进行加载以处理它们的配置:
1 | const fromEntries = require("object.fromentries"); // <- Why is this used directly? |
本地清理
在撰写本文时,安装eslint-plugin-react
总共引入了令人惊讶的 97 个依赖项。我对其中有多少是 polyfill
感到好奇,并开始在本地逐个补丁。所有事情做完后,这将总依赖数量减少到了 15。原始的 97 个依赖项中有 82 个是不需要的。
巧合的是,同样在各种 eslint
预设中很受欢迎的 eslint-plugin-import
也存在类似的问题。安装该插件会填满您的 node_modules
文件夹,共有 87 个包。在经过另一轮本地清理后,我成功将这个数字缩减到了 17。
空间整理
现在您可能想知道您是否受到影响。我进行了快速搜索,基本上您能想到的每个广受欢迎的 eslint 插件或预设都受到了影响。由于某种原因,整个事件让我想起了一段时间前整个行业发生的 is-even/is-odd
事件。
拥有如此多的依赖项使得审核项目的依赖项变得更加困难。这也是对空间的浪费。举例来说:仅删除项目中的所有 eslint
插件和预设就减少了 220 个包。
1 | pnpm -r rm eslint-plugin-react eslint-plugin-import eslint-import-resolver-typescript eslint-config-next eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-prettier prettier eslint-config-prettier eslint-plugin-react-hooks |
我只是想要一些代码规范检查的规则。我不想要一堆我不需要的 polyfill
。