npm 支持多种依赖类型,每种类型在 package.json 中有不同的作用和使用场景。
依赖类型
1. dependencies(生产依赖)
应用运行时必需的依赖,部署到生产环境时需要安装。
json{ "dependencies": { "express": "^4.18.0", "lodash": "^4.17.21", "axios": "^1.0.0" } }
安装命令:
bashnpm install <package> npm install <package> --save-prod npm install <package> -P
使用场景:
- Web 框架(Express、React、Vue)
- 工具库(lodash、moment)
- API 客户端(axios、fetch)
2. devDependencies(开发依赖)
仅在开发时需要的依赖,生产环境不需要。
json{ "devDependencies": { "jest": "^29.0.0", "eslint": "^8.0.0", "webpack": "^5.0.0", "nodemon": "^3.0.0" } }
安装命令:
bashnpm install <package> --save-dev npm install <package> -D
使用场景:
- 测试框架(Jest、Mocha)
- 代码检查工具(ESLint、Prettier)
- 构建工具(Webpack、Rollup)
- 开发服务器(nodemon)
3. peerDependencies(同伴依赖)
期望宿主项目提供的依赖,不会自动安装。
json{ "peerDependencies": { "react": "^18.0.0", "react-dom": "^18.0.0" } }
使用场景:
- 插件或库需要宿主提供核心库
- 避免重复安装相同版本的包
- 确保与宿主项目的兼容性
示例:React 组件库
json{ "name": "my-react-components", "peerDependencies": { "react": "^18.0.0", "react-dom": "^18.0.0" } }
4. optionalDependencies(可选依赖)
安装失败不会中断安装过程的依赖。
json{ "optionalDependencies": { "fsevents": "^2.3.0", "chokidar": "^3.5.0" } }
安装命令:
bashnpm install <package> --save-optional npm install <package> -O
使用场景:
- 平台特定的包(如 macOS 的 fsevents)
- 可选功能的增强包
- 不影响核心功能的依赖
5. bundledDependencies(打包依赖)
打包时包含的依赖,发布时会一起打包。
json{ "bundledDependencies": [ "my-internal-lib" ] }
注意:
- 必须在 dependencies 或 devDependencies 中声明
- 不能是可选依赖
- 会增加包的大小
package.json 核心字段
基本信息
json{ "name": "my-project", "version": "1.0.0", "description": "A sample project", "keywords": ["npm", "javascript", "node"], "author": "Your Name <email@example.com>", "license": "MIT", "homepage": "https://github.com/user/repo#readme", "repository": { "type": "git", "url": "https://github.com/user/repo.git" } }
入口和配置
json{ "main": "index.js", "module": "dist/index.esm.js", "types": "dist/index.d.ts", "bin": { "my-cli": "./bin/cli.js" }, "files": [ "dist", "README.md", "LICENSE" ], "directories": { "lib": "lib", "test": "test" } }
配置字段
json{ "config": { "port": 3000, "env": "development" }, "engines": { "node": ">=14.0.0", "npm": ">=6.0.0" }, "os": ["!win32"], "cpu": ["x64", "arm64"] }
私有和发布配置
json{ "private": true, "publishConfig": { "registry": "https://registry.npmjs.org", "access": "public" } }
工作区(Workspaces)
npm 7+ 支持工作区,用于管理 monorepo:
json{ "name": "my-monorepo", "version": "1.0.0", "workspaces": [ "packages/*" ], "scripts": { "install": "npm install -ws", "build": "npm run build -ws" } }
目录结构:
shellmy-monorepo/ ├── package.json ├── packages/ │ ├── package-a/ │ │ └── package.json │ └── package-b/ │ └── package.json
依赖解析策略
npm 使用嵌套依赖结构(node_modules):
shellnode_modules/ ├── package-a/ │ └── node_modules/ │ └── package-c/ └── package-b/ └── node_modules/ └── package-c/
解析规则:
- 首先查找当前包的 node_modules
- 然后查找父包的 node_modules
- 递归向上查找直到根目录
常见问题
1. 依赖冲突
当两个包需要不同版本的同一依赖时:
json{ "dependencies": { "package-a": "^1.0.0", // 需要 lodash@^4.0.0 "package-b": "^2.0.0" // 需要 lodash@^3.0.0 } }
npm 会安装两个版本的 lodash。
2. 依赖提升
npm 会尝试将依赖提升到更高级别以减少重复:
shellnode_modules/ ├── lodash/ // 提升到顶层 ├── package-a/ └── package-b/
3. 依赖锁定
使用 package-lock.json 确保依赖一致性:
json{ "lockfileVersion": 2, "packages": { "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-..." } } }
最佳实践
- 明确区分依赖类型:正确使用 dependencies 和 devDependencies
- 使用 peerDependencies:插件库应使用 peerDependencies
- 最小化依赖:只安装必要的包
- 定期更新:使用
npm outdated和npm audit - 锁定版本:提交 package-lock.json 到版本控制
- 使用工作区:大型项目使用 workspaces 管理 monorepo
- 文档化依赖:在 README 中说明主要依赖及其用途
常用命令
bash# 安装生产依赖 npm install <package> # 安装开发依赖 npm install <package> -D # 安装所有依赖 npm install # 只安装生产依赖 npm install --production # 检查依赖更新 npm outdated # 更新依赖 npm update # 检查安全漏洞 npm audit # 自动修复安全漏洞 npm audit fix
理解 npm 依赖类型和 package.json 配置对于管理项目依赖、优化包大小和确保项目稳定性至关重要。