<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>包管理 on Liangweidong's blog</title><link>https://liangweidonggood.github.io/tags/%E5%8C%85%E7%AE%A1%E7%90%86/</link><description>Recent content in 包管理 on Liangweidong's blog</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Tue, 15 Aug 2017 00:00:00 +0800</lastBuildDate><atom:link href="https://liangweidonggood.github.io/tags/%E5%8C%85%E7%AE%A1%E7%90%86/index.xml" rel="self" type="application/rss+xml"/><item><title>包管理工具：npm / yarn / pnpm 全对比与 yarn berry 升级</title><link>https://liangweidonggood.github.io/p/npm-yarn-pnpm-compare/</link><pubDate>Tue, 15 Aug 2017 00:00:00 +0800</pubDate><guid>https://liangweidonggood.github.io/p/npm-yarn-pnpm-compare/</guid><description>&lt;img src="https://liangweidonggood.github.io/p/npm-yarn-pnpm-compare/image/cover.jpg" alt="Featured image of post 包管理工具：npm / yarn / pnpm 全对比与 yarn berry 升级" /&gt;
 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;为什么写这篇&lt;/strong&gt;：2016 年 yarn 1.0 横空出世，靠并行安装和 lockfile 把 npm 5 之前的&amp;quot;装包慢、依赖飘&amp;quot;问题锤了一遍。2018 年 pnpm 出现，靠&amp;quot;硬链接 + 内容寻址存储&amp;quot;把磁盘占用压到极致。2020 年 yarn 2（berry）做 Plug&amp;rsquo;n&amp;rsquo;Play，零 node_modules。2025 年的新项目几乎只在这三者之间选。本文用一份&amp;quot;选型决策树&amp;quot;和&amp;quot;命令对照表&amp;quot;收尾。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;适用读者&lt;/strong&gt;：要给新项目选包管理器；被同事的 &lt;code&gt;pnpm install&lt;/code&gt; 报错困扰；要从 yarn 1 升级到 berry/pnpm。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;前置知识&lt;/strong&gt;：用过 npm 即可。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="目录"&gt;目录
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;a class="link" href="#1-%e4%b8%89%e5%b7%a8%e5%a4%b4%e5%8e%86%e5%8f%b2%e4%b8%8e%e8%ae%be%e8%ae%a1%e5%93%b2%e5%ad%a6" &gt;三巨头历史与设计哲学&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#2-%e5%ae%89%e8%a3%85%e4%b8%8e%e7%89%88%e6%9c%ac%e7%ae%a1%e7%90%86" &gt;安装与版本管理&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#3-%e5%91%bd%e4%bb%a4%e5%af%b9%e7%85%a7%e9%80%9f%e6%9f%a5%e8%a1%a8" &gt;命令对照速查表&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#4-%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6npmrc--yarnrc--npmrc" &gt;配置文件：.npmrc / .yarnrc / .npmrc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#5-lockfile-%e4%be%9d%e8%b5%96%e7%9a%84%e5%94%af%e4%b8%80%e7%9c%9f%e7%90%86" &gt;lockfile：依赖的&amp;quot;唯一真理&amp;quot;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#6-%e9%95%9c%e5%83%8f%e5%8a%a0%e9%80%9f%e4%b8%8e%e4%bb%a3%e7%90%86" &gt;镜像加速与代理&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#7-%e5%b8%b8%e8%a7%81%e6%8e%92%e9%94%99" &gt;常见排错&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#8-yarn-berry--pnpm%e5%8d%87%e7%ba%a7%e8%b7%af%e5%be%84%e4%b8%8e%e5%9d%91" &gt;yarn berry / pnpm：升级路径与坑&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#9-monorepo-%e5%b7%a5%e4%bd%9c%e5%8c%ba" &gt;monorepo 工作区&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#10-%e9%80%89%e5%9e%8b%e5%86%b3%e7%ad%96%e6%a0%91" &gt;选型决策树&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id="1-三巨头历史与设计哲学"&gt;1. 三巨头历史与设计哲学
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;工具&lt;/th&gt;
					&lt;th&gt;诞生&lt;/th&gt;
					&lt;th&gt;维护方&lt;/th&gt;
					&lt;th&gt;核心思路&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;npm&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;2010&lt;/td&gt;
					&lt;td&gt;npm Inc.（被 GitHub 收购）&lt;/td&gt;
					&lt;td&gt;官方默认，与 Node 同生共死&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;yarn 1.x&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;2016-10&lt;/td&gt;
					&lt;td&gt;Facebook（已移交社区）&lt;/td&gt;
					&lt;td&gt;并行安装 + lockfile + 离线缓存&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;pnpm&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;2017&lt;/td&gt;
					&lt;td&gt;Zoltan Kochan&lt;/td&gt;
					&lt;td&gt;硬链接 + 内容寻址，磁盘节约 50%+&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;yarn berry (v2+)&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;2020-01&lt;/td&gt;
					&lt;td&gt;Yarn 团队&lt;/td&gt;
					&lt;td&gt;PnP（Plug&amp;rsquo;n&amp;rsquo;Play）—— 抛弃 node_modules&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;bun&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;2022&lt;/td&gt;
					&lt;td&gt;Oven&lt;/td&gt;
					&lt;td&gt;Zig 编写的 JS 运行时 + 极快包管理器（兼容 npm script）&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;核心设计差异&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;npm/yarn 1&lt;/strong&gt;：每个项目的 &lt;code&gt;node_modules&lt;/code&gt; 是平铺的&amp;quot;半 hoist&amp;quot;结构（依赖被提升到顶层 &lt;code&gt;node_modules&lt;/code&gt;），节省空间但导致&amp;quot;幽灵依赖&amp;quot;——你能 &lt;code&gt;require('xxx')&lt;/code&gt; 但它不在 &lt;code&gt;package.json&lt;/code&gt; 里&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;pnpm&lt;/strong&gt;：用 &lt;code&gt;.pnpm/&amp;lt;pkg&amp;gt;@&amp;lt;version&amp;gt;/node_modules/&amp;lt;pkg&amp;gt;&lt;/code&gt; 软链接隔离 + &lt;code&gt;node_modules/&amp;lt;pkg&amp;gt;&lt;/code&gt; 软链接到 &lt;code&gt;node_modules/.pnpm&lt;/code&gt;——&lt;strong&gt;真实依赖树&lt;/strong&gt;且零幽灵依赖&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;yarn berry PnP&lt;/strong&gt;：根本不要 &lt;code&gt;node_modules&lt;/code&gt;，每个包用 &lt;code&gt;.pnp.cjs&lt;/code&gt; 文件描述&amp;quot;谁在哪&amp;quot;。启动快、装包快，但&lt;strong&gt;所有老工具链（webpack、jest、tsc）都得配 PnP 适配器&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="2-安装与版本管理"&gt;2. 安装与版本管理
&lt;/h2&gt;&lt;h3 id="21-npm"&gt;2.1 npm
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;node -v &lt;span class="c1"&gt;# Node 自带 npm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm -v
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 升级&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm install -g npm@latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm update -g
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="22-yarn-1x"&gt;2.2 yarn 1.x
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm install -g yarn
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yarn -v
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 升级&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm install -g yarn@latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yarn self-update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 装指定 tag&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yarn self-update stable
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yarn self-update canary
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="23-pnpm"&gt;2.3 pnpm
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 推荐用独立安装脚本（避免污染全局 npm）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -fsSL https://get.pnpm.io/install.sh &lt;span class="p"&gt;|&lt;/span&gt; sh -
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Windows&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;iwr https://get.pnpm.io/install.ps1 -useb &lt;span class="p"&gt;|&lt;/span&gt; iex
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 升级&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pnpm self-update
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="24-bun备选"&gt;2.4 bun（备选）
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -fsSL https://bun.sh/install &lt;span class="p"&gt;|&lt;/span&gt; bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="3-命令对照速查表"&gt;3. 命令对照速查表
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;任务&lt;/th&gt;
					&lt;th&gt;npm&lt;/th&gt;
					&lt;th&gt;yarn 1.x&lt;/th&gt;
					&lt;th&gt;pnpm&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;初始化&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;npm init&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;yarn init&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;pnpm init&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;一键安装&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;npm install&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;yarn&lt;/code&gt; / &lt;code&gt;yarn install&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;pnpm install&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;添加依赖&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;npm i pkg&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;yarn add pkg&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;pnpm add pkg&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;添加开发依赖&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;npm i -D pkg&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;yarn add -D pkg&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;pnpm add -D pkg&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;全局装&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;npm i -g pkg&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;yarn global add pkg&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;pnpm add -g pkg&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;卸载&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;npm uninstall pkg&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;yarn remove pkg&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;pnpm remove pkg&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;升级&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;npm update&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;yarn upgrade&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;pnpm update&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;跑 script&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;npm run dev&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;yarn dev&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;pnpm dev&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;清理缓存&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;npm cache clean --force&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;yarn cache clean&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;pnpm store prune&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;列出已装&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;npm list&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;yarn list&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;pnpm list&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;装指定版本&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;npm i pkg@1.2.3&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;yarn add pkg@1.2.3&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;pnpm add pkg@1.2.3&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;只装 prod&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;npm i --production&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;yarn install --production&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;pnpm install --prod&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;锁文件&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;package-lock.json&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;yarn.lock&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;pnpm-lock.yaml&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="4-配置文件"&gt;4. 配置文件
&lt;/h2&gt;&lt;h3 id="41-npmnpmrc"&gt;4.1 npm：&lt;code&gt;.npmrc&lt;/code&gt;
&lt;/h3&gt;&lt;p&gt;放在项目根目录或 &lt;code&gt;~/.npmrc&lt;/code&gt;（用户级）：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;https://registry.npmmirror.com&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;save-exact&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;package-lock&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;audit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="42-yarn-1yarnrc"&gt;4.2 yarn 1：&lt;code&gt;.yarnrc&lt;/code&gt;
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;registry &amp;#34;https://registry.npmmirror.com&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="43-pnpmnpmrc与-npm-兼容-pnpm-workspaceyaml"&gt;4.3 pnpm：&lt;code&gt;.npmrc&lt;/code&gt;（与 npm 兼容）+ &lt;code&gt;pnpm-workspace.yaml&lt;/code&gt;
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# .npmrc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;https://registry.npmmirror.com&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;auto-install-peers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true # 自动装 peer dep&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;shamefully-hoist&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true # 兼容老 webpack/jest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="5-lockfile依赖的唯一真理"&gt;5. lockfile：依赖的&amp;quot;唯一真理&amp;quot;
&lt;/h2&gt;
 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;Why lockfile 必交 Git&lt;/strong&gt;：不交 lockfile，同一个 &lt;code&gt;package.json&lt;/code&gt; 在不同时间/不同网络下能装出&lt;strong&gt;完全不同的依赖树&lt;/strong&gt;——经典 bug&amp;quot;我这能跑你那不能跑&amp;quot;。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;工具&lt;/th&gt;
					&lt;th&gt;文件名&lt;/th&gt;
					&lt;th&gt;是否必交 Git&lt;/th&gt;
					&lt;th&gt;是否必交 lockfile 即可不重装&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;npm 5+&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;package-lock.json&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;yarn 1&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;yarn.lock&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;pnpm&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;pnpm-lock.yaml&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;yarn berry&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;yarn.lock&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;配合 &lt;code&gt;.yarn/cache&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 不读 lockfile 强制重装（出问题时偶尔用）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm install --no-package-lock
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yarn install --no-lockfile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pnpm install --no-lockfile
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="6-镜像加速与代理"&gt;6. 镜像加速与代理
&lt;/h2&gt;&lt;h3 id="61-永久改源"&gt;6.1 永久改源
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm config &lt;span class="nb"&gt;set&lt;/span&gt; registry https://registry.npmmirror.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yarn config &lt;span class="nb"&gt;set&lt;/span&gt; registry https://registry.npmmirror.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pnpm config &lt;span class="nb"&gt;set&lt;/span&gt; registry https://registry.npmmirror.com
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="62-nrm-一键切换"&gt;6.2 nrm 一键切换
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm install -g nrm
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nrm ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# npm ---------- https://registry.npmjs.org/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# yarn --------- https://registry.yarnpkg.com/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# cnpm --------- https://r.cnpmjs.org/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# taobao ------- https://registry.npmmirror.com/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# tencent ------ https://mirrors.cloud.tencent.com/npm/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nrm use taobao
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="63-代理"&gt;6.3 代理
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 命令行（项目级）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm config &lt;span class="nb"&gt;set&lt;/span&gt; proxy http://127.0.0.1:1081
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm config &lt;span class="nb"&gt;set&lt;/span&gt; https-proxy http://127.0.0.1:1081
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 环境变量（用户级）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;HTTP_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://127.0.0.1:1081
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;HTTPS_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://127.0.0.1:1081
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="7-常见排错"&gt;7. 常见排错
&lt;/h2&gt;&lt;h3 id="71-循环依赖错误"&gt;7.1 循环依赖错误
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm error ERESOLVE could not resolve
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm error Conflicting peer dependency: react@17 vs react@18
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;解决：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm install xxx --legacy-peer-deps
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yarn install --ignore-peer-deps
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pnpm install --shamefully-hoist
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="72-github-ssh-权限问题"&gt;7.2 GitHub SSH 权限问题
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm ERR! code &lt;span class="m"&gt;128&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm ERR! git@github.com: Permission denied &lt;span class="o"&gt;(&lt;/span&gt;publickey&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;解决：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1. 生成密钥&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh-keygen -t ed25519 -C &lt;span class="s2"&gt;&amp;#34;&amp;lt;YOUR_EMAIL&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2. 把 ~/.ssh/id_ed25519.pub 内容加到 GitHub → Settings → SSH and GPG keys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3. 验证&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh -T git@github.com
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="73-浏览器数据自动更新错误"&gt;7.3 浏览器数据自动更新错误
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;browserslist: Caniuse was updated
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;说明 &lt;code&gt;browserslist&lt;/code&gt; 数据陈旧。&lt;strong&gt;重新跑 &lt;code&gt;npx update-browserslist-db@latest&lt;/code&gt;&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id="74-装包后跑起来报错"&gt;7.4 装包后跑起来报错
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;经典排错四件套&lt;/strong&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1. 清缓存 + 删 node_modules&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rm -rf node_modules package-lock.json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm cache clean --force
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm install
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2. 升 Node&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nvm use &lt;span class="m"&gt;20&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3. 检查 peer dep&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm ls react
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 4. 看完整错误&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm install --verbose 2&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; head -100
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="8-yarn-berry--pnpm升级路径与坑"&gt;8. yarn berry / pnpm：升级路径与坑
&lt;/h2&gt;&lt;h3 id="81-yarn-1--yarn-berry-v2"&gt;8.1 yarn 1 → yarn berry (v2+)
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 在项目目录&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yarn &lt;span class="nb"&gt;set&lt;/span&gt; version berry
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# → Saving the new release in .yarn/releases/yarn-3.2.1.cjs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yarn --version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3.2.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;升级后会自动生成：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.yarn/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── cache/ # 离线包缓存（建议 commit）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── unplugged/ # 编译型 native 模块临时目录
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── releases/ # yarn 二进制（建议 commit）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.yarnrc.yml # 新版配置
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.pnp.cjs # PnP 依赖图
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;.gitignore&lt;/code&gt; 必须加：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/.pnp.*
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.yarn/cache
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.yarn/unplugged
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.yarn/install-state.gz
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;设置 npm registry：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yarn config &lt;span class="nb"&gt;set&lt;/span&gt; npmRegistryServer https://registry.npmmirror.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yarn &lt;span class="c1"&gt;# 装包&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="82-yarn-berry-的核心pnp"&gt;8.2 yarn berry 的核心——PnP
&lt;/h3&gt;&lt;p&gt;PnP（Plug&amp;rsquo;n&amp;rsquo;Play）&lt;strong&gt;没有 &lt;code&gt;node_modules&lt;/code&gt;&lt;/strong&gt;！所有包都在 &lt;code&gt;.yarn/cache/&lt;/code&gt;，启动时通过 &lt;code&gt;.pnp.cjs&lt;/code&gt; 的&amp;quot;依赖图&amp;quot;直接定位文件。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;优点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;装包速度比 yarn 1 快 2-3 倍&lt;/li&gt;
&lt;li&gt;启动速度提升（无文件系统 IO）&lt;/li&gt;
&lt;li&gt;杜绝幽灵依赖（包必须显式声明在 deps）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;坑&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;很多老工具链不兼容——必须用 PnP 适配版
&lt;ul&gt;
&lt;li&gt;Webpack 4/5：装 &lt;code&gt;@yarnpkg/pnpify&lt;/code&gt; 然后跑 &lt;code&gt;yarn pnpify webpack&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Jest：装 &lt;code&gt;jest-pnp-resolver&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;TypeScript：配 &lt;code&gt;pnpPlugin&lt;/code&gt; 解析器&lt;/li&gt;
&lt;li&gt;VSCode：装 ZipFS 扩展才能读 &lt;code&gt;.yarn/cache&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;小贴士&lt;/strong&gt;：Berry 默认是 PnP。如果你不想抛弃 node_modules，加 &lt;code&gt;.yarnrc.yml&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;nodeLinker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;node-modules&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这样就像 yarn 1 一样工作，但还是 yarn berry 的安装器。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h3 id="83-从-npmyarn-1-迁到-pnpm"&gt;8.3 从 npm/yarn 1 迁到 pnpm
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1. 装 pnpm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm install -g pnpm
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2. 删除旧 lockfile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rm package-lock.json yarn.lock
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3. 用 pnpm 装&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pnpm install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;坑&lt;/strong&gt;：老项目里大量 &lt;code&gt;require('xxx')&lt;/code&gt; 但 xxx 不在 &lt;code&gt;package.json&lt;/code&gt; 的&amp;quot;幽灵依赖&amp;quot;，pnpm 装完会报错。&lt;strong&gt;两种解法&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;找到所有 &lt;code&gt;require/import&lt;/code&gt; 实际用到的包，补到 &lt;code&gt;package.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;在 &lt;code&gt;.npmrc&lt;/code&gt; 加 &lt;code&gt;shamefully-hoist=true&lt;/code&gt;（pnpm 模拟 npm 的&amp;quot;提升&amp;quot;行为）——不推荐，治标不治本&lt;/li&gt;
&lt;/ol&gt;

 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="9-monorepo-工作区"&gt;9. monorepo 工作区
&lt;/h2&gt;&lt;p&gt;包管理工具的&amp;quot;工作区（workspace）&amp;ldquo;能力，让多个子包共享一个 &lt;code&gt;node_modules&lt;/code&gt;，是 monorepo 的基石。&lt;/p&gt;
&lt;h3 id="91-yarn-1-workspaces"&gt;9.1 yarn 1 workspaces
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;package.json&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;private&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;workspaces&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;packages/*&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;apps/*&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="92-pnpm-workspaces最推荐"&gt;9.2 pnpm workspaces（最推荐）
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;pnpm-workspace.yaml&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;packages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s1"&gt;&amp;#39;apps/*&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s1"&gt;&amp;#39;packages/*&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pnpm -F &amp;lt;pkg&amp;gt; add &amp;lt;dep&amp;gt; &lt;span class="c1"&gt;# 只给某个子包加依赖&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pnpm -r run build &lt;span class="c1"&gt;# 跑所有子包的 build&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pnpm --filter &amp;lt;pkg&amp;gt;... &amp;lt;cmd&amp;gt; &lt;span class="c1"&gt;# 依赖关系图上跑命令&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="93-npm-workspaces7-支持"&gt;9.3 npm workspaces（7+ 支持）
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;package.json&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;workspaces&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;packages/*&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm install lodash -w @myorg/utils
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm run build --workspaces
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;monorepo 工具链对比&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;工具&lt;/th&gt;
					&lt;th&gt;适合规模&lt;/th&gt;
					&lt;th&gt;特点&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;npm/yarn/pnpm workspaces&lt;/td&gt;
					&lt;td&gt;小团队&lt;/td&gt;
					&lt;td&gt;零额外依赖&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Lerna&lt;/td&gt;
					&lt;td&gt;中型&lt;/td&gt;
					&lt;td&gt;已并入 Nx&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Nx&lt;/td&gt;
					&lt;td&gt;中大型&lt;/td&gt;
					&lt;td&gt;任务编排、缓存、依赖图分析最强&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Turborepo&lt;/td&gt;
					&lt;td&gt;中大型&lt;/td&gt;
					&lt;td&gt;增量构建、远程缓存、零配置&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Rush&lt;/td&gt;
					&lt;td&gt;大型&lt;/td&gt;
					&lt;td&gt;微软维护，企业级权限与发布流水线&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;

 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="10-选型决策树"&gt;10. 选型决策树
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;新项目选包管理器？
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├─ 想 0 学习成本、纯前端小项目
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └─ npm ✓
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├─ monorepo + 多包共享
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ ├─ 小型（&amp;lt; 5 包）→ npm / yarn 1 workspaces
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ ├─ 中型（5-20 包）→ pnpm workspaces ✓
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └─ 大型（&amp;gt; 20 包）→ pnpm + Turborepo / Nx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├─ 老 npm 项目维护，不想折腾
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └─ npm 9+ ✓（性能已与 yarn 1 持平）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├─ 公司有私服（Nexus / Verdaccio）镜像严格
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └─ pnpm（lockfile 完整，依赖提升少）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├─ 极致装包速度、CI 跑得快
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └─ pnpm（内容寻址，复用 100%）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└─ 抛弃 node_modules、要 PnP 黑科技
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └─ yarn berry (PnP) —— 仅当你团队接受重写所有工具链时
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;小贴士&lt;/strong&gt;：CI 环境装包时，pnpm 默认&lt;strong&gt;不用&lt;/strong&gt;网络——因为依赖都已&amp;quot;硬链接&amp;quot;到全局 store。建议在 &lt;code&gt;package.json&lt;/code&gt; 旁边放 &lt;code&gt;.npmrc&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;prefer-frozen-lockfile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;锁文件没变就直接复用 node_modules，&lt;strong&gt;CI 启动时间从 90s 降到 15s&lt;/strong&gt;。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="小结"&gt;小结
&lt;/h2&gt;&lt;p&gt;npm / yarn / pnpm / berry 的设计哲学各有不同。&lt;strong&gt;2025 年的&amp;quot;默认推荐&amp;quot;是 pnpm&lt;/strong&gt;——装包快、磁盘省、workspace 体验最好、monorepo 生态最完整（Turbo/Nx 优先支持）。&lt;strong&gt;老项目维护&lt;/strong&gt;用 npm 就好，不要为了追新而迁移。&lt;strong&gt;yarn berry&lt;/strong&gt; 仅在大公司、复杂 monorepo、追求极致启动速度时考虑。&lt;/p&gt;
&lt;h2 id="参考资料"&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.npmjs.com/" target="_blank" rel="noopener"
 &gt;npm 官方文档&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://classic.yarnpkg.com/en/docs" target="_blank" rel="noopener"
 &gt;Yarn 1.x 文档&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://yarnpkg.com/getting-started" target="_blank" rel="noopener"
 &gt;Yarn berry 文档&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://pnpm.io/zh/" target="_blank" rel="noopener"
 &gt;pnpm 官方文档&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.robinwieruch.de/pnpm-npm-yarn/" target="_blank" rel="noopener"
 &gt;《Why I prefer pnpm over npm and yarn》— Catalin Pit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>