npm - Node.js包管理器
1. 什么是npm?
npm(Node Package Manager)是Node.js的默认包管理器,也是世界上最大的开源软件注册表。它允许开发者共享和复用代码,管理项目依赖,并发布自己的包。npm已经成为JavaScript生态系统中不可或缺的工具,几乎所有Node.js项目都会使用npm来管理依赖。
1.1 npm的组成部分
- npm注册表:一个公共的包数据库,存储着数百万个开源包
- npm命令行工具:用于安装、发布、管理包的命令行工具
- npm网站:用于浏览包、管理用户账户的网站
1.2 npm的作用
- 安装依赖:从注册表下载并安装包
- 管理版本:控制包的版本,避免版本冲突
- 脚本运行:定义和运行项目脚本
- 发布包:将自己的代码发布为npm包
- 管理依赖树:处理包之间的依赖关系
2. 安装与配置
2.1 安装npm
npm通常随Node.js一起安装,当你安装Node.js时,npm也会被自动安装。
检查npm版本
npm -v
# 或
npm --version更新npm
# 更新到最新版本
npm install -g npm
# 更新到特定版本
npm install -g npm@6.14.152.2 配置npm
查看配置
# 查看所有配置
npm config list
# 查看特定配置
npm config get registry
npm config get prefix
npm config get cache设置配置
# 设置registry
npm config set registry https://registry.npmjs.org/
# 设置前缀(全局安装路径)
npm config set prefix "C:\\Users\\Username\\AppData\\Roaming\\npm" # Windows
npm config set prefix "~/.npm-global" # macOS/Linux
# 设置缓存目录
npm config set cache "C:\\Users\\Username\\AppData\\Roaming\\npm-cache" # Windows
npm config set cache "~/.npm" # macOS/Linux
# 设置代理
npm config set proxy http://proxy.company.com:8080
npm config set https-proxy http://proxy.company.com:8080
# 取消代理
npm config delete proxy
npm config delete https-proxy使用配置文件
npm的配置也可以通过.npmrc文件来设置,这个文件可以存在于以下位置:
- 项目级:
./.npmrc- 仅适用于当前项目 - 用户级:
~/.npmrc- 适用于当前用户的所有项目 - 全局级:
$npm_config_prefix/etc/npmrc- 适用于系统所有用户
# .npmrc示例
registry=https://registry.npmjs.org/
prefix=~/.npm-global
cache=~/.npm
# 身份验证信息
//registry.npmjs.org/:_authToken=your_auth_token3. 基本使用
3.1 初始化项目
# 交互式初始化
npm init
# 快速初始化(使用默认值)
npm init -y
npm init --yes
# 初始化并指定参数
npm init --scope=@username
npm init --private初始化后会生成package.json文件,包含项目的基本信息和依赖配置。
3.2 安装依赖
本地安装
本地安装的包会被安装到项目的node_modules目录中,仅在当前项目中可用。
# 安装单个包
npm install lodash
npm i lodash
# 安装指定版本
npm install lodash@4.17.21
# 安装多个包
npm install lodash express mongoose
# 安装并保存到 dependencies
npm install lodash --save
npm i lodash -S
# 安装并保存到 devDependencies
npm install lodash --save-dev
npm i lodash -D
# 安装并保存到 peerDependencies
npm install lodash --save-peer
npm i lodash -P
# 安装并保存到 optionalDependencies
npm install lodash --save-optional
npm i lodash -O全局安装
全局安装的包会被安装到npm的全局目录中,在任何项目中都可用。
# 全局安装
npm install -g nodemon
npm i -g nodemon
# 全局安装指定版本
npm install -g nodemon@2.0.15安装所有依赖
# 安装package.json中定义的所有依赖
npm install
npm i
# 只安装dependencies
npm install --production
# 跳过可选依赖
npm install --no-optional
# 强制重新安装
npm install --force3.3 查看依赖
# 查看已安装的包
npm list
npm ls
# 查看顶层依赖
npm list --depth=0
# 查看全局安装的包
npm list -g
npm list -g --depth=0
# 查看包的详细信息
npm view lodash
npm info lodash
# 查看包的版本
npm view lodash version
# 查看包的所有版本
npm view lodash versions
# 查看包的依赖
npm view lodash dependencies3.4 更新依赖
# 检查可更新的包
npm outdated
# 更新单个包
npm update lodash
npm up lodash
# 更新所有包
npm update
npm up
# 更新到最新版本
npm install lodash@latest
# 使用npm-check-updates更新到最新版本
npm install -g npm-check-updates
ncu -u
npm install3.5 卸载依赖
# 卸载本地包
npm uninstall lodash
npm un lodash
npm remove lodash
npm r lodash
# 卸载并从package.json中移除
npm uninstall --save lodash
npm un -S lodash
# 卸载开发依赖
npm uninstall --save-dev lodash
npm un -D lodash
# 卸载全局包
npm uninstall -g nodemon
npm un -g nodemon4. package.json文件
package.json是npm项目的核心配置文件,包含了项目的基本信息、依赖、脚本等。
4.1 package.json结构
{
"name": "my-project",
"version": "1.0.0",
"description": "我的项目描述",
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"test": "jest",
"build": "webpack"
},
"keywords": ["nodejs", "express", "mongodb"],
"author": "Your Name <your.email@example.com>",
"license": "MIT",
"dependencies": {
"express": "^4.17.1",
"mongoose": "^6.0.12"
},
"devDependencies": {
"nodemon": "^2.0.15",
"jest": "^27.3.1",
"webpack": "^5.64.4"
},
"peerDependencies": {
"react": "^17.0.2"
},
"optionalDependencies": {
"fsevents": "^2.3.2"
},
"engines": {
"node": ">=14.0.0",
"npm": ">=6.0.0"
},
"repository": {
"type": "git",
"url": "git+https://github.com/username/my-project.git"
},
"bugs": {
"url": "https://github.com/username/my-project/issues"
},
"homepage": "https://github.com/username/my-project#readme"
}4.2 字段说明
- name:项目名称,必须唯一,用于发布到npm
- version:项目版本,遵循语义化版本规范
- description:项目描述,用于npm搜索
- main:主入口文件
- scripts:定义项目脚本
- keywords:关键词,用于npm搜索
- author:作者信息
- license:许可证
- dependencies:生产环境依赖
- devDependencies:开发环境依赖
- peerDependencies:对等依赖
- optionalDependencies:可选依赖
- engines:指定Node.js和npm版本要求
- repository:代码仓库信息
- bugs:问题跟踪地址
- homepage:项目主页
4.3 版本号规则
npm使用语义化版本(SemVer)规范,版本号格式为:主版本.次版本.补丁版本
- 主版本:不兼容的API变更
- 次版本:向后兼容的功能添加
- 补丁版本:向后兼容的bug修复
版本范围
{
"dependencies": {
"package": "1.2.3", // 精确版本
"package": "^1.2.3", // 兼容版本(>=1.2.3 <2.0.0)
"package": "~1.2.3", // 补丁版本(>=1.2.3 <1.3.0)
"package": ">1.2.3", // 大于指定版本
"package": ">=1.2.3", // 大于等于指定版本
"package": "<1.2.3", // 小于指定版本
"package": "<=1.2.3", // 小于等于指定版本
"package": "1.2.x", // 任意1.2.x版本
"package": "*", // 任意版本
"package": "latest" // 最新版本
}
}5. 脚本管理
npm允许在package.json中定义脚本,方便执行各种任务。
5.1 运行脚本
# 运行脚本
npm run script-name
# 运行简写脚本(start, test, restart, stop)
npm start
npm test
npm restart
npm stop
# 传递参数给脚本
npm run build -- --watch
# 运行多个脚本
npm run script1 && npm run script25.2 预脚本和后脚本
npm支持预脚本(pre)和后脚本(post),当运行一个脚本时,会自动先运行对应的pre脚本,后运行对应的post脚本。
{
"scripts": {
"prebuild": "echo 开始构建...",
"build": "webpack",
"postbuild": "echo 构建完成!",
"pretest": "echo 开始测试...",
"test": "jest",
"posttest": "echo 测试完成!"
}
}当运行npm run build时,执行顺序为:
npm run prebuildnpm run buildnpm run postbuild
5.3 环境变量
在npm脚本中,可以使用环境变量,包括:
- npm内置变量:
npm_package_name,npm_package_version等 - 自定义变量:在运行脚本时设置
{
"scripts": {
"start": "echo 项目名称: $npm_package_name, 版本: $npm_package_version",
"dev": "NODE_ENV=development node index.js",
"prod": "NODE_ENV=production node index.js"
}
}使用cross-env
在Windows和Unix系统中,设置环境变量的语法不同,使用cross-env可以统一语法。
npm install --save-dev cross-env{
"scripts": {
"dev": "cross-env NODE_ENV=development node index.js",
"prod": "cross-env NODE_ENV=production node index.js"
}
}5.4 常用脚本示例
{
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"build": "webpack",
"build:watch": "webpack --watch",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"format": "prettier --write .",
"deploy": "npm run build && npm run test",
"clean": "rimraf dist node_modules",
"reinstall": "npm run clean && npm install",
"upgrade": "ncu -u && npm install"
}
}6. 依赖管理
6.1 依赖类型
- dependencies:生产环境依赖,应用运行时需要
- devDependencies:开发环境依赖,仅开发时需要
- peerDependencies:对等依赖,要求用户自行安装
- optionalDependencies:可选依赖,安装失败也不影响应用运行
- bundleDependencies:捆绑依赖,发布时会包含在包中
6.2 依赖树
当安装包时,npm会构建一个依赖树,处理包之间的依赖关系。
查看依赖树
# 查看依赖树
npm ls
# 查看特定包的依赖
npm ls lodash
# 查看扁平化的依赖
npm ls --prod --depth=0依赖冲突
当不同包依赖同一个包的不同版本时,可能会发生依赖冲突。npm会通过以下方式处理:
- 嵌套安装:将不同版本的包安装在各自的
node_modules目录中 - 扁平化:在可能的情况下,将依赖扁平化到顶层
6.3 package-lock.json
package-lock.json文件用于锁定依赖版本,确保在不同环境中安装相同版本的依赖。
作用
- 锁定版本:记录每个依赖的确切版本
- 锁定依赖树:记录完整的依赖树结构
- 加速安装:基于锁定文件快速安装依赖
生成和更新
- 当运行
npm install时,会自动生成或更新package-lock.json - 当修改
package.json中的依赖后,运行npm install会更新package-lock.json - 当使用
npm ci时,会严格按照package-lock.json安装依赖
6.4 npm ci
npm ci(clean install)是一个用于CI/CD环境的命令,它会:
- 删除现有的
node_modules目录 - 严格按照
package-lock.json安装依赖 - 不更新
package-lock.json - 比
npm install更快
# 使用npm ci安装依赖
npm ci
# 仅安装生产依赖
npm ci --only=production7. 发布包
7.1 准备发布
创建账号
- 在npm官网注册账号
- 或使用命令行注册
npm adduser
# 或
npm login配置包信息
确保package.json中的信息完整准确:
{
"name": "your-package-name",
"version": "1.0.0",
"description": "包的描述",
"main": "index.js",
"scripts": {
"test": "jest"
},
"keywords": ["keyword1", "keyword2"],
"author": "Your Name <your.email@example.com>",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/username/your-package.git"
},
"bugs": {
"url": "https://github.com/username/your-package/issues"
},
"homepage": "https://github.com/username/your-package#readme"
}创建README.md
# your-package-name
包的描述
## 安装
```bash
npm install your-package-name使用
const yourPackage = require('your-package-name');
// 使用示例API
方法1
描述
方法2
描述
许可证
MIT
### 7.2 发布包
```bash
# 检查包是否符合发布要求
npm publish --dry-run
# 发布包
npm publish
# 发布测试版本
npm version prerelease
npm publish --tag beta
# 发布到组织
npm publish --scope=@username
# 发布私有包
npm publish --access=private7.3 更新包
更新版本
# 更新补丁版本(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
# 更新预发布版本(1.0.0 → 1.0.1-beta.1)
npm version prerelease
# 设置特定版本
npm version 1.2.3发布更新
# 更新版本后发布
npm version patch
npm publish7.4 撤销发布
# 撤销发布的包
npm unpublish your-package-name@1.0.0
# 撤销整个包(谨慎使用)
npm unpublish your-package-name --force注意:撤销发布的包可能会影响依赖它的项目,应谨慎使用。
8. 高级功能
8.1 工作区(Workspaces)
工作区允许在一个仓库中管理多个相关的包,适用于monorepo项目。
配置工作区
{
"name": "monorepo",
"version": "1.0.0",
"private": true,
"workspaces": [
"packages/*",
"apps/*"
],
"scripts": {
"build": "npm run build --workspaces",
"test": "npm run test --workspaces"
}
}使用工作区
# 安装所有工作区的依赖
npm install
# 在特定工作区安装依赖
npm install lodash --workspace=packages/package1
# 运行特定工作区的脚本
npm run build --workspace=packages/package1
# 运行所有工作区的脚本
npm run build --workspaces8.2 钩子(Hooks)
npm支持钩子,可以在特定事件发生时执行自定义脚本。
安装钩子
npm install husky --save-dev配置钩子
# 初始化husky
npx husky install
# 添加钩子
npx husky add .husky/pre-commit "npm test"
npx husky add .husky/pre-push "npm run lint"8.3 缓存管理
npm会缓存安装过的包,加速后续安装。
管理缓存
# 查看缓存大小
npm cache ls --summary
# 清理缓存
npm cache clean --force
# 验证缓存
npm cache verify8.4 审计(Audit)
npm audit用于检查依赖中的安全漏洞。
# 运行审计
npm audit
# 自动修复漏洞
npm audit fix
# 仅修复生产依赖的漏洞
npm audit fix --only=prod
# 强制修复所有漏洞
npm audit fix --force
# 查看详细报告
npm audit --json > audit-report.json8.5 shrinkwrap
npm shrinkwrap命令用于生成npm-shrinkwrap.json文件,锁定依赖版本,类似于package-lock.json。
# 生成shrinkwrap文件
npm shrinkwrap
# 更新shrinkwrap文件
npm shrinkwrap --dev注意:package-lock.json是npm-shrinkwrap.json的超集,推荐使用package-lock.json。
9. 最佳实践
9.1 项目配置
- **使用
.gitignore**:忽略node_modules、npm-debug.log等文件 - 锁定版本:使用
package-lock.json或npm-shrinkwrap.json - 指定Node.js版本:在
package.json中设置engines字段 - 使用语义化版本:遵循SemVer规范
9.2 依赖管理
- 分离依赖类型:正确使用dependencies和devDependencies
- 定期更新依赖:使用
npm outdated检查更新 - 避免全局安装:优先本地安装,使用npx运行命令
- 使用固定版本:生产环境使用固定版本,避免意外更新
9.3 脚本管理
- 使用有意义的脚本名称:如build、test、lint等
- 使用预脚本和后脚本:组织复杂任务
- 使用npm-run-all:运行多个脚本
- 使用cross-env:跨平台设置环境变量
9.4 安全性
- 定期审计:使用
npm audit检查安全漏洞 - 使用安全的依赖:避免使用有已知漏洞的包
- 保护npm令牌:不要将
_authToken提交到版本控制 - 使用私有registry:企业环境使用私有npm registry
9.5 性能优化
- 使用npm ci:CI/CD环境使用
npm ci加速安装 - 清理缓存:定期清理npm缓存
- 使用pnpm:考虑使用pnpm提高安装速度
- 优化依赖树:减少不必要的依赖,避免版本冲突
10. 常见问题与解决方案
10.1 安装失败
问题:npm install失败
解决方案:
- 检查网络连接
- 检查npm配置(如registry)
- 清理缓存:
npm cache clean --force - 删除node_modules和package-lock.json,重新安装
- 使用管理员权限运行命令
10.2 依赖冲突
问题:依赖版本冲突
解决方案:
- 使用
npm ls查看依赖树 - 手动指定版本
- 使用
resolutions字段(Yarn)或overrides字段(npm 8+) - 考虑使用pnpm的依赖管理
10.3 脚本执行失败
问题:npm run脚本执行失败
解决方案:
- 检查脚本语法
- 检查依赖是否安装
- 检查环境变量
- 查看详细错误信息
10.4 发布失败
问题:npm publish失败
解决方案:
- 检查包名是否已存在
- 检查npm账号权限
- 检查package.json配置
- 检查网络连接
10.5 速度慢
问题:npm安装速度慢
解决方案:
- 使用国内镜像:
npm config set registry https://registry.npmmirror.com - 清理缓存:
npm cache clean --force - 使用pnpm或yarn
- 考虑使用缓存服务(如npm cache)
11. 总结
npm是Node.js生态系统中不可或缺的工具,它不仅是一个包管理器,还是一个项目管理工具,提供了丰富的功能来简化开发流程。通过本教程的学习,您应该已经掌握了npm的基本用法和高级功能,可以在实际项目中高效地使用npm来管理依赖、运行脚本、发布包等。
11.1 核心优势
- 丰富的包生态:访问世界上最大的开源软件注册表
- 强大的依赖管理:处理复杂的依赖关系
- 灵活的脚本系统:自动化各种开发任务
- 简单的发布流程:轻松分享和分发代码
- 广泛的社区支持:大量的文档和资源
11.2 适用场景
- Web开发:管理前端和后端依赖
- Node.js应用:构建和部署Node.js应用
- 命令行工具:开发和发布CLI工具
- 库开发:创建和发布可重用的库
- Monorepo项目:管理多包项目
11.3 未来发展
npm持续演进,未来的发展趋势包括:
- 更快的安装速度:优化依赖解析和安装过程
- 更好的monorepo支持:增强工作区功能
- 更强的安全性:改进漏洞检测和修复
- 更丰富的CLI功能:提供更多实用命令
- 更好的与现代工具集成:与ES模块、TypeScript等更好集成
通过不断学习和实践,您可以充分发挥npm的优势,提高开发效率,构建更高质量的项目。