Skip to content
On this page

npm 包管理基础

npm包管理是Node.js开发的核心技能。本章将详细介绍npm包的安装、卸载、更新等基础操作,以及如何有效管理项目依赖。

包的类型

按功能分类

  • 工具包:如webpackbabel等构建工具
  • 库包:如lodashmoment等工具库
  • 框架包:如expressreact等框架
  • 可执行包:如nodemonhttp-server等命令行工具

按作用域分类

  • 普通包:如lodash
  • 作用域包:如@babel/core@angular/core

安装包

基本安装命令

bash
# 安装包到dependencies(生产环境依赖)
npm install package-name
npm i package-name  # 简写

# 安装特定版本
npm install package-name@1.2.3
npm i package-name@^1.2.3  # 安装兼容版本
npm i package-name@~1.2.3  # 安装补丁版本

# 安装最新版本
npm install package-name@latest
npm i package-name@next     # 安装预发布版本

安装到不同依赖类型

bash
# 生产依赖(默认)
npm install package-name
npm install package-name --save

# 开发依赖
npm install package-name --save-dev
npm i package-name -D

# 可选依赖
npm install package-name --save-optional
npm i package-name -O

# 仅生产环境(移除开发依赖)
npm install --production
NODE_ENV=production npm install

本地包安装

bash
# 从本地路径安装
npm install ./path/to/local/package
npm install file:./path/to/local/package

# 从Git仓库安装
npm install git+https://github.com/user/repo.git
npm install git+ssh://git@github.com/user/repo.git
npm install user/repo#branch  # 安装特定分支

# 从tarball安装
npm install https://example.com/package.tgz

卸载包

bash
# 卸载包
npm uninstall package-name
npm un package-name
npm remove package-name
npm rm package-name

# 卸载开发依赖
npm uninstall package-name --save-dev
npm un package-name -D

# 卸载多个包
npm uninstall package1 package2 package3

更新包

检查更新

bash
# 检查过时的包
npm outdated

# 检查特定包
npm outdated package-name

# 查看可用版本
npm view package-name versions --json
npm view package-name@latest version

执行更新

bash
# 更新单个包
npm update package-name

# 更新所有包
npm update

# 更新到特定版本
npm install package-name@latest

# 使用npm-check-updates工具(需要先安装)
npx npm-check-updates
npx npm-check-updates -u  # 更新package.json
npm install  # 安装更新后的版本

依赖关系管理

dependencies vs devDependencies

json
{
  "dependencies": {
    // 生产环境必需的包
    "express": "^4.18.0",
    "lodash": "^4.17.21"
  },
  "devDependencies": {
    // 开发环境需要的包
    "jest": "^28.0.0",
    "webpack": "^5.72.0",
    "eslint": "^8.0.0"
  }
}

peerDependencies

json
{
  "peerDependencies": {
    // 宿主环境应提供的依赖
    "react": "^17.0.0 || ^18.0.0",
    "vue": "^3.0.0"
  },
  "peerDependenciesMeta": {
    "vue": {
      "optional": true
    }
  }
}

bundledDependencies

json
{
  "bundledDependencies": [
    // 发布时包含的依赖
    "package-name"
  ]
}

版本控制

语义化版本控制

json
{
  "dependencies": {
    // 允许补丁和次要版本更新,不允许主版本更新
    "package-a": "^1.2.3",
    
    // 只允许补丁版本更新
    "package-b": "~1.2.3",
    
    // 固定版本
    "package-c": "1.2.3",
    
    // 版本范围
    "package-d": ">=1.0.0 <2.0.0",
    
    // 通配符
    "package-e": "1.x",
    "package-f": "*"
  }
}

预发布版本

bash
# 安装alpha版本
npm install package-name@alpha

# 安装beta版本
npm install package-name@beta

# 安装特定预发布标签
npm install package-name@1.0.0-beta.1

node_modules结构

扁平化结构

npm使用扁平化策略来减少嵌套:

bash
# 安装后node_modules可能的结构
node_modules/
├── lodash/           # 直接依赖
├── express/          # 直接依赖
├── accepts/          # express的依赖
├── array-flatten/    # express的依赖
├── debug/            # 多个包的共同依赖
└── ms/               # debug的依赖

重复依赖处理

当不同版本的同一包被需要时:

bash
node_modules/
├── package-a/
│   └── node_modules/
│       └── lodash@4.17.20  # package-a需要的版本
├── package-b/
│   └── node_modules/
│       └── lodash@4.17.21  # package-b需要的版本
└── lodash@4.17.21          # 顶层版本

package-lock.json详解

package-lock.json确保依赖树的一致性:

{
  "name": "my-project",
  "version": "1.0.0",
  "lockfileVersion": 2,
  "requires": true,
  "packages": {
    "": {
      "name": "my-project",
      "version": "1.0.0",
      "dependencies": {
        "express": "^4.18.0"
      }
    },
    "node_modules/express": {
      "version": "4.18.1",
      "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz",
      "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL2g==",
      "requires": {
        "accepts": "~1.3.8",
        "array-flatten": "1.1.1"
      }
    }
  }
}

锁定文件最佳实践

# 总是提交package-lock.json到版本控制
git add package-lock.json

# 使用npm ci进行干净安装
npm ci  # 忽略node_modules,完全按照lockfile安装

# 验证lockfile完整性
npm audit

脚本包管理

安装并运行一次性工具

# 使用npx运行包而不安装
npx create-react-app my-app
npx serve .
npx http-server

# npx会临时安装包并运行,然后清理

本地安装的可执行文件

{
  "scripts": {
    "build": "webpack --mode production",
    "dev": "webpack serve --mode development",
    "lint": "eslint src/",
    "test": "jest"
  }
}

本地安装的包会自动添加到PATH,可以在scripts中直接使用。

工作区包管理

设置工作区

{
  "name": "my-workspace-project",
  "private": true,
  "workspaces": [
    "packages/*",
    "frontend",
    "backend"
  ]
}

工作区命令

# 在特定工作区安装包
npm install package-name --workspace=frontend

# 在所有工作区安装包
npm install package-name --workspaces

# 在特定工作区运行脚本
npm run build --workspace=frontend

# 在所有工作区运行脚本
npm run build --workspaces

# 递归运行脚本
npm run build --workspaces --if-present

包搜索和发现

搜索包

# 搜索包
npm search lodash
npm search --searchopts name,description "react component"

# 查看包信息
npm view package-name
npm view package-name --json
npm view package-name version
npm view package-name versions  # 查看所有版本

检查包内容

# 查看包文件列表
npm view package-name files

# 检查包大小
npm pack package-name  # 下载tarball而不安装
npm view package-name dist.tarball  # 获取tarball URL

依赖安全

安全审计

# 检查安全漏洞
npm audit

# 检查详细信息
npm audit --audit-level high

# 自动修复
npm audit fix

# 修复所有可能的问题(可能改变依赖版本)
npm audit fix --force

# 生成审计报告
npm audit --json > audit-report.json

安全最佳实践

# 定期检查依赖
npm outdated

# 使用npm-check更新依赖
npx npm-check -u

# 验证包的完整性
npm audit
npm fund  # 查看项目资助信息

性能优化

安装优化

# 使用生产模式安装(跳过devDependencies)
npm install --production

# 使用淘宝镜像加速
npm install --registry https://registry.npmmirror.com/

# 使用缓存
npm install --prefer-offline  # 优先使用缓存

清理和维护

# 验证缓存
npm cache verify

# 清理缓存
npm cache clean --force

# 删除node_modules并重新安装
rm -rf node_modules package-lock.json
npm install

通过掌握这些包管理基础,您可以更有效地管理项目依赖,确保项目的稳定性和安全性。