踩雷!pnpm10 升级后 Vue2.7+Pinia 要多写.value?根源 + 终极解
本文适配 Hexo,含 Front-matter。掘金版请见仓库 juejin-articles。
1. 痛点复盘:一升级就“全员 .value”
- Vue2.7 项目将包管理器从 pnpm8 → pnpm10 后,Pinia 的所有
state/getters使用处突然都需要.value才能工作; - 升级前(pnpm8)一切正常;
- 本地
node_modules下的 pinia 没有任何 “vue2” 专属文件或入口(找不到vue2相关目录), - 尝试过:修改
.npmrc、Pinia 降级、封装代理 等均无效。
结论:问题不在 Pinia 写法,而在包解析与入口选择。
2. 根源通俗解析:vue-demi 被 pnpm10“带偏了”
- Pinia 依赖 vue-demi 来判断当前项目到底是 Vue2 还是 Vue3,然后返回对应版本的 API。
- 在 pnpm10 的解析规则下,vue-demi 误判当前是 Vue3 环境,于是返回了 Vue3 版本的 API:
- Vue3 中
ref不会自动在模板/计算中解包,导致使用时需要.value; - 这就解释了为何升级后你在 Vue2.7 + Pinia 项目里到处都要写
.value。
- Vue3 中
- 升级前(pnpm8)因为解析差异,vue-demi 正常识别为 Vue2.7,因此**无需
.value**。
一句话:不是 Pinia 变了,是 vue-demi 在 pnpm10 下选错了入口。
3. 终极实操解:Vite 别名强绑 vue-demi → Vue2.7 专属入口
目标:强制让所有依赖使用 vue-demi 的 Vue2.7 入口,彻底修正误判。
关键思路:通过 Vite 的 resolve.alias,把 vue-demi 指向 Vue2.7 专属 build,让 Pinia 以及其它依赖都拿到正确的 API。
vite.config.js 完整片段(可复制):
1 | import { defineConfig } from 'vite' |
路径说明:
node_modules/vue-demi/lib/index.iife.js为示例路径,请在你的项目中确认vue-demi包内对 Vue2.7 兼容的构建文件位置:- 常见还包括:
lib/index-v2.js、lib/v2/index.mjs、lib/index.cjs等; - 只要该入口在源码中明确走 Vue2 分支即可(可打开文件搜
isVue2标识)。
- 常见还包括:
提示:如果你使用的是 monorepo 或者有多层
node_modules,务必确保 alias 指向的是项目最终运行时实际被解析的那一个路径。
4. 验证:无需 .value 的 Pinia 使用示例
重启本地服务后,随手在组件中验证:
1 | // stores/counter.ts |
1 | <!-- components/Demo.vue --> |
现象:模板中直接使用 counter.n、counter.double 正常工作,无需 .value。
5. 避坑说明:常规方案为什么不靠谱?
- 改
.npmrc/ 换解析策略:pnpm10 的整体解析行为变化较大,仅凭 npmrc 配置很难稳定影响到 vue-demi 的入口选择; - Pinia 降级:治标不治本,且可能带来其它依赖的兼容性问题;
- 封装代理(自己包装
.value):不仅侵入业务,还会牺牲可读性和可维护性。
本方案优势:
- 一招根治:直击根因(入口判断),从源头纠偏;
- 零业务代码修改:无需改任何组件或 store 代码;
- 不降级:保留 pnpm10 带来的性能和生态优势;
- 无副作用:只影响
vue-demi的解析位置,不改变其它模块行为。
6. 拓展:vue-demi 与 pnpm9+/10 的解析变化
- vue-demi:为同时兼容 Vue2 & Vue3 的库提供统一 API 封装,它会在安装/运行时根据环境决定导出哪个版本的实现;
- pnpm9+/10:包解析(尤其是依赖的入口与 peer 解析)更加严格与模块化,一些“隐式”依赖路径在旧版本下可用,升级后会触发分支错误。
因此在 Vue2.7 + Pinia 的组合下,手动通过 alias 锁定 vue-demi 的 Vue2.7 入口是最稳妥的工程化处理。
核心总结 + 避坑提示
- 升级 pnpm10 导致 vue-demi 误判为 Vue3 → Pinia 返回 Vue3 API → **必须
.value**; - 通过 Vite
resolve.alias强制把vue-demi指向 Vue2.7 兼容入口,即可恢复原有行为; - 发布前务必 清空缓存并重启(
rm -rf node_modules && pnpm i、pnpm dev),确认生效; - 避坑:不要靠随意降级或 Hack 业务代码,工程化锁定入口是终极解。