Files
xgj/npm-install/README.md

325 lines
9.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# npm 依赖安装与缓存 Action
这个 GitHub Action 自动处理 npm 依赖的缓存和安装支持多种包管理器npm、pnpm、yarn可以大幅提升 CI/CD 流水线的执行速度。
## ✨ 特性
- 🚀 **智能缓存**: 自动缓存 node_modules避免重复安装
- 📦 **多包管理器支持**: 支持 npm、pnpm、yarn自动检测标准锁文件
- 🎯 **灵活配置**: 可自定义缓存前缀、安装命令等
- 🔑 **精确 hash 控制**: 支持自定义缓存 hash确保依赖变化时缓存失效
- 🔄 **Git 集成**: 可选的 git stash 功能
- 📊 **详细输出**: 提供缓存命中状态和使用的缓存 key
- 🧰 **自动安装 pnpm**: 当选择 `package-manager: pnpm` 时,自动通过 `pnpm/action-setup@v4` 确保 pnpm 可用(可指定版本)
## 📋 输入参数
| 参数名 | 描述 | 是否必需 | 默认值 |
| ------------------- | ---------------------------- | -------- | -------------- |
| `package-manager` | 包管理器类型 (npm/pnpm/yarn) | 否 | `npm` |
| `pnpm-version` | pnpm 版本(`package-manager: pnpm` 时生效) | 否 | `9` |
| `cache-mode` | 缓存模式(`node_modules``store` | 否 | `node_modules` |
| `cache-prefix` | 缓存前缀名称 | 否 | `modules` |
| `node-modules-path` | node_modules 目录路径 | 否 | `node_modules` |
| `force-install` | 是否强制安装 | 否 | `false` |
| `enable-git-stash` | 安装后是否执行 git stash | 否 | `false` |
| `install-command` | 自定义安装命令(覆盖默认) | 否 | `''` |
| `install-args` | 附加到默认安装命令的参数(当未提供 `install-command` 时生效) | 否 | `''` |
| `cache-hash` | 缓存 hash 值(**推荐使用** | 否 | 自动计算 |
## 📤 输出参数
| 参数名 | 描述 |
| ----------- | ------------------------- |
| `cache-hit` | 是否命中缓存 (true/false) |
| `cache-key` | 使用的缓存 key |
| `cache-path` | 缓存路径(用于调试与复用) |
## 💡 重要提示
**强烈推荐使用 `cache-hash` 参数!**
使用 `cache-hash` 参数有以下优势:
-**精确控制**: 让你完全控制缓存失效的条件
-**环境兼容**: 避免在不同容器环境中 hash 计算不一致的问题
-**灵活组合**: 可以组合多个文件的 hash`package.json` + `package-lock.json` + `.nvmrc`
-**调试友好**: 在 workflow 中可以清楚看到使用的 hash 值
```yaml
# 推荐用法
with:
cache-hash: ${{ hashFiles('package-lock.json') }}
```
如果不提供 `cache-hash`action 会自动使用 `package.json` 作为 fallback但不如手动指定精确。
## 🚀 使用方法
### 基础用法 (npm)
```yaml
- name: 安装npm依赖
uses: actions/xgj/npm-install@v1
```
### 使用 pnpm
```yaml
- name: 安装pnpm依赖
uses: actions/xgj/npm-install@v1
with:
package-manager: "pnpm"
# 可选:指定 pnpm 版本(默认 9
pnpm-version: "9"
# 可选:切换为包管理器 store 缓存,提升复用率(首次仍需安装链接)
# cache-mode: "store"
# 可选:附加安装参数(当未设置 install-command 时生效)
# 例如:保持锁文件严格、忽略可选依赖
install-args: "--frozen-lockfile --no-optional"
```
### 强制安装 + Git Stash
```yaml
- name: 强制安装依赖并stash
uses: actions/xgj/npm-install@v1
with:
package-manager: "npm"
force-install: "true"
enable-git-stash: "true"
```
### 自定义缓存配置
```yaml
- name: 自定义缓存安装
uses: actions/xgj/npm-install@v1
with:
package-manager: "yarn"
cache-prefix: "my-project"
node-modules-path: "./frontend/node_modules"
```
### 自定义安装命令
```yaml
- name: 使用自定义命令安装
uses: actions/xgj/npm-install@v1
with:
install-command: "npm ci --only=production"
```
### 仅附加参数(不覆盖命令)
```yaml
# npm 示例:追加只生产依赖
- name: 安装npm仅生产依赖
uses: actions/xgj/npm-install@v1
with:
package-manager: npm
install-args: "--only=production"
# pnpm 示例:严格锁文件 + 忽略可选依赖
- name: 安装pnpm严格锁文件
uses: actions/xgj/npm-install@v1
with:
package-manager: pnpm
install-args: "--frozen-lockfile --no-optional"
# yarn 示例:纯安装(禁用脚本)
- name: 安装yarn禁用脚本
uses: actions/xgj/npm-install@v1
with:
package-manager: yarn
install-args: "--ignore-scripts"
```
### 使用自定义缓存 hash推荐用法
```yaml
# 推荐手动指定缓存hash确保精确的缓存管理
- name: 安装npm依赖
uses: actions/xgj/npm-install@v1
with:
package-manager: "npm"
cache-hash: ${{ hashFiles('package-lock.json') }}
# pnpm项目
- name: 安装pnpm依赖
uses: actions/xgj/npm-install@v1
with:
package-manager: "pnpm"
cache-hash: ${{ hashFiles('pnpm-lock.yaml') }}
# 多文件hash组合
- name: 安装依赖多文件hash
uses: actions/xgj/npm-install@v1
with:
package-manager: "npm"
cache-hash: ${{ hashFiles('package.json', 'package-lock.json', '.nvmrc') }}
```
### 检查缓存状态
```yaml
- name: 安装依赖
id: install-deps
uses: actions/xgj/npm-install@v1
with:
package-manager: "pnpm"
- name: 根据缓存状态执行操作
if: steps.install-deps.outputs.cache-hit != 'true'
run: |
echo "依赖已重新安装,执行额外步骤"
npm run build:fresh
```
## 📝 完整工作流示例
```yaml
name: CI Pipeline
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 设置Node.js
uses: actions/setup-node@v4
with:
node-version: "18"
- name: 安装依赖
id: deps
uses: actions/xgj/npm-install@v1
with:
package-manager: "pnpm"
force-install: "false"
- name: 运行测试
run: pnpm test
- name: 构建项目
if: steps.deps.outputs.cache-hit != 'true'
run: pnpm build
```
## 🔧 工作原理
1. **缓存 Key 生成**: 根据包管理器类型和 lock 文件生成唯一的缓存 key
2. **缓存检查**: 使用`actions/cache@v4`检查是否存在匹配的缓存
3. **自动安装 pnpm如需**: 当 `package-manager=pnpm` 时,使用 `pnpm/action-setup@v4` 确保 pnpm 已安装
4. **缓存路径确定**:
-`cache-mode=node_modules` 时,缓存 `node_modules`(可用 `node-modules-path` 定义目录)。
-`cache-mode=store` 时,缓存包管理器的全局存储:`npm``~/.npm``pnpm` → 通过 `pnpm store path` 动态获取,`yarn``~/.cache/yarn`
5. **条件安装**: 仅在缓存未命中时执行依赖安装
6. **可选操作**: 根据配置执行 git stash 等额外操作
> 说明:缓存 key 中包含 OS、包管理器以及 pnpm 的版本)、缓存模式与自定义前缀,避免跨包管理器/模式的缓存误用。
## 🎯 最佳实践
### 1. 选择合适的包管理器
```yaml
# 推荐:根据项目实际使用的包管理器
- uses: actions/xgj/npm-install@v1
with:
package-manager: "pnpm" # 如果项目使用pnpm
### 1.1 选择合适的缓存模式
```yaml
# 追求最快的安装且目录较稳定:缓存 node_modules默认
- uses: actions/xgj/npm-install@v1
with:
package-manager: pnpm
cache-mode: node_modules
# 追求更高的通用性和复用率:缓存包管理器 store首次仍需 install 链接)
- uses: actions/xgj/npm-install@v1
with:
package-manager: pnpm
cache-mode: store
```
### 2. 合理使用强制安装
```yaml
# 仅在必要时使用强制安装
- uses: actions/xgj/npm-install@v1
with:
force-install: "true" # 仅用于解决依赖冲突
```
### 3. 自定义缓存前缀避免冲突
```yaml
# 为不同项目使用不同的缓存前缀
- uses: actions/xgj/npm-install@v1
with:
cache-prefix: "frontend-app"
```
### 4. 利用输出参数优化流程
```yaml
- name: 安装依赖
id: install
uses: actions/xgj/npm-install@v1
# 仅在重新安装依赖时执行某些步骤
- name: 重建缓存
if: steps.install.outputs.cache-hit != 'true'
run: npm run build:cache
# 调试:打印缓存路径(可用于后续步骤复用路径)
- name: 打印缓存路径
run: echo "Cache path is: ${{ steps.install.outputs.cache-path }}"
```
## 🚨 注意事项
1. **Git Stash**: 启用`enable-git-stash`会在安装后执行`git stash`,请确保这符合你的工作流需求
2. **缓存大小**: node_modules 可能很大,请关注 GitHub Actions 的缓存限制
3. **Lock 文件**: 确保 lock 文件已提交到仓库,这是缓存 key 生成的基础
4. **权限**: 某些自定义安装命令可能需要额外的权限
5. **跨包管理器缓存隔离**: 缓存 key 与 restore-keys 均包含包管理器、版本pnpm与模式切换包管理器/模式时会触发一次干净安装,避免污染
## 🔍 故障排除
### 缓存未命中
如果缓存总是未命中,检查:
- lock 文件是否存在且已提交
- package.json 或 lock 文件是否有变更
- 缓存前缀是否与之前一致
- 是否切换了包管理器或 `cache-mode`(切换会生成不同的 key 与前缀)
### pnpm store 路径
`cache-mode=store``package-manager=pnpm` 时,本 Action 会通过 `pnpm store path` 动态解析缓存目录;若命令不可用,则回退到 `~/.pnpm-store`
### 安装失败
如果安装失败,尝试:
- 启用`force-install`
- 使用自定义安装命令
- 检查 Node.js 版本兼容性
### Git Stash 问题
如果 git stash 出现问题:
- 确保工作目录有可 stash 的变更
- 考虑禁用`enable-git-stash`
- 在 action 之前确保 git 配置正确