pnpm 的介绍

引用官方的话:

节约磁盘空间并提升安装速度

关键技术点

软硬链接

pnpm 的高效来自于硬链接,是指:新建的文件是已经存在的文件的一个别名,当原文件删除时,新建的文件仍然可以使用,只当所有文件都删除了,才算是真正的删除。

软链接:也称为符号链接,新建的文件以“路径”的形式来表示另一个文件,和 Windows 的快捷方式十分相似,新建的软链接可以指向不存在的文件.
(或者是 npm link 通过一个符号,比如:vue 然后执行一个映射仓库的脚本 vue script 类似执行某个脚本)

引用自:
https://www.cnblogs.com/itech/archive/2009/04/10/1433052.html

与 monorepo 的配合

monorepo 与 multirepo 的优缺点

pnpm 的 monorepo 在 CI/CD 的优点,不用频繁的切换目录就可以使用特定包专属的命令 pnpm -F 可以直接在根目录就实现调用任意命令。

monorepo 的优点:

  1. 统一工作流
    由于所有的项目放在一个仓库当中,复用起来非常方便,如果有依赖的代码变动,那么用到这个依赖的项目当中会立马感知到。并且所有的项目都是使用最新的代码,不会产生其它项目版本更新不及时的情况,对开发调试而言都带来了方便。

  2. 降低基建成本
    所有项目复用一套标准的工具和规范,无需切换开发环境,如果有新的项目接入,也可以直接复用已有的基建流程,比如 CI 流程、构建和发布流程。这样只需要很少的人来维护所有项目的基建,维护成本也大大减低降低基建成本。

  3. 提升团队协作效率
    一方面大家都在一个仓库开发,能够方便地共享和复用代码,方便检索项目源码,另一方面,git commit 的历史记录也支持以功能为单位进行提交,之前对于某个功能的提交,需要改好几个仓库,提交多个 commit,现在只需要提交一次,简化了 commit 记录,方便协作。

monorepo 的缺点:

  1. 权限问题
    Monorepo模式下的权限是开放的。代码安全,文档安全,都会是一个需要好好考虑的问题。这个方面如果处理不好的话,对整个团队整个项目带来的后果可能是灾难性的。

  2. 体积问题
    因为所有code都在一个repo下,这就导致了随着项目越来越复杂,整个repo的体积会变得很大。

  3. 版本控制
    仓库变得太大,对版本控制技术会有很大的挑战。因为 Git 社区建议的是使用更多更小的代码库,Git 本身并不适合单个巨大的代码库。
    需要团队成员的git水平较高。尤其是多个子包同时修改的 commit 是不太建议,因为这不利于回滚。

实操

  1. 按照以下的方式去创建项目
├── package.json
├── packages
|  ├── utils
|  |  ├── package.json
|  └── vue3-ts-practise
|     ├── package.json
└── pnpm-workspace.yaml

packages 里放的都是子包。其中包含主项目 vue3-ts-practise 与 工具函数 utils 包

  1. 然后 pnpm-workspace.yaml 的内容如下:
packages:
  - "packages/*"

意思是:所有的包都在 packages 子目录里,方便 pnpm 识别并后续添加依赖用的

安装依赖

  1. 全局依赖

pnpm add xxx -w

devDependency
pnpm add xxx -wD

  1. 子包依赖

pnpm -F @xxx 包 add 依赖 xxx

package 之间如何引用

// (@* 是指最新版本,这样子包版本改了,也不用重新引入)
pnpm -F @xxx 包 add @xxx 包@*

通过 jsconfig.json 和 tsconfig.json 配置,方便 package 之间的跳转

如下:

"compilerOptions":{
    "paths": {
      "@jjlau/utils": ["../utils"]
    }
  }

分包的思路

TBD

常见命令

与 lerna.js 的对比

  1. lerna 需要额外下载这个依赖,而 pnpm 不需要

TBD

与 TreeShaking 的搭配

安全问题

pnpm 解决了 非法访问依赖 的问题,也就是只要一个包未在 package.json 中声明依赖,那么在项目中是无法访问的。

而 npm 与 yarn 的依赖提升会出现该安全问题。

比如:

在 monorepo 项目中,如果 A 依赖 X,B 依赖 X,还有一个 C,它不依赖 X,但它代码里面用到了 X。由于依赖提升的存在,npm/yarn 会把 X 放到根目录的 node_modules 中,这样 C 在本地是能够跑起来的,因为根据 node 的包加载机制,它能够加载到 monorepo 项目根目录下的 node_modules 中的 X。但试想一下,一旦 C 单独发包出去,用户单独安装 C,那么就找不到 X 了,执行到引用 X 的代码时就直接报错了。

问题集合(坑)

  1. 子包的 package.json 中的依赖没有办法通过 vscode 的提示快速生成 import 语句,但是可以引入根目录的依赖

相关文章的引用

  1. https://juejin.cn/post/7115058575801581605

  2. https://juejin.cn/post/6932046455733485575

  3. https://pnpm.io/zh 官方文档



pnpm monorepo

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!