Verdaccio|Verdaccio publish 时包含 deprecated 导致历史版本丢失问题原因分析
背景
公司内部的 NPM 因为一些固有的 bug 经常被吐槽,最近刚好有时间可以来做优化,然后就尝试解一下之前遇到的一个 publish 的 bug,下边是分析记录。
问题现象
公司内网 NPM 选择的是使用 verdaccio 来做服务,目前遇到了一个模块 publish 时包含 deprecated 字段导致历史版本丢失,仅剩下本次 publish 的版本信息。
问题原因
NPM CLI 实现 deprecate 的时候流程是这样的:
https://github.com/npm/cli/bl...
- 请求 get 接口获取当前模块的信息
- 然后修改符合的版本 deprecated 字段
- 请求 put 接口更新模块
https://github.com/npm/libnpm...
- 读取本地 package.json 内容
- 请求 put 接口上传模块
此部分逻辑为 deprecated 处理逻辑:https://github.com/verdaccio/...
local-storage 处理逻辑:https://github.com/verdaccio/...
这里删除了无效版本的信息:https://github.com/verdaccio/...
举例场景,如果已经有一个模块存在 1.0.0、1.0.1 的版本,那么触发 publish 上传 1.0.2 版本的时候服务接收到的数据是这样的:
{
"name": "module_name",
"version": {
"1.0.2": {
"deprecated": "xxx" // 如果有的话
},
}
}
而如果直接调用 npm deprecate module_name@1.0.0 "xxx" 的时候服务接收到的数据是这样的:
{
"name": "module_name",
"version": {
"1.0.0": {
"deprecated": "xxx" // 如果有的话
},
"1.0.1": {}
}
}
而两者在服务端的处理逻辑是一样的:
- storage 修改对应的版本信息
- 过滤移除失效的版本信息(比如这里就会把 1.0.0、1.0.1 的信息移除)
- 使用当前 metadata 覆盖原有的 package.json 信息
修复方式 修复方式也比较简单,其实主要就是能够区分出当前接口触发是 deprecate 导致的还是 publish 导致的就可以了。
那么我们就通过手动读取一次当前模块的 versions 信息,然后对比本次接口触发时接收到的 metadata,如果是 publish,那么这里一定不会匹配上的。
那么就可以在触发 deprecated 的时候新增一个检测,检测是否为 publish 时携带了 deprecated,这种情况直接忽略,进入原有的新模块上传流程。
问题总结 总结来说,deprecated 字段更像是一个 NPM 内部约定的字段,而非一个需要使用者写到 package.json 中的显性字段,如果需要对版本添加废弃信息,请用官方推荐的方案:https://doc.codingdict.com/np...
以及已经把 PR 提给官方了,期待一波回复:https://github.com/verdaccio/...
推荐阅读
- 任时光绽放成六月繁花
- 一个人的碎碎念
- 昨夜小楼听风
- 20170612时间和注意力开销记录
- 远去的风筝
- 为什么你的路演总会超时()
- 杜月笙的口才
- 时间老了
- MediaRecorder前后摄像头同时录像
- 眉头开了