最火的npm包,三成已经没人管了
📋 总体概括
一项对全部2905个百万级周下载npm包的逐一手动核查显示:887个(约30%)超过一年没有发版,630个沉默超过两年。更麻烦的是,npm官方已下架了全量索引接口。本文拆解这组数字背后的方法、含义与供应链风险,并讨论开源'沉默即完成'的产业悖论。
📄 正文
最火的npm包,三成已经没人管了。
全部2905个周下载量超过100万的npm包中,887个在过去12个月里没有发布过任何版本,占比约30%;其中630个的沉默期已经超过两年。这份数据来自开发者Pavel Zubkou的一个人完成的普查项目 npm-census,快照时间为2025年10月9日至10日,方法是对着npm registry逐包人工核查。
下载量说明一个包还活在生态里,但说明不了还有人给它写代码。这个缺口,正是今天整个软件供应链最容易被忽视的那一块。
📉 全量核查:不是抽样,是2905个包挨个点名
做这件事的出发点很朴素:npm上的包不会过期。一个2015年发布后就再没动过的包,只要别人还在依赖它,就会随着每一次npm install继续流入千千万万个项目。周下载量证明它还在被用,不能证明它还被维护。
于是问题可以换成一个“无聊版本”的供应链提问:在JavaScript世界下载量最高的那批包里,有多少已经一年以上没有发过版?
核心数字如下:
| 指标 | 数值 | 占比 |
|---|---|---|
| 周下载量 ≥ 100万的包总数 | 2,905 | 100% |
| 过去12个月无任何发版 | 887 | 约30% |
| 其中超过24个月未发版 | 630 | 占总数约21.7% |
| 12–24个月之间未发版 | 257 | 占总数约8.8% |
| 12个月内有发版 | 2,018 | 约69.5% |
用饼图看更直观:
这里要强调方法论的诚实:作者没有抽样2905个里的几百个,而是全部逐一对照registry核查。当然,一个包两年不发版不等于“死了”——有些包是真的“完成了”,稳定、无bug、无需更新。问题的核心在于:你分不清哪些是完成,哪些是弃养,除非你去查。
在开源维护者社区里流传一句半开玩笑的话:“不发版的包有两种,一种是修好了,一种是没人修了。”对下游企业来说,这两者的风险敞口天差地别,而它们在registry里长着一模一样的脸。
🗂️ npm把自己的全量索引下架了
这份数据的诞生过程,本身就是一个值得单独讲的故事。
作者原本的打算很简单:下载npm的全量包索引,本地一跑就出结果。结果发现这条路已经封死了——registry的枚举接口/-/all、/-/v1/all、/_all_docs全部返回404,作者逐一验证过。那个曾经约4GB的JSON全量索引,官方已经不再提供。
也就是说,你想系统性地回答“npm生态里谁还活着”这个问题,官方已经不给你数据了。
这个细节的产业含义,比那887个数字本身更值得琢磨。
第一,生态透明度在物理性下降。以前任何研究者、安全团队、企业采购方都能拉一份全量索引做分析;现在这类分析只能靠逐包请求,成本从“一次下载”变成“数千次调用”。生态级的健康度量——多少包无人维护、多少依赖链悬空——从此缺少一个可以常态化刷新的基线。
第二,平台收回数据接口,分析权就集中回平台手里。这不是npm独有的现象,而是整个开源基础设施的普遍趋势:registry、代码托管、CI服务都在收紧枚举类接口。对做数据平台的人来说,这个场景太熟悉了——上游接口一收,下游所有依赖“全量枚举”的分析管线全部失效。据多位做过开源生态数据分析的工程师反映,这几年类似的上游接口变更,已经悄悄废掉过不少企业内部的开源资产盘点工具。
第三,一人工作室用最笨的办法补上了平台留下的空档。这本身就是一种信号:生态健康的度量,正在从“平台义务”变成“民间自费劳动”。
⚠️ 下载量不等于活着的软件
回到那887个包。为什么“高下载+零发版”是个危险组合?
逻辑链条其实很直白:现代JavaScript项目的依赖树动辄数百上千个包,头部包处于依赖树的咽喉位置。一个百万周下载的包一旦被发现安全问题,正常解法是维护者快速发一个补丁版本,下游锁住新版本即可。但如果这个包已经两年没人碰,补丁就不存在——下游数以万计的项目只能自己fork、自己patch,或者赌这个问题够小。
对企业工程团队来说,真正麻烦的是分拣成本。在这2905个包里,那2018个一年内有发版的,风险画像清晰;而887个沉默包里,混着三类完全不同的东西:真正完成、功能冻结、彻底弃养。三类包在扫描器报告里的呈现完全一样——“该依赖超过365天未更新”。安全团队面对的从来不是数字本身,而是数字背后无法自动区分的意图。
这里有一个反直觉的产业判断:头部包的“沉默”未必比长尾包更危险,但头部包沉默造成的系统性盲区一定更大。 长尾无人维护的包成千上万,业界早已默认;头部包是大家默认“一定有人在管”的那一层。三成头部包没人管这个事实,击穿的是这层默认信任。
顺便说一句,这场核查本身也提醒所有做数据的人:“看起来很好拿的数据”和“实际还存在的数据”之间,永远有距离。 作者最初设想的4GB索引下载方案,第一分钟就死在了404上。
💸 谁来为“已完成”的代码付账
把镜头拉远,这组数字指向的是开源可持续性的老问题,只是换了一副新面孔。
过去十年,开源的商业化叙事集中在“持续演进”的项目上——数据库、AI框架、开发平台,这些项目靠云服务、订阅、托管赚钱,维护有商业引擎。但npm生态的真相是:支撑现代应用的相当一部分重量,压在那些没有商业模式、也没有商业义务的小包上。
一个百万周下载的包,如果它两年没发版是因为“作者找到了工作、项目稳定、没有收入压力也没有外部资助”,那它是健康的;如果是因为“作者累了、没人接手、issue堆积”,那它就是一颗定时存在感的雷。而这两种状态,从外面完全看不出来。
| 维度 | 下载量能告诉你 | 下载量不能告诉你 |
|---|---|---|
| 生态位置 | 是否被广泛依赖 | 是否处于关键依赖链咽喉 |
| 使用热度 | 每周被安装多少次 | 安装之后是否真的在运行 |
| 维护状态 | — | 是否还有人在提交和发版 |
| 风险敞口 | — | 漏洞出现时有无补丁路径 |
对企业的启示有三条,都很实操:
1. 把“发版时间”写进依赖准入标准。引入新依赖时,除了看下载量和star,把最近发版时间、维护者活跃度设为硬指标;对沉默超过12个月的头部依赖建立白名单机制,区分“冻结即完成”与“弃养”。
2. 建立内部的沉默包台账。既然npm官方不再提供全量索引,企业只能基于自己的lock文件做反向盘点——你的依赖树里有多少包落在那887的画像里,是可计算、也应该被计算的。
3. 对关键沉默依赖,准备fork预算。真正的供应链韧性不是“发现问题时再想办法”,而是提前知道哪些包出问题时需要自己接盘,以及接盘要多少人天。
开源世界欠维护者的账,最终都会以工程工时的方式还给企业。区别只在于,是提前付在赞助和内部兜底上,还是事后付在应急修复上。
三成头部包沉默,官方索引下线,民间自费普查——这三个事实拼在一起,勾勒出的是开源基础设施治理的真空地带:生态最大的风险,不是某个包坏了,而是没有人有义务告诉你哪些包坏了。
接下来可以预见两类动作:一是企业侧的依赖治理工具会把“维护活跃度”提到和安全扫描同级的位置;二是registry平台在枚举接口与生态透明之间,需要重新找一个平衡点——数据不开放,风险就只会转移到最难承受它的下游。
那份一个人手工做出来的“过期但关键”清单,价值不在887这个数字,而在它示范了一件事:生态健康这件事,在平台不管、数据不开放的时候,总得有人用笨办法把它算出来。
本文由本站 AI 辅助聚合生成,原始来源如下: