Yarn 3.0 Plug'n'Play (PnP) 安装和迁移

前言

以前用 npm, 后来 yarn 火了就用 yarn. 后来 yarn 2.0 大改版, Angular 不支持就一直没用.

一直到去年的 Angular 13 才开始支持. 最近又开始写 Angular 了, 所以来补上它吧.

这篇会讲到 Node.js v16 + Yarn 3 运行 TypeScript esbuild 和 Webpack 的例子. (刚好我之前有写过 WebpackTypeScript esbuild)

还有如何从 Yarn 1 升级到 Yarn 3 (我之前写的 Webpack 和 TypeScript esbuild 是用 Yarn 1 的) 

最后是 Angular 的例子.

 

一点点历史 npm, yarn, cnpm, pnpm

参考: 

主流包管理工具npm、yarn、cnpm、pnpm之间的区别与联系——原理篇

JavaScript package managers compared: npm, Yarn, or pnpm?

npm 是最早的, 很多问题, 后来

yarn 出现了, 解决了很多问题, 后来 

pnpm 出现了, 比 npm 和 yarn 都好

yarn 出现后, npm 也一直在进步.

pnpm 出现后, yarn 也一直在进步

cnpm 是 for china 的 npm, 只是这样而已

目前 yarn 1.x 是经典版 (classic) 已经没有在开发了, 但还是有维护

yarn 2.0 (berry 版) 时代是比较苦难的年代, 因为改版太大了, node_modules 直接没了. 所以很多 library 更不上.

yarn 3.0 才比较好一些. 这篇主要就是介绍这个.

 

Uninstall Yarn 1 and Node.js (npm)

Yarn 3 是搭配 Node.js 一套的, 为了测试我直接把 Yarn 1 和所有 Node.js, npm 统统删除. 一个干净的开始

删除 Node.js 的方式: stackoverflow – How to completely remove node.js from Windows

Yarn 1 的删除方式: Windows start > add or remove > search yarn > remove (如果没有找到就算了)

Remove Yarn files. 上面的所以 folder 检查 nodejs 和 npm 的同时也检查 yarn 这个关键字. 

比如 C:\Users\{User}\.yarn 之类的. 全部删除. environment variable 也是删除和 yarn 有关的.

 

安装 Node.js & Yarn 3

参考: Getting Started with Yarn 3 with TypeScript

安装 Node.js

Node.js 官网下载 v16 或以上, 然后安装.

安装 Yarn 3

参考: 官网 installation

安装好 Node.js 后, 打开 cmd (run as administrator). 

corepack enable

Yarn 安装和管理是靠它的, 这个是 v16 才有的功能. 默认是关闭的, 以后可能默认会开哦

这个时候 Yarn 就安装好了.

 

Yarn 3 with VS Code

参考: Editor SDKs

为了让 VS Code 知道 TypeScript, ESLint, Prettier 等等

需要安装 yarn sdk

yarn dlx @yarnpkg/sdks vscode

没有安装的话, TypeScript 会找不到 node_modules/@types, 就报错了.

还需要安装 VS Code ZipFS extension

这是因为 Yarn 3 会用到 zip file

p.s. 每个项目都需要安装一次哦

Multiple wordspace issue

如果你通过项目的 parent folder 打开 VS Code, 你会发现 ESLint 会报错

error log

如果是在 test-material-web folder 打开, 则一切正常, 所以我觉得应该是 multiple workspace 的问题.

然后我找到了一个 VS Code 关于 Yarn PnP 的 issue: Choose different Typescript version for projects in multi root workspaces (needed for Yarn PnP)

他的问题是使用 Yarn PnP 无法在 multiple workspace 情况下选择不同版本的 TypeScript. 虽然和我遇到的不同但是应该是类似的问题.

 

Yarn 3 with TypeScript esbuild

更新: 20-02-2023 从 v0.15.0 以后 native 就直接支持 PnP 了. 不需要在安装 plugin (安装反而会有 bug, 比如 TS + PnP + esbuild + RxJS 会 error)

之前有写过一篇 TypeScript – Work with JavaScript Library (using esbuild).

可以 follow 搭环境的部分去做.

和 Yarn 1 主要的区别有几点

1. 需要安装 plugin for esbuild

yarn add @yarnpkg/esbuild-plugin-pnp --dev

2. 需要使用 esbuild.js (类似一个 config file, 为了引入 plugin)

const esbuild = require("esbuild");
const { pnpPlugin } = require("@yarnpkg/esbuild-plugin-pnp");

esbuild
  .build({
    entryPoints: ["./index.ts"],
    minify: process.env.NODE_ENV === "production",
    bundle: true,
    outfile: "./bundle.js",
    plugins: [pnpPlugin()],
  })
  .catch(() => process.exit(1));

3. 运行 command 需要加上 yarn

yarn node esbuild.js

 

Yarn 3 with Webpack

之前有写过一篇 Webpack 学习笔记

Webpack 5.0 直接支持 Yarn 3, 什么都不需要安装. 

用 yarn init -2 做初始化, 然后照着把所有需要的加进去就可以了.

关键: 只有一个点不一样. 不可以用 npm start, 要改成 yarn start, 这样就 ok 了.

 

Yarn 升级

检查 version

yarn -v

 升级

yarn set version stable 

yarn set version from sources // pre-release

yarn set version from sources --branch 1211 // target specify branch

yarn install // 升级后最好跑一下

local 也是相同做法

 

Yarn 降级 downgrade to classic

参考: Docs – yarn set version

有时候需要切换 classic 和 canary (比如遇到 bug, 你怀疑是它的问题, 或者项目太久不敢升级)

yarn set version classic // 切换回 1.x 版本, 这时 yarn init 就是 node_modules 的 pattern

yarn set version canary // 切换到 3.x 版本. 这时就没有 node_modules 了. 2.x 版本叫 berry
yarn set version stable // 建议用这个, 上面那个有时候跑不到的...
yarn set version berry // canary 不行, 但是 berry 可以哦 (它也会更新版本 3) 

 

Migration Yarn 1 to 3

为了测试, 我是像上面那样 uninstall Node.js, 然后重新安装 Node.js 和 Yarn 1 (下载 msi)

接着就 follow 官网的 step 做: Yarn Migration

Without PnP

它分 2 个环节

第一个是升级 Yarn, 但没有使用 Plug'n'Play (PnP), node_modules 依然还在那里.

因为不是所有 library 都支持 PnP, 比如 esbuild 需要一个 PnP plugin 才支持, Webpack 要 v5 才支持 (v4 需要 plugin).

所以要确保你依赖的 library 支持 Yarn 3 才可以转去 PnP 哦.

叉的部分是不重要或我的项目不需要的, 所以我不重视.

注意第 10, yarn outdated 没有了, 取而代之的是 yarn upgrade-interactive (有时候需要加 --latest), 要运行这个需要安装 yarn plugin import interactive-tools

它用起来是这样的.

keyboard 上下左右 enter 操作

 With PnP

without PnP 会把 nodeLinker set 成 node_modules, 在这里换成 pnp 或者删除它 (因为默认就是 pnp 了)

建议大家可以 yarn init -2 创建一个新项目来对比一下 migration 的版本.

比如 .gitignore

我的发现是 .yarn 里面有些 folder 是必须的, cache (最大的) 则可以不要

.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions

# Swap the comments on the following lines if you don't wish to use zero-installs
# Documentation here: https://yarnpkg.com/features/zero-installs
!.yarn/cache
#.pnp.*

如果想把 releases, plugins 全部都 ignore 也不是不行. 只是 git clone 后不能马上 yarn install.

会报错 The "yarn-path" option has been set, 原因是 .yarnrc.yml 记入了路径

这时可以把 .yarnrc.yml 洗掉, 重新跑一次 

yarn set version berry
yarn plugin import interactive-tools

让它安装过 plugin 就可以了.

但我还是推荐不要 ignore releases 和 plugins, 这样 git clone 就可以马上 yarn install 使用了. 方便很多.

# Yarn PnP
*/.yarn/*
*/!.yarn/patches
!*/.yarn/plugins
!*/.yarn/releases
*/!.yarn/sdks
*/!.yarn/versions

# Swap the comments on the following lines if you don't wish to use zero-installs
# Documentation here: https://yarnpkg.com/features/zero-installs
*/!.yarn/cache
#.pnp.*
View Code

.gitignore starts with ! 意思是反义词, 要保留.

.editor.config

root = true

[*]
end_of_line = lf
insert_final_newline = true

[*.{js,json,yml}]
charset = utf-8
indent_style = space
indent_size = 2

migration 可能会撞, 要小心哦.

 

yarn list 换成了 yarn info

以前想 list out all package and version 用 yarn list

现在改成了 yarn info

yarn info // all package information 
yarn info typescript // only typescript info
yarn info --name-only // show only name and version

 

遇到 Bug

我以为等了一个 version, 从 Yarn 2 到 Yarn 3 应该不会遇到什么 Bug 了吧. 不可能还算早鸟吧.

还是太天真...

今天遇到一个 error: The TypeScript language service died 5 times right after it got started. The service will not be restarted

我猜是 Yarn 3 造成的, 于是拿一个 Yarn 1 来跑. 果然是

然后就开始排查. 最后确定是 sdk 的问题, 就去 Github 开 Issue

Yarn 开 Issue 很苛刻, 指明要用 Sherlock 做 reproduction. 不然不处理. 但我不会啊, 而且这个又牵涉到 VS Code 和 TypeScript, Sherlock 未必就搞的出来吧.

不管就直接提交了.

结果他们不到 5 分钟就回复我了, 给了我一个 RC 版本.

安装以后问题就解决了, 也不知道是我倒霉还是怎么着...纳闷...

yarn dlx @yarnpkg/sdks@3.0.0-rc.43 vscode

 

遇到 Bug 2.0

我就知道, 不成熟的东西总是有 Bug 的. 升级 TypeScript 到 4.7 所有 depend 的 library 直接红灯.

Github Issue – [Bug?]: TS 4.7 beta breaks with yarn pnp

升级 Yarn 到最新的 3.2.1 就可以了

02-09-2022 又来了, 升级 TypeScript 到 4.8 所有 depend 的 library 直接红灯.

Github Issue – Module resolution breaking for Yarn PNP in TS 4.8

Github Issue – TS 4.8.4 not working

Github Issus – [Bug?]: TS 4.9.4 PnP Cannot find module error (update 12-12-2022: 真的是每一版都有 issue 呢)

等吧... 总是慢一拍就是了.

 

遇到 Bug 3.0

升到 TypeScript 5.0 又出 error.

这里给一点 tips. 

1. update yarn version (workspace & global)

2. update @yarnpkg/sdks

3. 却换 TypeScript version

换来换去一下, 有时候它就是要一个 reset 的动作

 

遇到 Bug 4.0

Issue – ENOTDIR when using yarn 3

Issue – [Bug]: Error with prettier 3.0.0

这次不是 TypeScript 而是 VS Code Prettier Extension。

Prettier 2.8.8 没有问题,升级到 3.0.0 直接坏掉!

目前的 workaround 是 unplug Prettier

yarn unplug prettier

还有 .vscode > setting.json 一定要指名 prettier sdk 路径

通常在安装 yarn dlx @yarnpkg/sdks vscode 的时候它 detect 到你有 prettier 就会自动添加的。

注意: 上面的方法也解决不了 stylelint extension 的问题。

总之问题多多,如果不要用 Yarn PnP 那全部都可以用新的。如果要 PnP 那么可以考虑用旧 package 

保持这几个在旧版本就可以了。不然就是用上面不完善的 wordaround.

 

posted @ 2022-05-11 19:09  兴杰  阅读(2939)  评论(2编辑  收藏  举报