安装依赖前,先拦截不兼容的 Node.js 版本
一个包可以声明 "node": ">=20" 并且仍然可能在几个命令之后给开发者留下模糊的失败信息。将运行时版本视为可执行的契约:声明它,检查它,并在安装依赖项之前提供修复指令。
小型检查
在以下位置添加无依赖脚本 scripts/check-node-version.mjs:
const requiredMajor = 20;
const actualMajor = Number.parseInt(process.versions.node.split(".")[0], 10);
if (!Number.isInteger(actualMajor) || actualMajor < requiredMajor) {
console.error(
`Node.js ${requiredMajor}+ is required; found ${process.versions.node}. ` +
"Install an active LTS release, then rerun npm install."
);
process.exit(1);
}
console.log(`Node.js ${process.versions.node} satisfies the Node.js ${requiredMajor}+ requirement.`);
在正常安装路径之前运行它:
{
"engines": { "node": ">=20" },
"scripts": { "preinstall": "node scripts/check-node-version.mjs" }
}
这个 engines 该字段使包管理器和托管系统能够检查该需求。该脚本使使用仅提醒引擎不匹配的包管理器的人也能看到相同的需求。
让文档使用相同的真实来源
快速入门应该准确说明检查执行的内容:
### Prerequisite
- Node.js 20 or newer (`node --version`)
If the install stops at the runtime check, install an active Node.js LTS
release and run `npm install` again.
像“一个最近的 Node.js 版本”这样的短语无法测试,并且一旦产品采用新的基线就会漂移。
在不更改运行时的情况下测试两个分支
将比较提取为纯函数,以便回归测试可以涵盖支持和不支持的版本:
export function supportsNode(version, requiredMajor = 20) {
const major = Number.parseInt(version.split(".")[0], 10);
return Number.isInteger(major) && major >= requiredMajor;
}
import assert from "node:assert/strict";
import { supportsNode } from "./supports-node.mjs";
assert.equal(supportsNode("18.20.8"), false);
assert.equal(supportsNode("20.0.0"), true);
assert.equal(supportsNode("22.19.0"), true);
assert.equal(supportsNode("not-a-version"), false);
此检查故意设置得很窄。常规测试套件仍然确保与较新的主要版本的兼容性。此检查保持声明的最低要求、第一条命令和快速入门之间不互相矛盾。
验收清单
- 在Node.js 18上干净安装会在依赖安装之前停止,并标明所需版本。
- 在Node.js 20上干净安装会继续到包管理器。
package.json,检查和快速入门都命名为相同的最小值。- 一个无依赖的测试覆盖边界和格式错误的输入。
这是独立编写的示例,不代表曾对第三方仓库进行测试。代码及文中结论均在 AI 辅助起草后经过人工复核。
有首次运行阻塞问题吗?
发送仓库和预期结果。我们可以定义一次小型首次交付,并明确验收标准。
发送电子邮件给 Tiee