如题,对于开发者而言,这可能是最预料不到和最诡异的事情,此Bug不知道多少小伙伴正在坑里,因为它来自当前最新版本 Vite(<= 5.4.11)和其依赖 rollup(<= 4.27.2),以下为最简复现 Demo:
<template>
<div>
<el-button @click="onTest('get')">测试 - get</el-button>
<el-button @click="onTest('post')">测试 - post</el-button>
</div>
</template>
<script setup lang="ts">
const onTest = (method: string) => {
const opt = method === 'get' ? { get: true } : { get: false }
// 这行代码中的逻辑判断,完全是从 opt 赋值语句中复制下来的
console.log(`method=${method},此时 opt 应该是:`, method === 'get' ? { get: true } : { get: false })
// 打印一下 opt 的实际值
console.log(`method=${method},此时 opt 最终是:`, opt)
}
</script>
以上代码很简单,当我点击 测试 - get 和 测试 - post,输出应该是:
# 点击 "测试 - get" 按钮
method=get,此时 opt 应该是: { get: true }
method=get,此时 opt 最终是: { get: true }
# 点击 "测试 - post" 按钮
method=post,此时 opt 应该是: { get: false }
method=post,此时 opt 最终是: { get: false }
在开发环境中,这一切正常,但是在编译后的生产环境中,它的输出是:
# 点击 "测试 - get" 按钮
method=get,此时 opt 应该是: { get: true }
method=get,此时 opt 最终是: { get: true }
# 点击 "测试 - post" 按钮
method=post,此时 opt 应该是: { get: false }
method=post,此时 opt 最终是: {}
如果你在仔细看一遍上面的 Demo,你就会发觉这代码的执行结果离谱到了什么程度:
opt的实际值与预期不符,应该同开发环境和开发者想要的结果一致,也就是{ get: false }console.log和opt的赋值语句完全一致,但是log中的值是{ get: false },赋值结果却是{},同一个赋值语句,数据未变,执行结果却变了!
排查
以上是最简复现 Demo,实际上的代码肯定复杂很多,作为一个合格的开发者,肯定是优先怀疑自己的问题,多次修改和确认传参->重新编译无果后,开始打断点和重写代码,你猜猜他们把代码编译成了什么样子?
const o = (t) => {
const e = t === 'get' ? { get: !0 } : {}
console.log(`method=${t},此时 opt 应该是:`, t === 'get' ? { get: !0 } : { get: !1 })
console.log(`method=${t},此时 opt 最终是:`, e)
}
是的,编译产物中,不等于 get 时,直接赋值 {},这完全背离了原代码的逻辑,神奇的是在 log 中它是正常的...
解决
- 目前确定这个Bug是在使用三元运算符时才会发生,如果使用多行的
if else则不会有问题,所以最简单的办法是修改代码,但是三元运算符并不方便全局搜索和替换,只能继续寻找原因 - Bug是最近突然产生的,在前几天还正常,今天的编译结果却出了问题,优先怀疑依赖问题,但是项目的依赖全部指定了固定版本(没有使用
~ ^ < >=等符号,直接指定了固定版本),但是还有一种可能,依赖的依赖没有固定版本
首先找到正常时期的 pnpm-lock.yaml 文件,复制过来,利用 BuildAdmin 内置的WEB终端快速安装依赖和重新发布,测试结果回归正常!
虽然正常了,但是笔者任想寻根究底,因为不习惯使用以前的 pnpm-lock.yaml 虽然很多开源仓库和项目部署都有上传这个文件,以保证依赖一致,但是它的内容总是被自动修改,是一个令人不喜的文件(笔者为开源作者,部署时任然建议上传它)。
接下来,使用针对此问题秘制的 pnpm-lock.yaml 分析工具,对出问题和不出问题的 pnpm-lock.yaml 进行分析对比,找到了一个比较明显的依赖,立刻找一个它次级版本固定起来测试
重新编译后,代码执行结果回到了我预想的样子,看来罪魁祸首就是它,再检查一下 Vite 的代码仓库,果然并未固定版本,欢迎有时间的大佬上去提交 PR,当然最好是向 rollup 提交修复这个 bug 的 PR,最后,如果以上内容有帮助到你,笔者在此邀请你使用我倾心打造的开源后台管理系统 BuildAdmin,内置WEB终端,支持可视化CRUD,非常棒!