news 2026/9/7 14:36:43

记一次 CI 构建事故:vant 把 `workspace:` 协议发布到了 npm,Jenkins 直接崩了

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
记一次 CI 构建事故:vant 把 `workspace:` 协议发布到了 npm,Jenkins 直接崩了

文章目录

    • 事故现场
    • 第一个疑问:项目里明明没有 workspace 依赖
    • 背景知识:`workspace:` 协议是什么
    • 复现与定位:二分法揪出"真凶"
    • 实锤:vant 把 monorepo 的协议发到了 npm
    • 科普:`^` 版本号到底是什么意思
      • 版本号三段式
      • `^`(caret,插入符)
      • 常见写法对照表
      • 正是 `^` 让我们"中招"
    • 解决方案
      • 第一步:锁定安全版本(立即止血)
      • 第二步:关注上游修复(后续跟进)
      • 第三步:治本——统一包管理器(长期建议)
    • 经验与反思

事故现场

2026-8-31早上,Jenkins构建突然失败:

npmERR!code EUNSUPPORTEDPROTOCOLnpmERR!Unsupported URL Type"workspace:":workspace:^npmERR!A complete log of this run can be found in: /home/jenkins/.npm/_logs/2026-08-31T02_47_51_131Z-debug-0.log

EUNSUPPORTEDPROTOCOLworkspace:^——npm 在安装依赖时遇到了一个它不认识的协议。

第一个疑问:项目里明明没有 workspace 依赖

我在项目里翻了个遍,没有任何workspace:痕迹:

  • package.jsonworkspace:协议
  • 没有pnpm-workspace.yaml
  • git 历史里从未出现过workspace:

关键线索是用户的一句话:“Jenkins 一直用 npm,上周是好的,今天突然报错。”

"上周好、今天坏"说明不是代码变了,而是外部依赖变了

背景知识:workspace:协议是什么

在 pnpm / Yarn 的 monorepo(多包仓库)里,workspace:^用来引用同仓库内的兄弟包

{"dependencies":{"@shared/utils":"workspace:^"}}

这个协议只有 pnpm / Yarn 认识,npm 完全不支持,解析时一撞上就抛EUNSUPPORTEDPROTOCOL

所以问题变成:npm 到底在解析哪个包时撞上了workspace:^

复现与定位:二分法揪出"真凶"

本地用临时目录 +npm install --dry-run(只解析不落盘)完整复现,确认依赖树确实无法用 npm 安装。然后用二分法把 20 多个依赖对半拆、逐个击破,很快锁定:

=== 问题依赖: vant (^4.10.0) === 单独安装该依赖: 失败

单独装一个vant都会失败——答案呼之欲出。

实锤:vant 把 monorepo 的协议发到了 npm

官方的issue链接: https://github.com/youzan/vant/issues/13911

对比vant两个版本:

vant@4.10.0(2026-06-28 发布):

{"@vant/use":"^1.6.0","@vue/shared":"^3.5.39","@vant/popperjs":"^1.3.0"}

vant@4.10.1(2026-08-30 发布):

{"@vant/use":"workspace:^","@vue/shared":"^3.5.42","@vant/popperjs":"workspace:^"}

真相大白:Vant 发布4.10.1时,把 monorepo 内部的workspace:^协议原封不动带到了 npm。项目声明"vant": "^4.10.0",npm 每次解析最新版,昨天才发的4.10.1今天就被拉到了。

时间线完全吻合:

时间事件
2026-06-28vant@4.10.0发布,依赖正常
2026-08-30vant@4.10.1发布,携带workspace:协议
2026-08-31Jenkinsnpm install命中4.10.1→ 报错

本地没炸是因为有pnpm-lock.yaml锁着vant@4.10.0;Jenkins 用 npm 且无 lock 文件,只能被最新版牵着走。

科普:^版本号到底是什么意思

版本号三段式

语义化版本(SemVer):主版本.次版本.补丁版本,如4.10.0

含义示例
主版本(major)不兼容的大改动5.0.0
次版本(minor)向后兼容的新功能4.11.0
补丁版本(patch)向后兼容的 bug 修复4.10.1

^(caret,插入符)

表示:允许更新次版本和补丁版本,但不允许跨越主版本

"vant": "^4.10.0" ⇔ >=4.10.0 且 <5.0.0

npm 会选范围内最新的版本,但绝不会碰5.0.0

常见写法对照表

写法含义命中范围
"vant": "4.10.0"精确锁定只有4.10.0
"vant": "~4.10.0"只允许补丁更新>=4.10.0 <4.11.0
"vant": "^4.10.0"允许次版本+补丁更新>=4.10.0 <5.0.0
"vant": "*"任意版本全部

正是^让我们"中招"

  • 项目写"vant": "^4.10.0"→ 允许4.10.x任意新版本
  • Vant 发4.10.1,满足^4.10.0范围
  • npm 无 lock 文件兜底,每次挑范围内最新版 → 命中带毒的4.10.1

解决方案

第一步:锁定安全版本(立即止血)

{"dependencies":{"vant":"4.10.0"// 由 ^4.10.0 改为精确锁定}}

去掉^,任何包管理器都不会再拉到带毒的4.10.1。提交后 Jenkins 重新构建即恢复。

第二步:关注上游修复(后续跟进)

等 Vant 发布4.10.2+修复版本后,再恢复^4.10.0或升级新版本。

第三步:治本——统一包管理器(长期建议)

项目 README 规定"必须使用 pnpm,禁止 npm / yarn",但 Jenkins 一直在用 npm。pnpm 有 lock 文件锁死版本,上游"带毒发布"也不受影响。建议 Jenkins 改为:

corepackenablepnpminstall--frozen-lockfilepnpmbuild:uat

经验与反思

  1. 版本声明与锁文件,缺一不可。^意味着"用范围内最新版",等于把命运交给上游;lock 文件的作用正是把范围冻结成具体版本。CI 环境必须有 lock 文件,否则任何一次上游发布都可能变成事故。
  2. 包管理器要"言行一致"。规范里写 pnpm,CI 却跑 npm,等于自己拆掉了锁文件这道防线。从本地到 CI 应全链路统一。
  3. “突然变坏"优先怀疑"变化的东西”。代码没改、上周还好,那变化的一定是外部因素——依赖版本、环境、镜像源。
  4. 二分法是依赖问题的利器。面对几十个依赖,对半拆解、逐个击破,比对着日志猜快得多。
  5. 大型生态的依赖也可能"带毒"。Vant 是老牌组件库一样会踩workspace:泄漏的坑,供应链上的任何一环都值得警惕。

事故不可怕,可怕的是没有锁版本。


🚀 感谢阅读!想了解更多?

📖 我的博客网站 | 记录思考,分享干货
🏡 我的个人主页 | 关于我、开源项目


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/5 9:04:42

基于51单片机的锂电池电量检测与充放电保护系统设计详解

简介&#xff1a;本资源面向电子类专业学生、嵌入式初学者及电池管理系统&#xff08;BMS&#xff09;实践开发者&#xff0c;提供一套覆盖锂电池检测、电量估算、充放电保护与均衡管理的完整51/52单片机工程方案。四套设计分别聚焦电压电流容量检测仪表、BMS均衡测试仪、仿真级…

作者头像 李华
网站建设 2026/9/2 22:56:14

yazi 剪贴板方案解析:三步搞定终端与 SSH 远程的复制粘贴

yazi 剪贴板方案解析&#xff1a;三步搞定终端与 SSH 远程的复制粘贴 【免费下载链接】yazi &#x1f4a5; Blazing fast terminal file manager written in Rust, based on async I/O. 项目地址: https://gitcode.com/GitHub_Trending/ya/yazi yazi 是用 Rust 编写的终…

作者头像 李华
网站建设 2026/9/5 23:19:48

ROS2仿真环境下SLAM算法对比:从环境搭建到性能评估

简介&#xff1a;本资源是一套面向机器人方向本科生与研究生的ROS2-SLAM算法对比仿真实践包&#xff0c;适用于毕业设计、课程设计及期末大作业等教学场景&#xff0c;旨在解决SLAM算法在ROS2环境下部署、测试与性能评估的学习痛点。压缩包共476个文件&#xff08;85.1MB&#…

作者头像 李华
网站建设 2026/9/5 22:41:34

随机子空间识别(SSI)的MATLAB实现与工程实践指南

简介&#xff1a;本资源是一套面向结构动力学与模态分析领域的工程技术人员及高校研究者的随机子空间&#xff08;SSI&#xff09;算法MATLAB实现代码&#xff0c;专用于从实测响应数据中稳健提取固有频率、阻尼比和模态振型等关键模态参数&#xff0c;广泛适用于桥梁健康监测、…

作者头像 李华
网站建设 2026/9/5 18:33:49

Zod 数据验证实践:从订单字段到接口解析,三个场景完成上手

Zod 数据验证实践&#xff1a;从订单字段到接口解析&#xff0c;三个场景完成上手 【免费下载链接】zod TypeScript-first schema validation with static type inference 项目地址: https://gitcode.com/GitHub_Trending/zo/zod 周五晚上的一次线上告警&#xff1a;聊天…

作者头像 李华
网站建设 2026/9/6 9:01:05

Logseq DB 版本指南:如何把你的笔记搬进实时协作知识库

Logseq DB 版本指南&#xff1a;如何把你的笔记搬进实时协作知识库 【免费下载链接】logseq A privacy-first, open-source platform for knowledge management and collaboration. Download link: http://github.com/logseq/logseq/releases. roadmap: https://logseq.io/p/NX…

作者头像 李华