我是如何利用 NPM 下载的……以及为什么不应该相信它们
在过去的一个月里,我成功让一个几乎没有用户的软件包累计下载量超过一百万次🚀。
它不需要花费任何金钱,没有违反任何法律(我认为),而且几乎不需要付出任何努力。
以下是您需要了解的有关 NPM 的下载统计数据。
🔮 下载的幻觉
如果您曾经考虑过使用 NPM 的新包,那么您很可能考虑过“每周下载”统计数据。
这是页面上显示的第一个指标 - 因此它对用户来说一定是有用的信息......对吗?
参与本次调查的三分之一的人似乎都这么认为,甚至表示这对他们决定采用新方案有很大影响。
但问题是,由于以下两个原因,它并不是一个有用的指标:
- 用户数和下载量之间的关系(最好是松散的)
- 该系统很容易被利用
什么是下载
NPM 博客对此进行了很好的讨论,但总结一下,它是从 NPM 注册表中成功下载的任何包(tarball)。
NPM 已公开声明,此统计数据不考虑来源(IP、用户代理等)。这意味着所有下载都是平等的,无论来自:
- 用户向其项目添加新包
- CI 运行安装依赖项
- 机器人反复下载软件包,营造出流行的假象(这里有一些伏笔)
你可以想象,这意味着一个频繁运行 CI 的项目可能会比任何一组个体对下载统计数据产生更大的影响(尤其是在考虑 npm 客户端缓存时)。
注册表
注册表数量过多也是下载量无法准确反映使用情况的另一个原因。NPM 下载量仅包含官方 NPM 注册表的下载量,而不包括unpkg和github等注册表。
🧑💻 利用系统
免责声明:我记录此内容是为了说明下载统计数据是多么容易被利用。但是,我强烈建议您不要这样做,因为这既不诚实,又会浪费 NPM 公司的资源。
如果您已经阅读了到目前为止的所有内容,您就会知道不需要任何类型的“天才黑客攻击”。
相反,我们需要的是某种多次下载包的方法。
使用某种 cron 作业在本地运行脚本应该没问题 - 但这并不是太令人兴奋...让我们使用无服务器吧!
您可以在此处查看完整的 repo 。
创建脚本
对于 Lambda,我创建了一个采用以下参数的函数:
package
- 要下载的包probability
- 给定运行的下载可能性
后一种论点旨在增加噪音——模拟下载随时间的变化性质。
每次运行都会进行一次“抛硬币”,并probability
使用参数来衡量成功率。如果抛硬币成功,则下载该软件包。
export const handler = async ({ package, probability }) => {
// Simulate coin flip
if (Math.random() > probability) {
// Flip fail
return;
}
// Flip success
await downloadPackage({ package });
};
触发 Lambda
为了使该脚本定期运行,设置了以每分钟一次的频率触发的 CloudWatch 事件。
// Terraform example
resource "aws_cloudwatch_event_rule" "lambda_trigger_rule" {
name = "trigger-npm-install"
description = "Trigger an NPM install"
schedule_expression = "rate(1 minute)"
}
Terraform 中的示例 CloudWatch 事件规则。
为了在触发此事件时执行某些操作,我们设置了一个事件目标,并使用我们所需的参数指向 Lambda。
resource "aws_cloudwatch_event_target" "lambda" {
arn = aws_lambda_function.install_package_lambda.arn
rule = aws_cloudwatch_event_rule.lambda_trigger_rule.name
input = jsonencode({
package = "is-introspection-query"
probability = 0.8
})
}
Terraform 中的示例 CloudWatch 事件目标。
🚀 结果
部署了一周之后,结果......其实并不那么令人印象深刻;事实证明,一周内的秒数并没有我预期的那么多🤔。
但遗憾的是,经过一些调整后,我们每周的下载量已接近 100 万次!
是的,没错,一个实际上没有用户的软件包的下载量比urql
和之类的软件包还要多mobx
。
您现在看到问题了吗?
下载统计数据不起作用
事实是,简单的下载统计数据在最好的情况下是无用的,在最坏的情况下是具有误导性的。
NPM 网站上的大型图表、在线庆祝下载 量的文化、以及显示软件包下载“趋势”的第三方网站。所有这些都助长了这样一种说法:NPM 的下载量可以某种程度上反映软件包的受欢迎程度,但事实并非如此。
即使忽略恶意行为者(比如我自己)的可能性,大量的注册表和缓存实现也使得这些统计数据变得毫无用处。
“人气”
幸好,NPM 有个救星——流行度统计!我们干脆把下载次数换成其他更有用的统计信息吧……对吧?
不对——看来热门度统计只是伪装的下载量@prisma/engines
统计。正如你下面看到的,我的软件包在热门度方面超越了其他软件包。
以下是两个包的快速并排比较。
@prisma/引擎 | 是自省查询 | |
---|---|---|
每周下载量 | 约10万 | 约80万 |
星星 | 264 | 0 |
叉子 | 三十五 | 0 |
贡献者 | 二十六 | 1 |
用户 | 可能不是 0 | 肯定是 0 |
结论
如果您从本次讨论中得出一个结论,那就是下载量本身并不是一个有用的指标。
虽然我毫不怀疑 NPM 可以创建一个聚合包的许多不同属性的流行度指标(npms.io已经做到了这一点),但从现在开始,我将在信任NPM 🕵️ 上的下载量和流行度指标之前做更多的背景研究。
希望你觉得这篇文章有趣!如果你有任何想法或评论,欢迎在下方留言,或者在推特上联系我 - @andyrichardsonn
免责声明:本文中表达的所有想法和观点均为我个人的。
鏂囩珷鏉ユ簮锛�https://dev.to/andyrichardsonn/how-i-exploited-npm-downloads-and-why-you-shouldn-t-trust-them-4bme