pnpm 中,为什么node_modules/.pnpm里出现2个pinia库

问题:

  1. pnpm项目中,为什么node_modules/.pnpm里出现2个pinia库,如pinia@2.3.1_typescript@5.8.2_vue@3.5.13pinia@2.3.1_typescript@4.9.5_vue@3.5.13
  2. 在业务代码中,2个不同的package都引用了pinia(一处初始化、一处使用createStore)。开发时没有报错,但是构建发版后会报错(排查是pinia未初始化)。鼠标hover到pinia引用,显示实际路径不一致(即上一点的内容)

解决与原因

node_modules/.pnpm里为什么有多个pinia

在 pnpm 项目中,这种多个同名依赖但带有不同版本后缀的情况是正常现象,主要由以下原因造成:

  • peerDependencies 差异: 当同一个包(如 pinia)被不同依赖项使用时,如果这些依赖项声明了不同的 peerDependencies 版本(如 typescript 4.9.5 vs 5.8.2),pnpm 会为每个不同的 peerDependencies 组合创建独立安装实例

    1. Peer Dependencies 差异 pnpm 会通过 “版本哈希” 机制区分不同 peer dependencies 组合的包实例,即使主版本相同(如 Pinia 2.3.1),只要 peer dependencies 的版本要求不同,就会生成独立的安装目录
    2. 项目中存在多版本 TypeScript 依赖 根据你的 package.json,项目中直接依赖的 TypeScript 版本是 ^4.6.4 但可能存在其他依赖的子包通过 peer dependencies 要求不同版本的 TypeScript 例如:某个包可能要求 TypeScript >=4.9.5,而另一个包要求 TypeScript >=5.8.2 验证方法,检查间接依赖 使用 pnpm why 命令排查是否有间接依赖引入了额外的 TypeScript 版本要求
      # 查看 TypeScript 依赖树
      pnpm why typescript
       
      # 查看 Pinia 依赖关系
      pnpm why pinia
  • 版本锁定机制: 从您提供的依赖信息看,项目中直接声明的 pinia 版本是 2.1.7,但实际安装的 2.3.1 版本说明存在依赖升级,可能是其他子依赖间接引入了更高版本 工作区影响: 项目使用了 pnpm workspaces,不同子包可能声明了不同版本的 peerDependencies

    解决方案:

    # 1. 统一项目中的 typescript 版本(推荐升级到 5.x)
    pnpm up typescript@latest -w
     
    # 2. 强制重新构建依赖树
    pnpm install --force

该现象不会影响项目运行,pnpm 的符号链接机制会确保最终加载正确的依赖版本。如果要彻底消除多实例,需要统一所有子包的 peerDependencies 声明。

为什么构建时没有报错,但是运行时报错?

  1. 开发模式下,pnpm i 通过符号链接将多个实例通义映射到根node_modules,此时子包看到的pinia版本是统一的(因为pinia本身版本都一样,只不过peerDependencies中的typescript版本不一样)。因此运行时没有报错。
  2. 构建阶段,vite、rollup进行依赖分析时,会遵循实际物理路径,从而打包出2个pinia文件,进而运行时报错(初始化和创建store分别用了不同的pinia实例)。