包管理器完全指南:NPM、Yarn、PNPM、Bun
NPM (Node Package Manager)
NPM 是 Node.js 默认的包管理器,也是世界上最大的软件注册表。
安装与初始化
# 检查版本
npm --version
# 或
npm -v
# 初始化项目(交互式)
npm init
# 快速初始化(使用默认值)
npm init -y
# 安装所有依赖
npm install
# 或
npm i包安装
# 安装到 dependencies(运行时依赖)
npm install express
npm install lodash axios moment
npm i <package-name>
# 安装到 devDependencies(开发依赖)
npm install --save-dev typescript jest eslint
npm install -D @types/node @types/express
npm i -D vite
# 全局安装(命令行工具)
npm install -g nodemon typescript create-react-app
npm i -g pnpm yarn
# 安装特定版本
npm install express@4.17.1
npm install lodash@^4.17.0 # 兼容版本
npm install axios@~0.21.0 # 补丁版本
# 从 GitHub 安装
npm install git+https://github.com/user/repo.git
npm install user/repo
npm install user/repo#branch
# 从本地路径安装
npm install ./local-package
npm install /path/to/package包卸载
# 卸载包
npm uninstall express
npm uninstall -D typescript
npm uninstall -g nodemon
# 卸载多个包
npm uninstall lodash axios moment包更新
# 检查过时依赖
npm outdated
# 更新到符合 package.json 中版本范围的最新版本
npm update
# 更新全局包
npm update -g typescript
# 交互式升级(使用 npx)
npx npm-check-updates -u
npm installnpm scripts
{
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js",
"build": "tsc && vite build",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"lint": "eslint src --ext .ts,.js",
"lint:fix": "eslint src --ext .ts,.js --fix",
"format": "prettier --write 'src/**/*.{ts,js}'",
"clean": "rm -rf dist node_modules/.cache",
"prebuild": "npm run clean",
"postinstall": "npm run build",
"deploy": "npm run build && node deploy.js"
}
}# 运行脚本
npm run dev
npm run build
npm test # 特殊:不需要 run
# 传递参数
npm run test -- --watch
npm run build -- --mode production
# 生命周期脚本
npm install # 会自动执行 preinstall -> install -> postinstall
npm publish # 会自动执行 prepack -> prepare -> postpack
# 环境变量
NODE_ENV=production npm run build
# 跨平台环境变量(使用 cross-env)
npm install -D cross-env
cross-env NODE_ENV=production npm run buildpackage.json 详解
{
"name": "my-project",
"version": "1.0.0",
"description": "项目描述",
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"type": "module",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs",
"types": "./dist/index.d.ts"
},
"./package.json": "./package.json"
},
"files": [
"dist",
"README.md",
"LICENSE"
],
"scripts": {
"build": "tsc",
"test": "jest"
},
"keywords": [
"typescript",
"library"
],
"author": "张三 <zhangsan@example.com>",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/user/repo.git"
},
"bugs": {
"url": "https://github.com/user/repo/issues"
},
"homepage": "https://github.com/user/repo#readme",
"dependencies": {
"express": "^4.18.0"
},
"devDependencies": {
"typescript": "^5.0.0"
},
"peerDependencies": {
"react": ">=16.8.0"
},
"optionalDependencies": {
"fsevents": "^2.3.0"
},
"engines": {
"node": ">=18.0.0",
"npm": ">=8.0.0"
},
"os": [
"darwin",
"linux"
],
"cpu": [
"x64",
"arm64"
],
"private": true
}字段说明:
name: 包名,发布到 npm 时必须唯一version: 语义化版本号 (major.minor.patch)description: 包描述,帮助他人了解包的用途main: CommonJS 入口文件module: ESM 入口文件(现代打包工具优先使用)types: TypeScript 类型定义文件type:"module"启用 ESM,"commonjs"使用 CJSexports: 条件导出,精确控制包的入口files: 发布到 npm 时包含的文件/目录scripts: 可执行的命令脚本keywords: 关键词,帮助他人搜索包dependencies: 生产环境依赖devDependencies: 开发环境依赖peerDependencies: 对等依赖,要求宿主项目提供optionalDependencies: 可选依赖,安装失败不报错engines: 指定 Node.js 和 npm 版本要求os/cpu: 指定操作系统和 CPU 架构限制private: 设为true防止意外发布
版本语义 (SemVer)
# 版本格式:major.minor.patch (主版本.次版本.补丁)
# 例如:1.2.3
# 精确版本
"lodash": "4.17.21"
# 兼容版本(^):允许次版本和补丁版本更新
"express": "^4.18.0" # >=4.18.0 <5.0.0
# 补丁版本(~):只允许补丁版本更新
"axios": "~1.4.0" # >=1.4.0 <1.5.0
# 范围
"lodash": ">=4.0.0 <5.0.0"
"lodash": "4.x" # >=4.0.0 <5.0.0
"lodash": "4.17.x" # >=4.17.0 <4.18.0
# 特殊标签
"lodash": "latest" # 最新版本
"lodash": "next" # 下一个版本(可能是 beta)
"lodash": "*" # 任何版本(危险!)
# 预发布版本
"lodash": "5.0.0-beta.1"npm 配置
# 查看配置
npm config list
npm config list -l # 查看所有配置
# 设置配置
npm config set registry https://registry.npmmirror.com
npm config set init-author-name "张三"
npm config set save-exact true
# 获取配置
npm config get registry
# 删除配置
npm config delete registry
# 使用 .npmrc 文件
# 项目级 .npmrc
registry=https://registry.npmmirror.com
save-exact=true
# 用户级 ~/.npmrc
//registry.npmjs.org/:_authToken=your-token-here
# 临时使用镜像
npm install --registry=https://registry.npmmirror.com发布包
# 登录
npm login
npm whoami # 检查当前用户
# 发布
npm publish
npm publish --tag beta # 发布为 beta 版本
npm publish --access public # 发布公共包(对于 scope 包)
# 取消发布(72 小时内)
npm unpublish <package>@<version>
# 废弃版本
npm deprecate <package>@<version> "此版本已废弃,请升级到新版本"
# 管理标签
npm dist-tag add <package>@<version> <tag>
npm dist-tag ls <package>
npm dist-tag rm <package> <tag>Yarn
Yarn 是 Facebook 开发的替代包管理器,速度更快且更可靠。
安装
# 通过 npm 安装
npm install -g yarn
# 通过 Homebrew (macOS)
brew install yarn
# 通过 Corepack(Node.js 16.10+)
corepack enable
corepack prepare yarn@stable --activateYarn Classic (v1) vs Yarn Berry (v2+)
# 检查版本
yarn --version
# 初始化项目
yarn init
yarn init -y # 快速初始化
# 安装依赖
yarn install
yarn # 简写
# 添加依赖
yarn add express
yarn add -D typescript # 开发依赖
yarn add -W typescript # 工作区根目录添加(monorepo)
# 添加特定版本
yarn add express@^4.18.0
yarn add lodash@~4.17.0
# 升级依赖
yarn upgrade express
yarn upgrade # 升级所有
# 移除依赖
yarn remove express
# 全局安装
yarn global add typescript
yarn global bin # 查看全局 bin 路径
# 运行脚本
yarn dev
yarn build
yarn testYarn Berry (v2+) 特性
# 初始化 Berry 版本
yarn set version berry
yarn set version stable
# Plug'n'Play (PnP) 模式
# 不使用 node_modules,直接通过 .pnp.cjs 解析依赖
yarn install
# 恢复 node_modules(如果需要)
# .yarnrc.yml
nodeLinker: node-modules
# Workspaces(工作区)
# package.json
{
"workspaces": [
"packages/*"
]
}
# 在工作区中运行命令
yarn workspace package-name build
yarn workspaces foreach run build
# 延迟要求(Lazy requirements)
# yarn.lock 会记录所有依赖的解析结果Yarn vs NPM 命令对照
| 功能 | npm | yarn |
|---|---|---|
| 初始化 | npm init | yarn init |
| 安装所有 | npm install | yarn |
| 添加依赖 | npm install <pkg> | yarn add <pkg> |
| 添加开发依赖 | npm i -D <pkg> | yarn add -D <pkg> |
| 移除依赖 | npm uninstall <pkg> | yarn remove <pkg> |
| 全局安装 | npm i -g <pkg> | yarn global add <pkg> |
| 运行脚本 | npm run <script> | yarn <script> |
| 更新依赖 | npm update | yarn upgrade |
| 检查过时 | npm outdated | yarn outdated |
PNPM
PNPM 是"快速、节省磁盘空间的包管理器",使用硬链接和符号链接来节省磁盘空间。
安装
# 通过 npm 安装
npm install -g pnpm
# 通过 Homebrew (macOS)
brew install pnpm
# 通过独立安装程序
curl -fsSL https://get.pnpm.io/install.sh | sh -
# Windows
Invoke-WebRequest -Uri https://get.pnpm.io/install.ps1 | Invoke-Expression基本使用
# 初始化项目
pnpm init
# 安装依赖
pnpm install
pnpm i
# 添加依赖
pnpm add express
pnpm add -D typescript
pnpm add -g pnpm # 全局安装
# 移除依赖
pnpm remove express
pnpm rm express
# 更新依赖
pnpm update
pnpm up
# 运行脚本
pnpm dev
pnpm build
pnpm run dev # 也可以
# 执行命令
pnpm exec tsc # 使用本地安装的 tsc
pnpm dlx create-react-app my-app # 临时执行PNPM 优势
1. 磁盘空间节省
# 查看 pnpm store 大小
pnpm store path
du -sh $(pnpm store path)
# 清理 store
pnpm store prune2. 严格的依赖管理
// .npmrc
shamefully-hoist=false # 不提升依赖到根目录(默认)
strict-peer-dependencies=true # 严格的 peerDependencies 检查3. 工作区支持(Monorepo)
// pnpm-workspace.yaml
packages:
- 'packages/*'
- 'apps/*'# 在工作区中运行
pnpm --filter package-name build
pnpm -r build # 递归运行所有包
# 添加依赖到特定包
pnpm --filter package-name add express4. 性能优化
# 并行运行
pnpm -r --parallel test
# 按拓扑顺序运行
pnpm -r build
# 只运行有变化的包
pnpm -r --filter '...HEAD~1' buildPNPM vs NPM vs Yarn
| 特性 | npm | yarn | pnpm |
|---|---|---|---|
| 安装速度 | 中等 | 快 | 最快 |
| 磁盘使用 | 高 | 高 | 低(硬链接) |
| node_modules 结构 | 扁平 | 扁平 | 严格隔离 |
| 幽灵依赖 | 可能 | 可能 | 不可能 |
| Monorepo 支持 | 一般 | 好 | 最好 |
| 离线缓存 | 有 | 有 | 有(store) |
Bun
Bun 是一个快速的全能 JavaScript 运行时,集 runtime、bundler、test runner、包管理器于一体。
安装
# macOS/Linux
curl -fsSL https://bun.sh/install | bash
# Windows (PowerShell)
powershell -c "irm bun.sh/install.ps1|iex"
# 通过 Homebrew
brew install oven-sh/bun/bun
# 通过 npm
npm install -g bun
# 检查版本
bun --version
bun upgrade # 更新包管理器
Bun 的包管理器比 npm 快 25-30 倍。
# 初始化项目
bun init
bun init -y
# 安装依赖
bun install
bun i
# 添加依赖
bun add express
bun add -d typescript # 开发依赖
bun add -g typescript # 全局安装
# 移除依赖
bun remove express
bun rm express
# 更新依赖
bun update
# 运行脚本
bun run dev
bun dev # 简写(bun run 可省略)
bun run build
# 执行二进制
bunx tsc # 类似 npx
bun x create-react-app my-app运行时特性
// 直接运行 TypeScript
bun run index.ts
// 直接运行 JSX
bun run app.tsx
// 内置 SQLite
import { Database } from "bun:sqlite";
const db = new Database("mydb.sqlite");
db.run("CREATE TABLE users (name TEXT, age INTEGER)");
// 内置文件 API
const file = Bun.file("input.txt");
const text = await file.text();
await Bun.write("output.txt", "Hello Bun!");
// 内置 HTTP 服务器
Bun.serve({
port: 3000,
fetch(req) {
return new Response("Hello from Bun!");
},
});
// 内置测试运行器
bun test
// 内置打包器
bun build ./index.ts --outdir ./dist
bun build ./index.ts --target=browser --outdir ./dist
bun build ./index.ts --target=node --outdir ./dist
// WebSocket 服务器
Bun.serve({
fetch(req, server) {
if (server.upgrade(req)) {
return;
}
return new Response("Upgrade required", { status: 426 });
},
websocket: {
message(ws, message) {
ws.send(`Echo: ${message}`);
},
},
});
// 环境变量
const apiKey = process.env.API_KEY;
// 或使用 Bun 的方式
const dbUrl = Bun.env.DATABASE_URL;
// 进程退出
process.exit(0);
// 子进程
const result = Bun.spawnSync(["echo", "hello"]);
console.log(result.stdout.toString());
// 异步子进程
const proc = Bun.spawn(["bun", "--version"]);
const output = await new Response(proc.stdout).text();性能对比
# 启动速度
time node -e "console.log('hello')"
time bun -e "console.log('hello')"
# 包安装速度
time npm install
time yarn install
time pnpm install
time bun install
# 运行速度
time node index.js
time bun index.js兼容性
Bun 兼容大多数 Node.js API 和 npm 包:
// Node.js API 兼容
import fs from "fs/promises";
import path from "path";
import { createServer } from "http";
// npm 包兼容
import express from "express";
import React from "react";
// TypeScript 支持(无需配置)
import { User } from "./types"; // 直接导入 .ts 文件
// JSX 支持
const App = () => <div>Hello</div>;
// 路径映射
// tsconfig.json 或 jsconfig.json
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
}
}何时使用 Bun
适合使用 Bun 的场景:
- 新项目,追求极致性能
- 需要快速启动的开发服务器
- 简单的脚本和工具
- 全栈应用(需要内置打包器和运行时)
谨慎使用的场景:
- 依赖大量原生 Node.js 模块
- 需要与旧版 Node.js 生态深度集成
- 生产环境需要极高的稳定性保证
迁移建议:
# 1. 测试项目兼容性
bun install # 看是否能安装所有依赖
# 2. 运行测试
bun test # 使用 Bun 运行测试
# 3. 开发
bun dev # 开发服务器
# 4. 构建
bun run build # 或使用 Vite 等工具
# 5. 生产部署
# 选项 1:使用 Bun 作为运行时
bun run dist/index.js
# 选项 2:编译为 Node.js 兼容代码
bun build ./index.ts --target=node --outdir ./dist
node dist/index.js选择建议
小型项目/快速原型
- 推荐: Bun 或 npm
- 理由: 简单快速,开箱即用
中型项目/团队协作
- 推荐: PNPM 或 Yarn
- 理由: 速度快,依赖管理严格,支持工作区
大型项目/Monorepo
- 推荐: PNPM
- 理由: 最佳的工作区支持,节省磁盘空间,严格的依赖隔离
企业级项目/生产环境
- 推荐: npm 或 PNPM
- 理由: 稳定性好,生态成熟,社区支持完善
个人项目/实验性项目
- 推荐: Bun
- 理由: 性能极佳,功能全面,开发体验好
最佳实践
1. 锁定版本
// package.json
{
"engines": {
"node": ">=18.0.0",
"pnpm": ">=8.0.0"
},
"packageManager": "pnpm@8.15.0"
}2. 使用锁文件
# 始终提交锁文件到版本控制
git add package-lock.json # npm
git add yarn.lock # yarn
git add pnpm-lock.yaml # pnpm
git add bun.lockb # bun3. 定期更新依赖
# 检查过时依赖
npm outdated
pnpm outdated
# 自动更新(使用工具)
npx npm-check-updates -u
npx taze -u # 更快的替代工具4. 审计安全漏洞
# npm
npm audit
npm audit fix
# pnpm
pnpm audit
# yarn
yarn audit5. 清理缓存
# npm
npm cache clean --force
# yarn
yarn cache clean
# pnpm
pnpm store prune
# bun
bun pm cache rm