🧮 定制你的评分公式
高级 · 20 分钟 · 2026-08-16
1. 文件结构
核心算法在 scripts/lib/score.mjs,只有这一个文件:
scripts/lib/score.mjs
├── logNormalize() // log scale 归一化
├── recencyScore() // 指数衰减时间评分
├── score() // 主入口,返回 5 维分数 + grade
├── gradeOf() // 分数→等级
└── parseGhRepo() // 从 URL 解析 GitHub owner/repo 2. 改权重
打开 scripts/lib/score.mjs,找 score() 函数末尾:
const overall = Math.round(
popularity * 0.25 + // ← 改这里
maintenance * 0.20 +
quality * 0.20 +
security * 0.15 +
dsh_compat * 0.20
); 改成你想要的比例(建议总和 = 1.0,否则 overall 会超 100 或低于 0)。
典型调整场景
| 场景 | 建议调整 |
|---|---|
| 企业场景,押注安全 | security 0.15 → 0.30,其他等比下调 |
| 个人开发者,不关心下载量 | popularity 0.25 → 0.10,quality → 0.30 |
| 想找冷门优质插件 | popularity 0.25 → 0.10,quality 0.20 → 0.35 |
| 只信 DSH 标准 | dsh_compat 0.20 → 0.40,其他等比下调 |
实战建议:popularity 该调高还是调低?
五维里最容易吵起来的就是 popularity。它衡量的是 weekly downloads 的 log 归一化值, 本质上是「别人替你踩过多少坑」的代理指标——不是质量本身。判断标准:
- 团队要定白名单:装机量本身就是最便宜的稳定性证据,出问题时能搜到别人的解法
- 生产环境、不能当小白鼠:冷门包的 bug 往往要你自己修,隐性成本远超评分差距
- 插件面向终端用户:下载量高意味着边界情况已经被大量真实输入打磨过
- 你不打算读源码:不看代码就装,只能靠群众基数兜底
- 你在做选型调研:想挖被低估的新包,高权重会让榜单永远是那几个老面孔
- DSH 生态还年轻:全站周下载量不到一万,头部和腰部差距被 log 放大后噪声很大
- 细分领域插件:某个垂直场景全网就 30 个用户,下载量根本没有区分度
- 内网 / 私有 registry:npm 公网下载量对你毫无意义,直接压到 0.05 更诚实
一个经验法则:popularity 权重 + maintenance 权重代表你有多依赖「社区替你验证」, quality + security + dsh_compat 代表你有多依赖「自己看代码验证」。 两组加起来永远是 1.0,先想清楚自己站哪边,再动数字。
3. 改等级阈值
同一文件,找 gradeOf() 函数:
function gradeOf(score) {
if (score >= 85) return 'S'; // ← 改这里
if (score >= 70) return 'A';
if (score >= 55) return 'B';
if (score >= 40) return 'C';
return 'D';
}
例:想让 D 级更严格,可以改成 score >= 30 才是 D(即低于 30 全部归到 "F 禁用")。
4. 改 Security 启发式
Security 维度最容易定制:
// score() 函数里 Security 部分:
let s = 50; // baseline
+ trustedPublisher.oidcConfigId ? 25 : 0
+ publisher.username ? 5 : 0
+ /audit|sandbox|permission|allowlist/.test(lowerDesc) ? 15 : 0 // ← 改关键词
- /eval|exec|child_process/.test(lowerDesc) && !/safe|sandbox/ ? 10 : 0
- gh.archived ? 30 : 0 例:你想给 "测试覆盖率" 加分:
+ /test|coverage|vitest|jest/.test(lowerDesc) ? 10 : 0 5. 跑完整重算
改完公式,跑:
# 重算所有插件评分(增量 5-30 秒)
cd /path/to/dsh-radar
node scripts/build-data.mjs
# 重算搜索索引
node scripts/build-search-index.mjs
# 重算 changelog(基于历史快照对比)
node scripts/build-changelog.mjs
# 重新 build 站点
cd web && npm run build 6. 验证效果
看 data/stats.json 的 by_grade 分布(下面是全量 711 个插件时的示意):
{
"total": 711,
"by_grade": {
"S": 1, // ← 改权重后数字会变
"A": 3,
"B": 147,
"C": 549,
"D": 11
},
"by_compat": 505,
"total_weekly_downloads": 8692,
"generated_at": "2026-08-16T01:55:19.531Z"
} 最快的验证方式是 git diff。改公式前先确保工作区干净, 重算后一条命令就能看出这次调参到底影响了谁:
# ① 只看等级分布怎么变(最直观)
git diff data/stats.json
# ② 看有多少个插件的 grade 真的翻了
git diff -U0 data/plugins/ | grep '"grade"' | sort | uniq -c
# ③ 看首页 Top 10 排名有没有洗牌
git diff data/index.json | head -60
# ④ 只想知道"改动波及多少文件"
git diff --stat data/
健康的调参:10%-30% 的插件换档,Top 10 里有 2-3 个位次变化。
如果 git diff 几乎没输出,说明这次调整没意义;
如果 90% 插件全部换档、S 级一下子冒出 50 个,说明权重和阈值不匹配,回去改 gradeOf()。
7. 提交 PR
如果你的公式改得不错,欢迎 PR 回主仓库:
# 1. fork → 改 score.mjs → 测试 OK
# 2. 提交
git checkout -b formula/my-tuning
git add scripts/lib/score.mjs data/stats.json
git commit -m "formula: 调整 security 权重到 0.30(企业安全优先)"
# 3. 推送 + 开 PR
git push origin formula/my-tuning PR 描述里写清楚:
- 改了什么(具体行 + diff)
- 为什么(场景)
- 前后对比(git diff stats.json)
- 对现有插件排名的影响(前 10 变化)
⚠️ 注意事项
改公式会让所有评分变化,影响现有用户的认知。谨慎改动主仓库公式,建议先在自己的 fork 跑两周,看社区反馈再提 PR。