1. 为什么 Mac 上装 Yarn 这件事值得单独写一篇
很多人看到"Mac 安装 yarn"这个标题,第一反应是:不就一行命令的事吗?npm install -g yarn敲下去不就完了?我一开始也这么想,直到我在三台不同芯片、不同系统版本的 Mac 上反复折腾,才发现这件事的坑远比想象中多。尤其是 Apple Silicon 芯片普及之后,Node 版本管理工具、包管理器、全局路径、权限这几件事搅在一起,新手很容易装完发现命令找不到、版本对不上、或者装到一半报权限错误。
Yarn 是什么?简单说,它是 JavaScript 生态里的一个包管理工具,和 npm 干的是同一件事——帮你下载、管理项目依赖。它最早由几家大厂联合推出,主打速度快、依赖锁定可靠、支持离线缓存。虽然现在 npm 本身也进步了很多,pnpm 也分走了不少用户,但 Yarn 在大量存量项目里依然是标配,尤其是那些用 Yarn Workspaces 做 monorepo 的工程。所以不管你是刚入门前端的新手,还是接手老项目的开发者,在 Mac 上把 Yarn 装好、装对,都是一件绕不开的事。
这篇内容我会从芯片架构差异、安装方式选型、版本管理、常见报错排查几个角度,把这件事彻底讲透。适合三类人看:一是刚买 Mac 准备学前端的同学;二是装了 Yarn 但总出问题的开发者;三是想搞清楚 Yarn 和 npm、pnpm 到底该怎么选的人。我不会只给你一行命令就完事,而是把每一步背后的原因讲清楚,让你装完之后心里有底,出了问题也能自己排查。
先说一个反直觉的结论:在 Mac 上装 Yarn,最不推荐的方式恰恰是很多人最先想到的npm install -g yarn。为什么?往下看。
2. 装之前先搞清楚:你的 Mac 是什么芯片、Node 从哪来
2.1 Apple Silicon 和 Intel 芯片的路径差异
从 2020 年之后,Mac 分成了两条线:老的 Intel 芯片和新的 Apple Silicon(M 系列)芯片。这件事对装 Yarn 的影响,比大多数人以为的要大。
核心差异在于二进制依赖的架构。Yarn 本身是 JavaScript 写的,理论上跨架构没问题,但它依赖的 Node 运行时是分架构的。如果你在 M 系列芯片上装了一个 x86 架构的 Node(比如通过 Rosetta 转译运行的旧版本),那么基于它安装的 Yarn 也可能跑在转译层里,速度慢不说,还容易出现原生模块编译失败的问题。
怎么确认自己的芯片?打开终端,敲:
uname -m- 输出
arm64:你是 Apple Silicon,走原生 arm64 路线。 - 输出
x86_64:你是 Intel 芯片,或者你的终端正跑在 Rosetta 转译模式下。
这里有个隐藏坑:有些人的终端本身被设置成了 Rosetta 模式,导致uname -m显示x86_64,但机器其实是 M 系列。检查方法是在"访达"里找到终端应用,右键"显示简介",看有没有勾选"使用 Rosetta 打开"。如果有,取消勾选,重启终端再测一次。
为什么要在意这个?因为如果你的 Node 是 x86 版本,装出来的 Yarn 在调用某些原生依赖时会出现架构不匹配的报错,典型症状是mach-o file, but is an incompatible architecture。这个错误我在帮别人排查时遇到过好几次,根源就是架构混用。
2.2 Node 的来源决定了 Yarn 怎么装
Yarn 是跑在 Node 之上的,所以先有 Node,才有 Yarn。而 Node 在 Mac 上的安装方式,直接决定了你该用哪种方式装 Yarn。
常见的 Node 安装方式有三种:
| 安装方式 | 特点 | 对装 Yarn 的影响 |
|---|---|---|
| 官网 pkg 安装包 | 简单直接,但全局包路径固定,切换版本麻烦 | 用npm -g装 Yarn 会装到系统级路径,可能需要 sudo |
| Homebrew | 方便管理,但 Node 版本更新频繁 | 可以用 brew 直接装 Yarn,但版本可能滞后 |
| nvm / fnm 等版本管理器 | 可自由切换 Node 版本,路径隔离干净 | 推荐配合corepack或npm -g,无需 sudo |
我的建议很明确:如果你还没装 Node,先装一个版本管理器(nvm 或 fnm),再用它装 Node,最后装 Yarn。这样全局包路径都在你的用户目录下,不需要 sudo,切换 Node 版本时 Yarn 也跟着走,干净利落。
如果你已经用官网 pkg 装了 Node,也别急着卸载,可以先看看当前 Node 版本和路径:
which node node -v npm -vwhich node的输出能告诉你 Node 装在哪。如果是/usr/local/bin/node或/opt/homebrew/bin/node,说明是系统级或 brew 级安装;如果是/Users/你的用户名/.nvm/...这种,说明是版本管理器装的。
2.3 一个容易被忽略的前置检查:npm 全局路径权限
不管你最后用哪种方式装 Yarn,都建议先检查一下 npm 的全局路径权限。很多人装 Yarn 时报EACCES: permission denied,根源就在这里。
npm config get prefix如果输出是/usr/local或/usr,那说明全局包会装到系统目录,普通用户没写权限,就会报权限错误。正确的做法是把 prefix 改到用户目录下:
mkdir -p ~/.npm-global npm config set prefix ~/.npm-global然后把~/.npm-global/bin加到 PATH 里。在~/.zshrc(Mac 默认 shell 是 zsh)末尾加一行:
export PATH=~/.npm-global/bin:$PATH执行source ~/.zshrc生效。这一步做完,后面装 Yarn 就不会再被权限问题卡住了。这个操作看起来是额外步骤,但它能帮你避开后面 80% 的报错,非常值得。
3. 四种安装方式实测对比:哪种最适合你
3.1 方式一:corepack(Node 16.10+ 官方推荐)
从 Node 16.10 开始,官方内置了一个叫corepack的工具,专门用来管理 Yarn 和 pnpm 这类包管理器的版本。这是目前最推荐的方式,原因是它把 Yarn 的版本和项目绑定,而不是全局装一个固定版本。
启用方式:
corepack enable如果提示command not found,说明你的 Node 版本太老,或者 corepack 没被激活。可以先检查:
node -vNode 16.10 以上才有 corepack。如果版本够但还是找不到,可能是安装 Node 时没带上 corepack,这种情况建议换用版本管理器重装 Node。
启用之后,在项目目录里可以直接指定 Yarn 版本:
corepack prepare yarn@stable --activate或者更精细地指定:
corepack prepare yarn@4.1.0 --activatecorepack 的好处是每个项目可以用不同的 Yarn 版本,通过项目根目录的packageManager字段自动切换。比如你在package.json里写:
{ "packageManager": "yarn@4.1.0" }那么进入这个项目时,corepack 会自动使用 4.1.0 版本,完全不用手动切换。这对维护多个老项目的开发者来说,简直是救星。
不过 corepack 也有个坑:它默认可能没在 PATH 里注册 yarn 命令,需要先corepack enable一次。另外某些 Node 版本(尤其是通过某些包管理器装的)可能没带 corepack,这时候就得手动补。
3.2 方式二:npm 全局安装(最传统,但要注意路径)
这是最广为人知的方式:
npm install -g yarn如果你前面已经把 npm prefix 改到了用户目录,这条命令会顺利执行,Yarn 会装到~/.npm-global/bin/yarn。验证:
yarn -v能输出版本号就成功了。
但这种方式有两个问题。第一,它装的是 Yarn 1.x(Classic)还是 2.x+(Berry)取决于 npm 源里的 latest 标签,你没法精确控制。第二,全局只有一个版本,切换项目时如果项目要求不同版本,就会冲突。
所以我的看法是:npm 全局安装适合只想快速用一下、不涉及多版本切换的场景。如果你要长期做前端开发,还是 corepack 更靠谱。
3.3 方式三:Homebrew 安装(适合 brew 重度用户)
如果你习惯用 Homebrew 管理一切,那可以:
brew install yarnHomebrew 会自动处理依赖,把 Yarn 装到/opt/homebrew/bin(Apple Silicon)或/usr/local/bin(Intel)。
但这里有个非常容易踩的坑:brew install yarn有时会顺带装一个 Node 依赖,导致你系统里出现两个 Node——一个是你自己装的,一个是 brew 装的。两个 Node 路径不同,npm 全局包也各管各的,最后yarn命令用的是哪个 Node 都搞不清。
验证方法:
which -a node which -a yarn如果输出多行,说明有多个版本共存。这时候要么统一用 brew 管理,要么把 brew 装的 Node 卸载掉(brew uninstall node),只保留版本管理器装的。
另外,Homebrew 的 Yarn 版本更新通常比官方慢半拍,如果你需要最新特性,可能等不到。
3.4 方式四:独立脚本安装(不推荐,仅作了解)
Yarn 官方早期提供过一个安装脚本,通过 curl 下载执行。这种方式现在基本被 corepack 取代了,而且脚本安装的版本管理很麻烦,我不建议用。这里提一句只是让你知道有这么回事,遇到老教程提到时能分辨。
3.5 四种方式横向对比
| 方式 | 优点 | 缺点 | 推荐场景 |
|---|---|---|---|
| corepack | 版本随项目切换,官方推荐,无需 sudo | 需要 Node 16.10+,初次配置略繁琐 | 长期开发,多项目并存 |
| npm 全局 | 命令简单,人人会 | 版本固定,可能需改 prefix | 快速试用,单一项目 |
| Homebrew | 与 brew 生态统一 | 可能引入重复 Node,版本滞后 | brew 重度用户 |
| 独立脚本 | 无需 Node | 管理混乱,已过时 | 不推荐 |
看完这张表,结论很清楚:能上 corepack 就上 corepack,实在不行用 npm 全局但记得改 prefix,brew 只在你有明确理由时用。
4. 装完之后必须做的三件验证事
4.1 验证命令可用性和版本
装完第一件事,别急着跑项目,先确认命令真的能用:
yarn -v如果报command not found,说明 PATH 没配好。回到前面检查~/.zshrc里的 PATH 配置,确认~/.npm-global/bin或 corepack 的 shim 路径在里面。
如果输出了版本号,比如1.22.22或4.1.0,说明命令通了。这里要注意区分Yarn 1.x 和 Yarn 2+,它们的命令行为差异很大。1.x 是经典版,2+ 是所谓的 Berry 版,配置文件、锁文件格式都不一样。
4.2 确认 Yarn 用的是哪个 Node
这一步很多人忽略,但非常关键:
yarn node -v这条命令会告诉你 Yarn 实际调用的 Node 版本。如果这个版本和你node -v看到的不一致,说明 Yarn 和 Node 来自不同的安装源,后面很可能出问题。
理想情况下,两者应该一致。如果不一致,检查是不是有多个 Node 共存,用which -a node排查。
4.3 检查全局缓存和配置目录
Yarn 会在用户目录下建缓存和配置:
yarn cache dir yarn config listyarn cache dir告诉你缓存位置,默认在~/Library/Caches/Yarn或类似路径。如果这个目录权限有问题,装包时会失败。yarn config list列出当前所有配置,能帮你确认 registry 等关键项是否正确。
提示:如果你在国内网络环境下遇到下载慢的问题,可以配置镜像源。但具体配置请参考官方文档,我这里不展开,避免给出过时信息。
5. 那些年我踩过的 Yarn 安装坑
5.1 坑一:command not found 的三层排查
yarn: command not found是最常见的报错,但原因可能有三层,得逐层排查。
第一层:PATH 没包含 Yarn 所在目录。用echo $PATH看输出里有没有 Yarn 的安装路径。没有的话,把对应路径加进~/.zshrc。
第二层:shell 配置文件没生效。改完~/.zshrc后必须source ~/.zshrc或者重开终端。有些人改了文件但没生效,以为没配对。
第三层:装到了错误的 shell 配置里。Mac 默认是 zsh,但有些人之前用过 bash,把 PATH 写进了~/.bash_profile。zsh 启动时读的是~/.zshrc,两者不互通。确认你改的是当前 shell 对应的文件,用echo $SHELL看当前 shell。
这三层排查下来,基本能定位所有 command not found 问题。
5.2 坑二:权限报错的根治方法
EACCES: permission denied这个错误,本质是 npm 想往系统目录写文件但没权限。很多人第一反应是加sudo:
sudo npm install -g yarn千万别这么干。用 sudo 装全局包,会让文件属主变成 root,后续普通用户操作时又会报权限错误,陷入死循环。正确做法是前面说的改 prefix 到用户目录,一劳永逸。
如果已经用 sudo 装过了,得先把属主改回来:
sudo chown -R $(whoami) ~/.npm-global然后再按正常流程操作。
5.3 坑三:架构不匹配的诡异报错
在 M 系列芯片上,如果你看到类似这样的报错:
mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64')说明你的 Node 或某个依赖是 x86 架构的,但系统期望 arm64。根源通常是 Node 装错了架构。
解决办法是卸载现有 Node,用版本管理器重装 arm64 版本。用 nvm 的话:
nvm uninstall <版本号> nvm install <版本号>nvm 会自动根据当前架构下载对应版本。装完再重装 Yarn,问题就解决了。
5.4 坑四:Yarn 1 和 Yarn 2+ 的命令差异
很多人装完发现命令行为和教程对不上,原因是版本不同。Yarn 1.x 和 2+ 有几个关键差异:
| 操作 | Yarn 1.x | Yarn 2+ |
|---|---|---|
| 初始化 | yarn init | yarn init -2或自动 |
| 添加依赖 | yarn add xxx | yarn add xxx(类似) |
| 全局安装 | yarn global add xxx | 不再支持 global,用yarn dlx |
| 锁文件 | yarn.lock | yarn.lock(格式不同) |
| 配置 | .yarnrc | .yarnrc.yml |
最典型的是Yarn 2+ 取消了yarn global add,改用yarn dlx临时执行。如果你照着老教程敲yarn global add,在 2+ 上会报错。搞清楚自己用的是哪个大版本,能省下大量困惑时间。
5.5 坑五:corepack 启用后 yarn 命令反而没了
这个坑比较隐蔽。有些人启用 corepack 后,发现原来的yarn命令不见了。原因是 corepack 接管了 yarn 命令,但需要项目里有packageManager字段才会激活对应版本。在没配置的项目里,可能提示找不到版本。
解决办法是在项目里显式指定:
corepack use yarn@stable这条命令会写入packageManager字段并激活。之后yarn -v就正常了。
6. Yarn、npm、pnpm 到底该怎么选
6.1 三者的核心差异
装 Yarn 的过程中,很多人会问:现在 npm 这么好用,pnpm 又这么快,我为什么还要用 Yarn?这个问题值得说清楚。
| 维度 | npm | Yarn | pnpm |
|---|---|---|---|
| 依赖存储 | 扁平化 node_modules | 扁平化(1.x)/ PnP(2+) | 硬链接 + 内容寻址 |
| 安装速度 | 中等 | 快 | 最快 |
| 磁盘占用 | 高 | 高 | 低(共享存储) |
| 锁文件 | package-lock.json | yarn.lock | pnpm-lock.yaml |
| monorepo 支持 | workspaces | workspaces(成熟) | workspaces |
| 生态兼容 | 最好 | 好 | 偶有兼容问题 |
简单说:npm 是默认选项,兼容性最好;Yarn 在 monorepo 和依赖锁定上更成熟;pnpm 在速度和磁盘占用上最优,但个别老包可能不兼容。
6.2 什么情况下必须用 Yarn
有三种情况你基本没得选,必须用 Yarn:
第一,项目里已经有 yarn.lock。锁文件决定了依赖的精确版本,用 npm 或 pnpm 装会生成不同的锁文件,可能导致依赖版本漂移,引发莫名其妙的 bug。
第二,项目用了 Yarn Workspaces 做 monorepo。虽然 npm 和 pnpm 也有 workspaces,但老项目的配置是按 Yarn 写的,换工具要改配置。
第三,团队规范要求。有些团队统一用 Yarn,你跟着用就行,别自作主张。
6.3 我的实际选择建议
就我个人经验,新项目我会优先考虑 pnpm,因为速度和磁盘优势明显。但如果是接手存量项目,项目用什么我就用什么,绝不轻易换包管理器。换包管理器的成本远大于那点速度收益,而且容易引入难以排查的依赖问题。
Yarn 的定位现在有点尴尬,夹在 npm 和 pnpm 之间。但它的 Workspaces 和 PnP(Plug'n'Play)机制依然有独特价值,尤其是 PnP 那种不生成 node_modules 的方案,在大型 monorepo 里能显著提升安装速度。所以学 Yarn 不算过时,只是要清楚它的适用边界。
7. 装好之后,几个提升效率的配置
7.1 配置镜像源加速下载
网络环境不理想时,下载依赖会非常慢。Yarn 支持配置 registry:
yarn config set registry <镜像地址>具体镜像地址请以官方或可信渠道公布的信息为准,我这里不写死,避免过时。配置后可以用yarn config get registry确认。
7.2 开启全局缓存复用
Yarn 默认就有缓存机制,重复安装同一个包时会从缓存读取。确认缓存开启:
yarn config get enableGlobalCache如果是true,说明全局缓存已启用。这个机制能大幅减少重复下载,尤其在多个项目共用相同依赖时效果明显。
7.3 用 .yarnrc.yml 做项目级配置
Yarn 2+ 用.yarnrc.yml做项目配置,可以针对单个项目设置 nodeLinker、registry 等。比如强制用 node_modules 模式(而不是 PnP):
nodeLinker: node-modules这个配置对不熟悉 PnP 的团队很友好,能避免一堆兼容性问题。放在项目根目录,提交到版本库,团队所有人共享。
7.4 定期清理缓存
缓存用久了会占空间,定期清理:
yarn cache clean这条命令会清空缓存。如果只想看缓存占了多少空间,可以先yarn cache dir找到目录,用du -sh查看大小。我一般几个月清一次,避免磁盘被占满。
8. 关于版本升级和降级的实操
8.1 从 Yarn 1 升级到 Yarn 2+
如果你项目还在用 Yarn 1,想升级到 2+,官方提供了迁移命令:
yarn set version berry这条命令会下载最新稳定版并写入配置。升级后项目里会多出.yarn目录和.yarnrc.yml,锁文件格式也会变。升级前务必提交代码或备份,因为锁文件变化可能影响依赖解析。
升级后如果遇到兼容问题,可以回退:
yarn set version classicclassic就是 1.x 的代号。
8.2 锁定特定版本避免意外升级
团队协作时,最怕每个人用的 Yarn 版本不一样。解决办法是在package.json里写死:
{ "packageManager": "yarn@4.1.0" }配合 corepack,任何人进项目都会自动用这个版本,彻底消除版本差异。这个字段是 corepack 识别的关键,强烈建议加上。
8.3 卸载 Yarn 的正确姿势
如果你要换包管理器,得先把 Yarn 卸干净。根据安装方式不同,卸载方法也不同:
- npm 装的:
npm uninstall -g yarn - brew 装的:
brew uninstall yarn - corepack 管理的:
corepack disable然后删掉相关配置
卸完记得检查which yarn,确认没有残留。有时候 PATH 里还留着旧路径,需要手动清理~/.zshrc。
9. 写在最后的一点个人体会
折腾了这么多台 Mac、这么多种安装方式,我最大的体会是:装工具这件事,慢就是快。花十分钟把 Node 的来源、PATH 的配置、芯片架构这些前置条件搞清楚,比装完出问题再花两小时排查要划算得多。
我见过太多人一上来就npm install -g yarn,然后被权限、路径、版本问题轮番折磨,最后对前端环境配置产生心理阴影。其实只要按"先版本管理器装 Node,再 corepack 管 Yarn"这个顺序走,整个过程会非常顺。
另外提醒一句,环境配置这东西没有一劳永逸的方案。系统升级、Node 大版本更新、Yarn 从 1 到 4 的演进,都会带来新的变化。保持关注官方文档,遇到报错先看错误信息里的关键词,再针对性搜索,比盲目试错高效得多。
最后分享一个小习惯:我会在~/.zshrc里加一行注释,记录当前 Node 和 Yarn 的安装方式,比如# Node via nvm, Yarn via corepack。过几个月回头看,能立刻想起当初是怎么配的,省去重新排查的麻烦。这个习惯帮我省了不少时间,你也可以试试。