> ## Content Index
> Fetch the complete content index at: https://www.hubwiz.com/blog/llms.txt
> Use this file to discover other available public pages before exploring further.

# 还在用npm？该迁移到pnpm了！
- URL: https://www.hubwiz.com/blog/still-using-npm-it-is-time-to-move-to-pnpm/
- Published: 2026-05-31T02:55:18.000Z
- Updated: 2026-05-31T02:55:18.000Z
- Description: 在pnpm 11于2026年4月下旬发布之后，npm和pnpm之间的差距从"值得考虑"变成了"难以忽视"。而这个差距不再仅仅是关于速度了。而是关于安全性。
- Author: admin
- Tags: TOOL, PNPM, #Import 2026-10-14 14:41

如果你在2026年仍然使用npm作为默认包管理器，我不怪你。npm能用。它是默认的。每个教程都用它。它随Node.js一起打包，换掉它感觉就像那些永远不会进入冲刺的低优先级任务。

但在pnpm 11于2026年4月下旬发布之后，npm和pnpm之间的差距从"值得考虑"变成了"难以忽视"。而这个差距不再仅仅是关于速度了。而是关于安全性。

让我带你了解一下为什么我把所有项目都迁移到了pnpm，以及为什么你大概也应该这样做。

## 1、为什么大多数开发者从不质疑npm

诚实的答案是：惯性。npm随Node.js一起发布，所以它是你接触的第一个工具。你学会了`npm install`、`npm run`、`npm publish`，它能完成工作。当出问题时，Stack Overflow上有答案。当队友加入时，他们已经知道了。

但这种熟悉感是有代价的——这个代价只有在出问题时才会显现。而在2026年，随着供应链攻击变得越来越复杂，出问题的频率越来越高。

## 2、没人谈论的npm问题

以下是典型的npm供应链攻击在实践中是如何展开的：

一个维护者的token被泄露。攻击者发布了一个恶意补丁——比如一个流行工具包的`v1.2.1`版本。你的CI/CD流水线通过cron定时运行，通过semver范围如`^1.2.0`获取了这个新版本，并执行了一个`postinstall`脚本，悄悄地从你的环境中窃取了密钥。

等到npm注册表检测到并撤下这个恶意版本时，你的流水线已经被攻击了。

这个模式在最近的**Mini Shai-Hulud**等活动中出现，该活动同时攻击了npm、PyPI和Packagist上的包。攻击使用安装时钩子下载了一个Bun运行时，并运行了一个针对CI/CD密钥的混淆凭证窃取器。

## 3、pnpm的不同之处

多年来，pnpm一直比npm更快、更节省磁盘空间。如果你从未使用过它，简单来说：pnpm使用内容寻址存储和硬链接在项目之间共享包，所以你不需要在五个仓库中下载五次同一版本的React。仅此一点就节省了大量的磁盘空间和安装时间。

但速度和效率现在是基本的入门条件。让pnpm 11真正有趣的是它默认做了什么。

> npm 11：安全作为默认配置，而非可选配置

### 3.1 24小时规则：minimumReleaseAge

这是pnpm 11中最有影响力的变化，而且它简单得漂亮。

当你运行`pnpm install`时，任何发布不到24小时的包版本都不会被解析。它处于冷却期。

为什么这很重要？因为大多数供应链攻击依赖于速度。攻击者的窗口很窄：发布恶意版本，等待自动化流水线在注册表发现并删除之前拉取它。这个窗口通常只有几个小时。

24小时的冷却意味着，等到pnpm甚至考虑安装新发布的版本时，安全社区已经有时间标记它。Socket.dev、Snyk等工具主动监控npm注册表。大多数恶意版本会在几小时内被发现和撤下。

这并不意味着你完全免疫。但它显著缩小了爆炸半径。

如果你需要立即拉取一个合法的紧急发布，你可以排除特定的包：

npm没有等价功能。它安装现在可用的任何东西。

### 3.2 阻断隐藏攻击路径：blockExoticSubdeps

这是一个大多数开发者从未想过的攻击向量：外来子依赖。

你从npm注册表安装的直接依赖可能本身会从GitHub仓库、tarball URL或私有SSH链接拉取传递性依赖。这些"外来"来源绕过了标准的注册表审计跟踪。它们更难扫描、更难验证，是一种有充分记录的将恶意代码隐藏在依赖树深处的方式。

pnpm 11现在默认设置`blockExoticSubdeps: true`。传递性依赖只能从你配置的注册表解析。如果子依赖试图从GitHub仓库或原始URL拉取，pnpm会停止安装。

npm完全不执行这个边界。你树中的任何包可以从任何地方拉取其子依赖。

### 3.3 控制什么可以运行：allowBuilds

生命周期脚本——`preinstall`、`postinstall`、`prepare`——是大多数恶意软件在安装时执行的方式。攻击者发布一个包，添加一个`postinstall`脚本，当你运行`pnpm install`时，该脚本以你的用户权限运行。

pnpm 10已经在这方面采取了强硬立场，禁用了依赖中`postinstall`脚本的自动执行。pnpm 11进一步用单一的、干净的`allowBuilds`映射替换了一组碎片化的遗留标志（`onlyBuiltDependencies`、`neverBuiltDependencies`、`ignoredBuiltDependencies`）：

你精确地定义哪些依赖被允许运行构建脚本。其他所有都被默认阻止。这强制了一个显式的信任模型：你不再希望一个包没有恶意的`postinstall`，你在主动决定哪些包可以在你的机器上运行代码。

npm的做法？生命周期脚本默认为所有东西运行，除非你传递`--ignore-scripts`或手动配置例外。那个标志会破坏很多合法工具，所以大多数团队从不启用它。

### 3.4 信任策略：trustPolicy

pnpm 11还引入了`trustPolicy`设置。当设置为`no-downgrade`时，如果一个包的信任级别相比之前的版本降低了——例如，它之前由经过验证的发布者发布，但最新版本缺少出处或签名——pnpm将拒绝安装它。

这听起来很小众，但它实际上是一个非常真实的攻击面。攻击者入侵维护者账户后经常发布一个新版本，该版本缺少与之前版本相同的签名过程。信任策略检查会自动捕获这个异常。

### 3.5 pnpm 11中还有什么变化

供应链安全占据了头条，但pnpm 11还有几个其他值得了解的改进。

**原生发布和注册表命令。** 以前，`pnpm publish`和相关命令在底层委托给npm CLI。pnpm 11原生处理所有这些——`login`、`logout`、`view`、`deprecate`、`unpublish`、`dist-tag`和`version`。不再需要npm依赖。

**内置SBOM生成。**`pnpm sbom`以CycloneDX 1.7或SPDX 2.3 JSON格式生成软件物料清单。对于受监管行业的团队或进行供应商安全审查的团队，这是一个重要的补充。

**SQLite支持的存储（Store v11）。** 之前的存储每个包使用一个JSON文件来跟踪索引。Store v11用单个SQLite数据库替换了它，减少了系统调用，安装速度明显更快。在热安装（缓存和lockfile已存在）时，pnpm 11大约在2.3秒内完成。

**隔离的全局安装。** 运行`pnpm add -g`现在将每个全局包放在自己隔离的目录中，有各自的`node_modules`和lockfile。不再有全局安装工具之间的奇怪版本冲突。

**需要Node.js 22。** pnpm 11放弃了对Node.js 18、19、20和21的支持。它现在也是纯ESM。如果你仍然在CI上使用旧版Node版本，迁移前需要为此做好计划。

### 3.6 pnpm 12即将带来什么

这值得一提，因为发展方向很重要：pnpm v12将引入**Pacquet**，一个基于Rust的安装引擎，负责获取和链接。早期基准测试显示热安装从2.3秒（pnpm 11）降到Rust引擎下不到1秒。冷安装（无缓存，无`node_modules`）从4.7秒降到约3.1秒。

Pacquet尚未准备好投入生产，但方向是明确的。pnpm正在积极投资于性能，其程度是npm根本无法比拟的。

## 4、从npm迁移到pnpm

如果你被说服了，以下是如何开始。迁移很简单。

**安装pnpm：**

或者使用独立安装器：

**导入你现有的npm项目：**

这将你的`package-lock.json`转换为`pnpm-lock.yaml`。你的`package.json`不会改变。

**安装依赖：**

**更新你的CI/CD脚本。** 将`npm install`替换为`pnpm install`，将`npm run`替换为`pnpm run`（或直接用`pnpm`）。大多数npm脚本直接兼容。

**在`pnpm-workspace.yaml`中配置你的安全默认设置：**

主要需要注意的是：pnpm默认使用更严格的模块解析。你访问了但没有在`package.json`中声明的包（幻影依赖）将会失败。这实际上是一件好事——它暴露了隐藏的依赖——但可能需要你在代码库中做一些小修复。

## 5、npm vs pnpm：快速对比

| 特性                 | npm      | pnpm              |
| ------------------ | -------- | ----------------- |
| 磁盘使用               | 跨项目重复存储包 | 使用硬链接的共享存储        |
| 安装速度               | 基线       | 更快（v11使用SQLite存储） |
| minimumReleaseAge  | 不可用      | v11默认24小时         |
| blockExoticSubdeps | 不可用      | v11默认启用           |
| 构建脚本控制             | 默认全部运行   | 通过allowBuilds选择加入 |
| 信任策略               | 不可用      | no-downgrade选项    |
| SBOM生成             | 不可用      | v11内置             |
| 原生发布               | 是        | 是（v11，不再依赖npm）    |

## 6、你应该切换吗？

如果你运行的是个人项目或没有CI/CD流水线的小型应用，紧迫性较低。npm会继续工作。

但如果你在管理生产基础设施、运行自动安装依赖的CI/CD流水线，或者在一个跨多个仓库的团队中工作——pnpm 11中的安全默认设置不是锦上添花。它们是那种保护——如果npm三年前就默认提供的话，本可以防止许多高知名度事件。

迁移成本低。持续维护差异很小。安全姿态改善显著。

pnpm已经有一段时间是更好的包管理器了。有了第11版，它也是更安全的一个。

---

原文链接: [You Should Move to pnpm from npm Now](https://blog.prateekjain.dev/you-should-move-to-pnpm-from-npm-now-6e84b6cc7778?ref=hubwiz.com)

汇智网翻译整理，转载请标明出处