pnpm v8版本升级变化关注点(前瞻速攻版)

news/2024/10/31 1:22:53/

前言

pnpm v8.0.0-alpha.0 版本已经发布,包含少量变化,但其中还是有令人在意的点的。

本文将默认读者拥有大部分 pnpm v7 版本的知识储备,进行 v8 版本的前瞻速攻。

安装方法

目前通过指定 Tag 方式可以安装 v8 alpha 版:

  npm i -g pnpm@next-8

所有 Tag 详见:npm > pnpm version

由于距 pnpm v8 正式发布还有一段距离( alpha > beta > latest ),本文可能存在部分内容过时,请仔细甄别。

从 v6 升级至 v7

本文是 v7 升级 v8 ,若你需从 v6 升级,可先参考 :

  • 聊聊 pnpm v6 升 v7 拥抱的变化和经验谈

正文

下面对 changelog 逐条分析。

auto-install-peers is true by default

在 pnpm v7 版本之初,strict-peer-dependencies 是默认打开的,这会导致不安装 peerDependencies 就会安装报错(除非打开 auto-install-peers),引发了大量社区反馈,极大降低了 pnpm 的易用性,我们在 v6 升级 v7 的文章中也推荐设定 strict-peer-dependencies=false 避免不必要的报错问题。

所以 strict-peer-dependenciesv7.13.5 又调整回默认 false

v7 的计划失败了,到了 v8 ,可以看出 pnpm 希望通过默认打开 auto-install-peers=true 的方式解决 peerDependencies 的问题,但这会导致在本地 package.json 中的 peerDependencies 也被安装,一个例子如下:

// package.json
{"peerDependencies": {"react": "^18"}
}

此时我们不期望 react 被安装,因为我们没有在 dependencies / devDependencies 指明安装他,但由于 auto-install-peers 被默认打开,最终仍然会安装 react

进一步,在实际业务中,分情况考虑可能造成的影响:

  1. 普通场景:在本地开发时,按照开发规范,我们必然对 peerDependencies 的依赖也在 devDependencies 指定一份,但不在 dependencies 指定,所以该依赖是肯定会被安装的,auto-install-peers 不会对我们造成影响。

  2. monorepo 场景:在 monorepo 时我们有 Monorepo丝滑方法论 ,依赖总唯一,所以无需担心 auto-install-peers 问题。

通过分析我们得知 auto-install-peers=true 默认打开一般情况对我们没有实质性影响。

下面我们举两个会存在问题的 case 供参考:

  1. npm link 调试等情况,导致 peerDependencies 被意外安装,但 npm link 早已过时不再使用,这种情况是很少见的。

  2. 不遵守 npm 包开发规范,导致 peerDependencies 被意外安装,我们也不展开该极少数的情况。

由于 auto-install-peers 几乎不会对我们造成影响,加上使用包管理工具应该向 零配置 靠拢,本文不再推荐手动关闭 auto-install-peers 该选项,而是拥抱变化,若有极少数的特殊需求,你可能需要关闭该行为:

// .npmrc
auto-install-peers=false

The registry field is removed from the resolution object in pnpm-lock.yaml

lock 文件层面格式的优化,对我们使用没有直接影响,可以忽略。

save-workspace-protocol is rolling by default

save-workspace-protocol 决定了在 pnpm monorepo 中,手动安装工作区内同名包的版本添加行为:

  pnpm add foo

如我们的 workspace 含有 foo 该包,在 v7 我们安装该包得到的是:

  "foo": "workspace:^1.0.0"

现在 v8 默认 rolling 策略得到的将是:

  "foo": "workspace:^"

由于我们极少在工作区内手动运行安装同名包的命令,往往是手动添加 workspace 内的其他包,并且使用 * 格式:

// package.json// 手动添加要使用的 monorepo 内其他包"foo": "workspace:*"

所以此变化不会影响我们的使用,可以忽略。

When there’s a files field in the package.json, only deploy those files that are listed in it

该命令涉及到 pnpm deploy 相关,由于 prune 功能还不够成熟,考虑到没有得到 nextjs 示例项目的推荐,我们几乎不会使用,可以忽略。

Use lockfile v6 by default

v6 是 pnpm 的下一个大版本的 lockfile 格式,目前格式版本是 5.4

// pnpm-lock.yaml
lockfileVersion: 5.4// ...
// pnpm-lock.yaml (pnpm v8)
lockfileVersion: '6.0'// ...

6.0 lockfile 格式相比 5.4 有 80% 内容基本一致,变化主要集中在对依赖的 版本描述 上,以下给出一个大致的 demo :

// old 5.4/@ant-design/colors/6.0.0:resolution: { ... }dependencies:'@ctrl/tinycolor': 3.4.0
// new 6.0registry.npmjs.org/react@18.0.0:resolution: { ... }name: reactversion: 18.0.0engines: {node: '>=0.10.0'}dependencies:loose-envify: ...dev: true

可以看出 6.0 新版 lockfile 对依赖的描述从 单行 变成了 多行 ,但对我们实际使用没有影响,运行 pnpm i 刷新 lock 文件即可,该变化可以忽略。

注:pnpm 早在 v7.24.2 就预先放出了该 6.0 lockfile 版本的配置项,同时官方仓库也第一时间使用了 6.0 新版 lockfile 格式,没有 Breaking change ,可以放心使用。

resolve-peers-from-workspace-root is true by default

resolve-peers-from-workspace-root 该选项主要用来解决 monorepo peerDependencies 困境 问题,当多子包需要同一个 peerDependencies 时,无需手动配置提升,而是在 root 安装唯一的该依赖,即可保证全局唯一性。

但提升至 root 只适合要求的版本范围全部匹配,可以唯一提升的依赖,不支持精细版本控制,同时会污染 monorepo 根 root ,造成不必要的隐形全局依赖和心智负担,我们在 Monorepo管理方法论和依赖安全 中明确指出 严禁安装 monorepo 全局依赖 ,故此选项不推荐使用,同时我们有 Monorepo丝滑方法论 实现更好的 monorepo 多实例解法,轮不到 resolve-peers-from-workspace-root 发挥作用,可以忽略该变化。

需要注意的是, Monorepo丝滑方法论 往往和框架挂钩,对于小型 monorepo 项目,若支持不了 丝滑方法论 的实现,可以勉强接受 resolve-peers-from-workspace-root 这种解决 peerDependencies 困境的方法。

publishConfig.linkDirectory is true by default

随着 package.json#exports 的流行,更多的项目会采用非根发布 npm 包(如 jotai 等),publishConfig.linkDirectory 是对于此类项目的优化支持,不会直接影响到我们的使用,可以忽略。

resolution-mode is lowest-direct by default

近年 npm 供应链攻击的 case 偶然发生,目前比较好的 被动 管控手法有:

  1. 预打包依赖:参考 Nextjs / Umi 预打包策略,实现略。

  2. pnpm time-based :time-based 策略可以基于包的最后发布时间来确保你使用的依赖在某个发布时间前,从而规避供应链发新包导致的攻击问题,但对于非自建 npm registry 需要花费更多时间读取 npm 包元信息,目前 pnpm 官方采用此策略,此处不做展开。

  3. pnpm lowest-direct :lowest-direct 是另一种 pnpm 推出的 缓解 供应链攻击的手段,他等价于锁定你的直接依赖版本(解析为 semver 的最低依赖版本),比如 ^1.0.0 也只会安装 1.0.0 最低版本,而不是最新的 ^1 版本,这等价于你锁定该依赖到 1.0.0 ,若你需要 1.2.0 版本也需要写为 ^1.2.01.2.0 ,该行为可以从一定程度上 缓解 供应链发新包导致的攻击,也不会承受 time-based 策略拉取 npm 元信息造成的依赖安装变慢。

默认 lowest-direct 策略后,我们可以直接性的 缓解 供应链攻击造成的影响,即使在没有 lock 文件时也可以每次都安装到确定的依赖版本。

但相应的成本是:必须显示的提升依赖版本号来做依赖升级,否则无法安装到最新版本,使用解析到的最低版本极有可能遭受未知的 bug ,从而浪费大量排查时间,请在使用 pnpm v8 时格外注意手动升级依赖至最新版本防止未知的 bug

Direct dependencies are deduped. So if the same dependency is both in a project and in the workspace root, then it is only linked to the workspace root

该变动是为了配合 resolve-peers-from-workspace-root 的行为,忽略即可。

Create a lockfile even if the project has no dependencies at all

对我们没有直接影响,忽略。

总结

通过分析 pnpm v8 alpha 的变化我们发现,只要遵守 pnpm v7 我们总结出来的 monorepo 方法论:

  • Monorepo 丝滑方法论:引用模块热更新

  • Monorepo 管理方法论和依赖安全

从 v7 升级至 v8 是几乎无损、水到渠成顺利的。

另外,请留意在 v8 状态下你的依赖是 锁定等价 的最低版本,请定期升级版本防止不必要的 bug ,并在出现 bug 时升级依赖排查。

若你需要进一步了解 monorepo ,提供如下内容参考:

  • monorepo 工作流基础之 changesets 打开与进阶(Speeches)

  • pnpm monorepo 的技术选型临界点(Critical adoption)

  • Monorepo 设计思路(Speeches)

  • turborepo v1.2.0版本升级指南

以上。


http://www.ppmy.cn/news/26857.html

相关文章

MySQL删除或清空表内数据的方法

MySQL删除或清空表内数据的方法 一、使用MySQL清空表数据命令:truncate SQL语法为: truncate table 表名注意: truncate该命令会直接将数据表内数据清空;truncate该命令删除数据后会重置Identity(标识列、自增字段…

简明易懂的JVM理解

文章目录简明易懂的JVM和GC理解写在前面Java虚拟机(JVM)的组成基本介绍结构类加载子系统(ClassLoader SubSystem)介绍类加载过程类加载过程小结双亲委派模型(Parent-Delegation Model)简介优点Java9的类加载的委派关系变动双亲委派模型小结运行时数据区(Runtime Data Areas)介绍…

Java——无重叠区间

题目链接 leetcode在线oj题——无重叠区间 题目描述 给定一个区间的集合 intervals ,其中 intervals[i] [starti, endi] 。返回 需要移除区间的最小数量,使剩余区间互不重叠 。 题目示例 输入: intervals [[1,2],[2,3],[3,4],[1,3]] 输出: 1 解释…

线程池种类和拒绝策略

1、newCachedThreadPool():可缓存的线程池,核心线程数量为0,最大线程数量为INT_MAX。线程空闲时间超过60秒被回收。适合处理大量小任务。 2、newFixedThreadPool()。固定线程个数的线程池,线程都是核心线程,没有应急线…

MyBatis-XML映射文件详解

一、XML 映射器 1.概述 使用 xml 文件去配置 SQL 代码,比传统的 jdbc 简单方便,能够少写代码,减少使用成本,提高工作效率。 1.1SQL 映射文件中的顶级元素 cache – 该命名空间的缓存配置。 cache-ref – 引用其它命名空间的缓…

spring boot——自定义依赖实现自动配置

需求 要实现的功能是:实现一个可以支持miniooss两种方式,上传下载文件的自定义依赖。其中还包括一些创建桶、删除桶、删除文件等功能,但是最主要的是实现自动配置。 如果对spring理解很深的话,自动配置这些东西很容易理解&#…

Java数据结构中链表分割及链表排序使用快速排序、归并排序、集合排序、迭代、递归,刷题的重点总结

本篇主要介绍在单链表进行分割,单链表进行分隔并使用快速排序、归并排序、集合排序、迭代、递归等方法的总结,愿各位大佬喜欢~~ 86. 分隔链表 - 力扣(LeetCode) 148. 排序链表 - 力扣(LeetCode) 目录 一…

C++调用Python脚本进行18次循环操作后,脚本不执行

C调用Python脚本进行18次循环操作后,脚本不执行 现象: 发送端接收端 从第二张图中可以看出,python脚本卡在’[parkin_debug] 6’与’[parkin_debug] 7’之间 该测试经过多次反复测试,均在第18次循环执行时,出现上述问…