npm 包管理
npm(Node Package Manager)是 Node.js 的默认包管理器,也是世界上最大的软件注册表。本章介绍 npm 的核心功能和使用技巧。
npm 简介
什么是 npm
npm 提供三个主要功能:
- 包注册表:托管开源 JavaScript 包
- 命令行工具:安装和管理包
- 包开发平台:发布和维护自己的包
npm vs yarn vs pnpm
| 特性 | npm | yarn | pnpm |
|---|---|---|---|
| 安装速度 | 中等 | 快 | 最快 |
| 磁盘空间 | 每个项目独立安装 | 每个项目独立安装 | 全局存储+符号链接 |
| 幽灵依赖 | 有 | 有 | 无 |
| lock 文件 | package-lock.json | yarn.lock | pnpm-lock.yaml |
| monorepo | workspaces | workspaces | workspace + 内置支持 |
package.json 详解
创建 package.json
# 交互式创建
npm init
# 使用默认值创建
npm init -y
# 使用预设配置创建
npm init -y --scope=@myorg
完整配置示例
{
"name": "@myorg/my-package",
"version": "1.0.0",
"description": "一个示例包",
"keywords": ["nodejs", "example"],
"homepage": "https://github.com/myorg/my-package#readme",
"bugs": {
"url": "https://github.com/myorg/my-package/issues"
},
"license": "MIT",
"author": {
"name": "Your Name",
"email": "[email protected]",
"url": "https://example.com"
},
"contributors": [],
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"./utils": {
"import": "./dist/utils.mjs",
"require": "./dist/utils.js"
}
},
"files": ["dist", "README.md", "LICENSE"],
"scripts": {
"start": "node index.js",
"dev": "node --watch index.js",
"build": "tsc",
"test": "node --test",
"lint": "eslint src/",
"format": "prettier --write .",
"prepare": "husky install"
},
"dependencies": {
"express": "^4.18.2",
"lodash": "^4.17.21"
},
"devDependencies": {
"typescript": "^5.0.0",
"eslint": "^8.50.0",
"prettier": "^3.0.0"
},
"peerDependencies": {
"react": ">=17.0.0"
},
"optionalDependencies": {
"fsevents": "^2.3.0"
},
"engines": {
"node": ">=18.0.0",
"npm": ">=9.0.0"
},
"os": ["linux", "darwin"],
"cpu": ["x64", "arm64"],
"repository": {
"type": "git",
"url": "git+https://github.com/myorg/my-package.git"
},
"type": "module",
"sideEffects": false
}
依赖类型
| 类型 | 用途 | 安装命令 |
|---|---|---|
dependencies | 生产环境依赖 | npm install pkg |
devDependencies | 开发环境依赖 | npm install -D pkg |
peerDependencies | 对等依赖 | 手动添加 |
optionalDependencies | 可选依赖 | 手动添加 |
bundledDependencies | 打包依赖 | 手动添加 |
版本号规则
npm 使用语义化版本(SemVer):主版本.次版本.补丁版本
版本范围符号:
| 符号 | 含义 | 示例 |
|---|---|---|
^ | 兼容版本(不改变主版本) | ^1.2.3 → >=1.2.3 <2.0.0 |
~ | 近似版本(不改变次版本) | ~1.2.3 → >=1.2.3 <1.3.0 |
> / >= | 大于/大于等于 | >1.2.3 |
< / <= | 小于/小于等于 | <2.0.0 |
| ` | ` | |
- | 范围 | 1.0.0 - 2.0.0 |
* | 任意版本 | * |
latest | 最新版本 | latest |
常用命令
安装依赖
# 安装所有依赖
npm install
# 安装生产依赖
npm install express
# 安装开发依赖
npm install -D typescript
# 安装指定版本
npm install [email protected]
# 安装最新版本
npm install express@latest
# 全局安装
npm install -g nodemon
# 安装特定范围的版本
npm install express@">=4.0.0 <5.0.0"
卸载依赖
# 卸载依赖
npm uninstall express
# 卸载开发依赖
npm uninstall -D typescript
# 卸载全局包
npm uninstall -g nodemon
更新依赖
# 检查可更新的包
npm outdated
# 更新所有依赖(在版本范围内)
npm update
# 更新到最新版本(可能超出范围)
npm install express@latest
# 全局更新
npm update -g
查看包信息
# 查看包信息
npm view express
# 查看特定版本信息
npm view [email protected]
# 查看所有可用版本
npm view express versions
# 查看包的依赖
npm view express dependencies
# 查看本地安装的包
npm list
# 查看全局安装的包
npm list -g --depth=0
运行脚本
# 运行脚本
npm run start
npm run build
npm run test
# 简写(仅限特定脚本)
npm start
npm test
# 传递参数
npm run test -- --coverage
# 并行/串行运行多个脚本
npm-run-all build:*
npm scripts 进阶
生命周期脚本
{
"scripts": {
"preinstall": "echo '安装前执行'",
"postinstall": "echo '安装后执行'",
"prepare": "npm run build",
"prestart": "echo '启动前执行'",
"start": "node index.js",
"poststart": "echo '启动后执行'"
}
}
跨平台脚本
使用跨平台工具替代平台特定命令:
{
"scripts": {
"clean": "rimraf dist",
"copy": "cpy src/** dist",
"env": "cross-env NODE_ENV=production",
"mkdir": "mkdirp dist"
},
"devDependencies": {
"rimraf": "^5.0.0",
"cpy-cli": "^5.0.0",
"cross-env": "^7.0.0",
"mkdirp": "^3.0.0"
}
}
钩子脚本
{
"scripts": {
"lint": "eslint src/",
"test": "node --test",
"precommit": "lint-staged",
"prepush": "npm test"
},
"devDependencies": {
"husky": "^8.0.0",
"lint-staged": "^14.0.0"
}
}
发布包
准备发布
- 注册 npm 账号
# 注册
npm adduser
# 或登录已有账号
npm login
- 配置 package.json
{
"name": "my-awesome-package",
"version": "1.0.0",
"main": "dist/index.js",
"files": ["dist", "README.md", "LICENSE"]
}
- 创建 .npmignore
# 忽略不需要发布的文件
src/
tests/
.*rc
*.log
node_modules/
发布流程
# 检查将要发布的文件
npm pack --dry-run
# 发布
npm publish
# 发布到私有仓库
npm publish --registry=https://registry.mycompany.com
# 发布预发布版本
npm publish --tag beta
# 发布 scoped 包(默认私有)
npm publish --access public
版本管理
# 更新补丁版本 1.0.0 -> 1.0.1
npm version patch
# 更新次版本 1.0.0 -> 1.1.0
npm version minor
# 更新主版本 1.0.0 -> 2.0.0
npm version major
# 预发布版本
npm version prerelease --preid=beta # 1.0.0 -> 1.0.1-beta.0
# 自定义提交信息
npm version patch -m "Upgrade to %s for reasons"
撤销发布
# 弃用包
npm deprecate my-package "此包已弃用,请使用 new-package"
# 删除版本(发布 24 小时内)
npm unpublish [email protected]
# 删除整个包
npm unpublish my-package --force
Workspaces(工作区)
npm 7+ 支持 monorepo:
{
"name": "my-monorepo",
"workspaces": [
"packages/*"
]
}
目录结构:
my-monorepo/
├── package.json
├── packages/
│ ├── core/
│ │ └── package.json
│ └── cli/
│ └── package.json
└── node_modules/
└── @my-org/
├── core -> ../../packages/core
└── cli -> ../../packages/cli
工作区命令:
# 在特定工作区执行命令
npm run test --workspace=packages/core
# 在所有工作区执行
npm run test --workspaces
# 安装依赖到特定工作区
npm install lodash -w packages/core
.npmrc 配置
创建 .npmrc 文件配置 npm:
# 镜像源
registry=https://registry.npmmirror.com
# 私有包配置
@mycompany:registry=https://npm.mycompany.com
//npm.mycompany.com/:_authToken=${NPM_TOKEN}
# 代理配置
proxy=http://proxy.company.com:8080
https-proxy=http://proxy.company.com:8080
# 缓存配置
cache=/path/to/cache
# 其他配置
save-exact=true
package-lock=false
engine-strict=true
常见问题
依赖冲突
# 查看依赖树
npm ls express
# 查看重复依赖
npm dedupe
# 强制重新安装
rm -rf node_modules package-lock.json
npm install
权限问题
# 修改 npm 默认目录
mkdir ~/.npm-global
npm config set prefix '~/.npm-global'
# 添加到 PATH
export PATH=~/.npm-global/bin:$PATH
清除缓存
# 清除缓存
npm cache clean --force
# 验证缓存
npm cache verify
小结
本章我们学习了:
- package.json 配置:依赖类型、版本号、scripts
- 常用命令:安装、卸载、更新、查看包信息
- npm scripts:生命周期、跨平台、钩子
- 发布包:准备、发布、版本管理
- Workspaces:monorepo 支持
- 配置管理:.npmrc 文件
练习
- 创建一个 npm 包并发布到 npm(可使用 scoped 包)
- 配置 husky 和 lint-staged 实现提交前检查
- 使用 workspaces 创建一个 monorepo 项目
- 实现一个 CLI 工具并通过 npm 全局安装使用