Verdaccio publish 时包含 deprecated 导致历史版本丢失问题原因分析

背景

公司内部的 NPM 因为一些固有的 bug 经常被吐槽,最近刚好有时间可以来做优化,然后就尝试解一下之前遇到的一个 publish 的 bug,下边是分析记录。

问题现象

公司内网 NPM 选择的是使用 verdaccio 来做服务,目前遇到了一个模块 publish 时包含 deprecated 字段导致历史版本丢失,仅剩下本次 publish 的版本信息。

问题原因

NPM CLI 实现 deprecate 的时候流程是这样的:
https://github.com/npm/cli/bl...

  1. 请求 get 接口获取当前模块的信息
  2. 然后修改符合的版本 deprecated 字段
  3. 请求 put 接口更新模块

然后新增模块在 CLI 的实现是:
https://github.com/npm/libnpm...

  1. 读取本地 package.json 内容
  2. 请求 put 接口上传模块

Verdaccio 在实现 server 的时候,更新模块和上传模块是同一个服务接口,两个动作之间又没有处理好:https://github.com/verdaccio/...

此部分逻辑为 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": {}
  }
}

而两者在服务端的处理逻辑是一样的:

  1. storage 修改对应的版本信息
  2. 过滤移除失效的版本信息(比如这里就会把 1.0.0、1.0.1 的信息移除)
  3. 使用当前 metadata 覆盖原有的 package.json 信息

最终导致如果 publish 的时候 package.json 中包含 deprecated 参数则会出现历史版本丢失的情况。

修复方式

修复方式也比较简单,其实主要就是能够区分出当前接口触发是 deprecate 导致的还是 publish 导致的就可以了。
那么我们就通过手动读取一次当前模块的 versions 信息,然后对比本次接口触发时接收到的 metadata,如果是 publish,那么这里一定不会匹配上的。
那么就可以在触发 deprecated 的时候新增一个检测,检测是否为 publish 时携带了 deprecated,这种情况直接忽略,进入原有的新模块上传流程。

问题总结

总结来说,deprecated 字段更像是一个 NPM 内部约定的字段,而非一个需要使用者写到 package.json 中的显性字段,如果需要对版本添加废弃信息,请用官方推荐的方案:https://doc.codingdict.com/np...

以及已经把 PR 提给官方了,期待一波回复:https://github.com/verdaccio/...


全沾开发(huā)
各种前端相关&Node.js

GitHub: [链接]

5k 声望
4.7k 粉丝
0 条评论
推荐阅读
手把手教你写一份优质的前端技术简历
不知不觉一年一度的秋招又来了,你收获了哪些大厂的面试邀约,又拿了多少offer呢?你身边是不是有挺多人技术比你差,但是却拿到了很多大厂的offer呢?其实,要想面试拿offer,首先要过得了简历那一关。如果一份简...

tonychen153阅读 17.9k评论 5

封面图
正则表达式实例
收集在业务中经常使用的正则表达式实例,方便以后进行查找,减少工作量。常用正则表达式实例1. 校验基本日期格式 {代码...} {代码...} 2. 校验密码强度密码的强度必须是包含大小写字母和数字的组合,不能使用特殊...

寒青57阅读 8.6k评论 11

JavaScript有用的代码片段和trick
平时工作过程中可以用到的实用代码集棉。判断对象否为空 {代码...} 浮点数取整 {代码...} 注意:前三种方法只适用于32个位整数,对于负数的处理上和Math.floor是不同的。 {代码...} 生成6位数字验证码 {代码...} ...

jenemy49阅读 7.3k评论 12

再也不学AJAX了!(二)使用AJAX ① XMLHttpRequest
「再也不学 AJAX 了」是一个以 AJAX 为主题的系列文章,希望读者通过阅读本系列文章,能够对 AJAX 技术有更加深入的认识和理解,从此能够再也不用专门学习 AJAX。本篇文章为该系列的第二篇,最近更新于 2023 年 1...

libinfs42阅读 7k评论 12

封面图
CSS 绘制一只思否猫
欢迎关注我的公众号:前端侦探练习 CSS 有一个比较有趣的方式,就是发挥想象,绘制各式各样的图案,比如来绘制一只思否猫?思否猫,SegmentFault 思否的吉祥物,是一只独一无二、特立独行、热爱自由的(>^ω^&lt...

XboxYan48阅读 3.3k评论 14

封面图
「多图预警」完美实现一个@功能
一天产品大大向 boss 汇报完研发成果和产品业绩产出,若有所思的走出来,劲直向我走过来,嘴角微微上扬。产品大大:boss 对我们的研发成果挺满意的,balabala...(内心 OS:不听,讲重点)产品大大:咱们的客服 I...

wuwhs32阅读 3.5k评论 5

封面图
还在用 JS 做节流吗?CSS 也可以防止按钮重复点击
举个例子:一个保存按钮,为了避免重复提交或者服务器考虑,往往需要对点击行为做一定的限制,比如只允许每300ms提交一次,这时候我想大部分同学都会到网上直接拷贝一段throttle函数,或者直接引用lodash工具库

XboxYan35阅读 2.7k评论 2

封面图

GitHub: [链接]

5k 声望
4.7k 粉丝
宣传栏