背??景公司内部的NPM经常因为一些固有的bug而被吐槽。最近刚好有时间优化一下,然后尝试解决之前遇到的一个publish问题。bug,下面是分析记录。问题现象公司内网NPM选择使用verdaccio作为服务。目前发布模块时,包含deprecated字段,导致历史版本丢失,只留下本次发布的版本信息。问题原因npmcli实现deprecate时的流程如下:https://github.com/npm/cli/bl...请求get接口获取当前模块的信息,然后修改deprecated字段对应版本请求put接口更新模块然后在CLI中实现新模块是:https://github.com/npm/libnpm...读取本地package.json的内容并请求上传模块的put接口。Verdaccio实现服务端时,更新模块和上传模块是同一个Service接口,这两个action处理不当:https://github.com/verdaccio/...这部分逻辑被弃用处理逻辑: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"//ifany},}}如果你直接调用npmdeprecatemodule_name@1.0.0"xxx",服务收到的数据就像this:{"name":"module_name","version":{"1.0.0":{"deprecated":"xxx"//ifany},"1.0.1":{}}}的处理逻辑两者在服务端是一样的:存储修改对应版本信息过滤去除无效的版本信息(比如这里会去除1.0.0和1.0.1信息),用当前元数据覆盖原来的package.json信息,最终会导致package.json在发布参数时包含deprecated,历史版本会丢失。修复方法修复方法也比较简单。其实主要是能够区分当前界面触发是deprecate还是publish引起的。然后我们手动读取当前模块的版本信息,然后比较触发这个接口时收到的元数据。如果发布了,那么这里肯定是匹配不到的。然后可以在触发deprecated时添加新的检测,在发布时检测是否被deprecated。这种情况直接忽略,进入原来的新模块上传流程。问题总结综上所述,deprecated字段更像是npm内部约定的字段,而不是需要用户在package.json中写入的显式字段。如果需要在版本中添加弃用信息,请使用官方推荐的解决方案:https://doc.codingdict.com/np...并且PR已经提交给官方,期待一波回复:https://github.com/verdaccio/...
