
本文介绍一种基于 HTTP 响应头 Last-Modified 的轻量级方法,通过解析 npm 包下载链接的最后修改时间,筛选出长期未维护(例如两年内无新版本)的依赖项,适用于 npm 和 yarn 项目,无需额外依赖即可快速识别潜在风险包。
本文介绍一种基于 http 响应头 last-modified 的轻量级方法,通过解析 npm 包下载链接的最后修改时间,筛选出长期未维护(例如两年内无新版本)的依赖项,适用于 npm 和 yarn 项目,无需额外依赖即可快速识别潜在风险包。
在现代前端工程中,npm outdated 是检查依赖版本落后的常用命令,但它仅能发现已有新版本发布的包——对已被作者弃用、长期停滞(如两年未发版)的“幽灵依赖”,它完全无感。这类包虽显示“最新”,实则可能已不兼容新版 Node.js、TypeScript 或安全生态,成为隐性技术债。
一个高效且跨包管理器(npm / yarn 兼容)的实践方案是:利用 npm registry 的静态资源 URL 及其标准 HTTP 响应头 Last-Modified。每个 .tgz 包文件在 registry 上均托管为不可变资源,其 Last-Modified 时间戳精确对应该版本包的发布时间(即 npm publish 时间),因此可直接作为“最后活跃度”指标。
以下是一段经过优化、健壮性增强的 Bash 脚本(Linux/macOS):
#!/bin/bash
# find-stale-deps.sh — 检测 2 年内未更新的直接依赖
THRESHOLD_DAYS=730
echo "? 扫描直接依赖(package.json 中 dependencies/devDependencies)..."
npm ls --json --prod --dev 2>/dev/null | \
jq -r '.dependencies? | .[]? | select(.resolved) | .resolved' | \
while IFS= read -r url; do
if [[ -n "$url" ]]; then
# 获取 Last-Modified 头(超时 3s,静默失败)
last_mod=$(curl -sI --max-time 3 "$url" 2>/dev/null | \
grep -i "^last-modified:" | \
sed 's/^[Ll][Aa][Ss][Tt]-[Mm][Oo][Dd][Ii][Ff][Ii][Ee][Dd]:[[:space:]]*//' | \
tr -d '\r\n')
if [[ -n "$last_mod" ]]; then
# 转换为 Unix 时间戳便于比较
mod_ts=$(date -d "$last_mod" +%s 2>/dev/null || echo 0)
now_ts=$(date +%s)
if [[ $mod_ts -ne 0 ]] && [[ $((now_ts - mod_ts)) -gt $((THRESHOLD_DAYS * 86400)) ]]; then
pkg_name=$(basename "$(dirname "$url")" | sed 's/^@//; s|/|-|')
echo "⚠️ ${pkg_name} (last published: $(date -d "$last_mod" '+%Y-%m-%d')) — $url"
fi
fi
fi
done | sort -k4,4✅ 使用说明:
- 保存为
find-stale-deps.sh,赋予执行权限:chmod +x find-stale-deps.sh - 运行:
./find-stale-deps.sh - 输出示例:
⚠️ user-event (last published: 2021-10-18) — https://registry.npmjs.org/@testing-library/user-event/-/user-event-13.5.0.tgz
? 进阶提示:
- 若需包含嵌套依赖(transitive deps),可将
npm ls --json替换为jq -r '.packages | to_entries[] | select(.value.name and .value.resolved) | .value.resolved' package-lock.json; - yarn 用户可先运行
yarn install确保生成yarn.lock,再用yarn list --json替代(注意输出格式差异); -
注意可靠性边界:此法依赖 registry 的 HTTP 服务稳定性与响应头准确性,不适用于私有 registry(需确认其是否返回标准
Last-Modified); -
安全建议:对识别出的 stale 包,务必结合
npm view <pkg> time</pkg>验证(如npm view @types/node time可查各版本发布时间),并人工评估替代方案(如迁移到社区维护分支或 fork)。
识别“沉默的老依赖”不是终点,而是技术健康度治理的起点。定期运行此类检查,配合自动化 CI 步骤(如 PR 提交时扫描),可显著降低维护成本与安全风险。


















