概述
在发布npm包的时候,安装包tag指向错误。本文档说明正式发布与 alpha 测试发布的流程、dist-tag 机制,以及 Nexus 删除版本后 tag 异常的成因与处理方式。
发布脚本
| 发布类型 | 脚本 | 版本策略 | 构建模式 | dist-tag |
|---|---|---|---|---|
| 正式版 | local-publish |
npm version patch |
build-prod |
latest(默认) |
| 测试版 | local-publish-alpha |
npm version prepatch --preid alpha |
build-test |
alpha |
脚本定义
json
{
"local-publish": "npm version patch && npm run build-prod && npm publish --registry https://nexus...",
"local-publish-alpha": "npm version prepatch --preid alpha && npm run build-test && npm publish --registry https://nexus... --tag=alpha"
}
使用方式
bash
# 发布正式版(更新 latest)
npm run local-publish
# 发布 alpha 测试版(仅更新 alpha,不影响 latest)
npm run local-publish-alpha
预期 dist-tag 状态
正常发布后,Registry 上的 tag 应类似:
json
{
"latest": "2.1.6",
"alpha": "2.1.8-alpha.0"
}
latest:最后一个稳定版,供生产环境使用alpha:最新测试版,供开发/测试环境使用
消费方安装方式
json
{
"install:dev": "... && yarn add talos-explain-player@alpha",
"install:prod": "... && yarn add talos-explain-player@latest"
}
| 环境 | 安装命令 | 期望版本 |
|---|---|---|
| 开发/测试 | talos-explain-player@alpha |
最新 alpha 版 |
| 生产 | talos-explain-player@latest |
最新稳定版 |
.npmrc 默认 Registry
问题现象
现象 1:安装 @latest 得到 alpha 版
bash
yarn add talos-explain-player@latest
# 实际安装:talos-explain-player@2.1.10-alpha.0
查询 dist-tags:
bash
npm view talos-explain-player dist-tags --registry=https://nexus...
# { latest: '2.1.10-alpha.0' } ← latest 指向了 alpha 版
# 且没有 alpha 标签
现象 2:删除 alpha 版本后 tag 错乱
典型复现步骤:
- 执行
local-publish-alpha,连续发布2.1.7-alpha.0、2.1.8-alpha.0 - 此时 tags 正常:
{ alpha: '2.1.8-alpha.0', latest: '2.1.6' } - 在 Nexus UI 手动删除
2.1.8-alpha.0 - 再次查询 tags:
{ latest: '2.1.10-alpha.0' },alpha标签消失
根因分析
1. 发布脚本本身是正确的
local-publish-alpha 使用 --tag=alpha,按 npm 规范只会更新 alpha 标签,不会修改 latest。
若 alpha 发布流程正常执行,不应出现 latest 被 alpha 覆盖的情况。
2. Nexus 删除版本会错误重算 dist-tag(已知 Bug)
这是 Sonatype Nexus Repository 的已知问题:
- Issue :Cleanup policy changes latest tag on npm repository #437
- 触发条件:在 Nexus UI 手动删除任意版本,或通过 Cleanup Policy 自动清理
- 异常行为 :
- 若被删版本恰好是某个 tag(如
alpha)的指向目标,该 tag 会丢失 - Nexus 会自动重算
latest,按剩余版本中 semver 最高的来,不区分是否为 pre-release - 原有 tag 语义(alpha / latest 等)不会被保留
- 若被删版本恰好是某个 tag(如
与 npm 官方 Registry 的行为对比
| 操作 | npm 官方 Registry | Nexus |
|---|---|---|
publish --tag=alpha |
只更新 alpha,不动 latest |
正常 |
| 删除某个 alpha 版本 | 其他 tag 不受影响 | 会重算/污染 latest |
本次事件还原
发布 2.1.7-alpha.0、2.1.8-alpha.0
→ alpha: 2.1.8-alpha.0, latest: 2.1.6 ✓
Nexus UI 删除 2.1.8-alpha.0
→ alpha 标签丢失(指向版本已不存在)
→ Nexus 重算 latest → 指向 semver 最高的 2.1.10-alpha.0 ✗
修复方法
Nexus 限制:无法手动修改 latest tag
Nexus 禁止 通过 npm dist-tag add ... latest 修改 latest 标签。执行时会返回:
npm error 400 Bad Request - Unable to update latest tag
这是 Nexus 的有意设计(参见 Sonatype PR #83),与 npm 官方 Registry 行为不同。
| dist-tag 操作 | Nexus 是否支持 |
|---|---|
dist-tag add ... alpha |
✅ 支持 |
dist-tag add ... latest |
❌ 不支持(E400) |
dist-tag rm ... latest |
❌ 不支持 |
修正 latest 的唯一官方方式:重新 publish 一个稳定版 (不带 --tag,或显式 --tag=latest),Nexus 会将 latest 指向新发布的稳定版。
方案 A:发布新的稳定版(推荐)
bash
cd talos-explain-h5
# 1. 确保 package.json 版本为上一个稳定版(如 2.1.6),再执行正式发布
# 会自动 bump 到 2.1.7 并 publish,latest 将指向 2.1.7
npm run local-publish
# 2. 修复 alpha tag(此操作 Nexus 允许)
npm dist-tag add talos-explain-player@2.1.7-alpha.0 alpha \
--registry=https://nexus...
# 3. 验证
npm view talos-explain-player dist-tags \
--registry=https://nexus...
期望结果:
json
{
"latest": "2.1.7",
"alpha": "2.1.7-alpha.0"
}
方案 B:不 bump 版本,清理污染版本后重建
若不想发布新稳定版,可尝试:
bash
# 1. 在 Nexus UI 删除污染 latest 的 alpha 版本(如 2.1.10-alpha.0)
# ⚠️ 删除后 Nexus 可能再次错误重算 latest,需配合后续步骤
# 2. 重新 publish 目标稳定版(需本地 checkout 到该版本代码并 build-prod)
# 若该版本已存在,npm 会拒绝重复 publish,此路可能走不通
# 3. 或联系 Nexus 管理员执行 "Rebuild npm Metadata" 定时任务
方案 B 不稳定,优先使用方案 A。
修复 alpha tag(可单独执行)
alpha 等非 latest 的 tag 可以正常修改:
bash
npm dist-tag add talos-explain-player@2.1.7-alpha.0 alpha \
--registry=https://nexus...
废弃而非删除的版本
若 2.1.10-alpha.0 为误发或废弃版本,优先使用 deprecate 标记(不要在 Nexus UI 删除):
bash
npm deprecate talos-explain-player@2.1.10-alpha.0 "已废弃,请使用 alpha tag 对应版本" \
--registry=https://nexus...
注意 :在 Nexus UI 物理删除版本会触发 dist-tag 重算 Bug,且
latest无法通过dist-tag手动修复,形成死循环。强烈建议用 deprecate 代替删除。
最佳实践
发布规范
-
正式版 走
local-publish,测试版走local-publish-alpha,不要混用 -
发布后用
npm view talos-explain-player dist-tags确认 tag 状态 -
建议在
local-publish中显式指定--tag=latest,避免歧义:json"local-publish": "npm version patch && npm run build-prod && npm publish --registry https://nexus..."
版本管理规范
- 禁止在 Nexus UI 直接删除 npm 包版本 ;改用
npm deprecate标记废弃 - 若必须删除,需通过重新 publish 稳定版 来修正
latest(无法用dist-tag add latest) - 检查 Nexus hosted 仓库的 Cleanup Policy,评估是否会触发同类问题
安装规范
-
开发环境使用
@alpha,生产环境使用@latest -
部署前执行 dist-tags 检查,确认
latest未指向 pre-release 版本:bashnpm view talos-explain-player dist-tags --registry=https://nexus.xkw.cn/repository/xkw-npm/
常用排查命令
bash
# 查看 dist-tags
npm view talos-explain-player dist-tags --registry=https://nexus...
# 查看所有版本
npm view talos-explain-player versions --json --registry=https://nexus...
# 查看指定 tag 对应的版本
npm view talos-explain-player@latest version --registry=https://nexus...
npm view talos-explain-player@alpha version --registry=https://nexus...
# 手动设置 tag(alpha 等非 latest tag)
npm dist-tag add talos-explain-player@<version> alpha --registry=https://nexus...
# ⚠️ 以下命令在 Nexus 上会失败(E400 Unable to update latest tag)
# npm dist-tag add talos-explain-player@<version> latest --registry=...
# 删除 tag
npm dist-tag rm talos-explain-player <tag> --registry=https://nexus...
参考资料
- Sonatype Nexus Issue #437 - Cleanup policy changes latest tag
- Sonatype Nexus Issue #382 - npm tags in group repositories
- npm dist-tag 官方文档
变更记录
| 日期 | 说明 |
|---|---|
| 2026-05-23 | 初版:整理 alpha 发布、Nexus 删包导致 dist-tag 异常的问题与修复方案 |