You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置NPM默认忽略超过指定时间阈值的软件包版本?

嘿,这个防范供应链攻击的思路挺棒的!针对家庭环境,完全不用搞企业那种复杂的私有镜像,有几个轻量的方案能实现你的需求,我给你梳理一下最简便的两种:

方法一:项目级依赖时间检查(推荐)

这个方案针对单个项目配置,灵活可控,不会影响其他项目。核心思路是利用npm的preinstall钩子,在每次执行npm install前自动检查所有依赖的发布时间,超过阈值且未审核的包会阻止安装。

步骤1:准备检查脚本

在项目根目录创建一个名为check-dep-ages.js的Node.js脚本,内容如下:

const { execSync } = require('child_process');
const semver = require('semver');
const moment = require('moment');

// 自定义时间阈值(这里设为60天,即2个月)
const THRESHOLD_DAYS = 60;

// 加载已审核通过的旧版本包列表
let allowedPackages = new Set();
try {
  allowedPackages = new Set(require('./allowed-old-packages.json'));
} catch (err) {
  // 如果文件不存在,初始化空集合
}

// 获取项目的依赖列表(包括生产和开发依赖)
const packageJson = require('./package.json');
const allDependencies = {
  ...(packageJson.dependencies || {}),
  ...(packageJson.devDependencies || {})
};

let hasUnapprovedOldPackages = false;

for (const [pkgName, versionRange] of Object.entries(allDependencies)) {
  try {
    // 获取该包的所有版本及发布时间
    const timeData = JSON.parse(execSync(`npm view ${pkgName} time --json`).toString());
    // 过滤出有效的版本号
    const validVersions = Object.keys(timeData).filter(v => semver.valid(v));
    // 找到符合当前版本范围的最新版本
    const matchedVersion = semver.maxSatisfying(validVersions, versionRange);

    if (!matchedVersion) {
      console.warn(`⚠️  无法找到${pkgName}符合版本范围${versionRange}的有效版本`);
      continue;
    }

    // 计算版本发布至今的天数
    const publishDate = new Date(timeData[matchedVersion]);
    const daysSincePublish = moment().diff(publishDate, 'days');

    // 检查是否超过阈值且未审核
    if (daysSincePublish > THRESHOLD_DAYS && !allowedPackages.has(`${pkgName}@${matchedVersion}`)) {
      console.error(`❌ 未审核的旧版本依赖:${pkgName}@${matchedVersion}`);
      console.error(`   发布时间:${publishDate.toLocaleString()},已超过${THRESHOLD_DAYS}天`);
      hasUnapprovedOldPackages = true;
    }
  } catch (err) {
    console.warn(`⚠️  无法获取${pkgName}的版本时间信息:${err.message}`);
  }
}

// 如果存在未审核的旧包,终止安装流程
if (hasUnapprovedOldPackages) {
  console.error('\n请将需要保留的旧版本包添加到allowed-old-packages.json文件中,或调整依赖版本后重试');
  process.exit(1);
} else {
  console.log('✅ 所有依赖版本均符合时间要求,开始安装...');
}

步骤2:配置package.json

在项目的package.json中添加preinstall脚本,并安装所需的依赖:

{
  "scripts": {
    "preinstall": "node check-dep-ages.js"
  },
  "devDependencies": {
    "moment": "^2.29.4",
    "semver": "^7.5.4"
  }
}

步骤3:初始化审核列表

在项目根目录创建allowed-old-packages.json文件,初始内容为空数组:

[]

当遇到必须使用的旧版本包时,将其格式如"pkg-name@version"添加到数组中即可,比如:

["lodash@4.17.21", "express@4.18.2"]

使用方式

每次执行npm install时,脚本会自动运行检查。如果存在未审核的旧版本包,安装会被终止;所有包符合要求或已审核时,才会继续安装。也可以手动触发检查:

npm run preinstall

方法二:全局生效的检查方案

如果你希望所有本地项目都默认应用这个规则,可以配置全局的npm钩子:

  1. 在用户目录下创建全局脚本(比如~/.npm-global/scripts/check-global-dep-ages.js),内容和方法一中的check-dep-ages.js基本一致,只需修改allowedPackages的加载路径为全局文件(比如~/.npm-global/allowed-old-packages.json)。

  2. 配置npm全局钩子:

npm config set preinstall "node ~/.npm-global/scripts/check-global-dep-ages.js"

不过这个方案灵活性稍差,不同项目的阈值或审核需求可能不同,所以更推荐项目级的方案。


内容的提问来源于stack exchange,提问作者Tomáš Zato

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 10:22:29