Workflow báo cache hit nhưng bước test vẫn lỗi thiếu module. Một nguyên nhân dễ bỏ sót là bạn cache thư mục tải package của npm, rồi dùng cache-hit để bỏ qua cả bước cài dependency. Cache đã có file tải xuống chưa có nghĩa workspace đã có node_modules đúng lockfile.
Bài đối chiếu tài liệu ngày 29/10/2026, dùng fragment actions/cache@v6 và npm CLI 11. Fragment dành cho job Linux đã checkout mã nguồn, thiết lập Node/npm và có package-lock.json ở gốc. YAML được kiểm tra cú pháp tại máy; chưa chạy workflow trên GitHub và không có số đo tiết kiệm thời gian.
Xác định chính xác thứ đang cache
Ba thứ thường bị gọi chung là “cache dependency”: dữ liệu tải package, cây dependency đã cài và sản phẩm build. Chúng có hợp đồng tái sử dụng khác nhau.
Trong ví dụ này chỉ cache thư mục do npm config get cache trả về. npm ci vẫn dựng cây dependency theo lockfile. Nếu đã có node_modules, lệnh còn loại nó trước khi cài. Đây là hành vi được ghi trong npm ci, không phải cơ chế phục hồi của GitHub cache.
Để tránh hai nơi quản lý cùng một cache, chọn một cách rõ ràng: nếu job đã dùng tùy chọn cache npm của setup-node, đọc cấu hình ấy trước khi thêm fragment dưới đây. Ví dụ này dùng actions/cache trực tiếp để nhìn thấy key và output.
Cache là bước hỗ trợ cho install
- name: Find npm cache directory
id: npm-cache-path
shell: bash
run: echo "dir=$(npm config get cache)" >> "$GITHUB_OUTPUT"
- name: Restore npm download cache
id: npm-cache
uses: actions/cache@v6
with:
path: ${{ steps.npm-cache-path.outputs.dir }}
key: ${{ runner.os }}-npm11-node24-${{ hashFiles('package-lock.json') }}
restore-keys: |
${{ runner.os }}-npm11-node24-
- name: Install locked dependencies
run: npm ci
- name: Test
run: npm test
npm ci không có điều kiện bỏ qua. Prefix node24-npm11 là hợp đồng của ví dụ; khi job dùng major khác, đổi cả môi trường lẫn phần key này. Tên key không tự cài Node hoặc xác minh phiên bản.
Đường dẫn lấy từ npm giúp tránh mặc định mọi runner đều dùng cùng thư mục. GITHUB_OUTPUT nhận đúng một dòng output tên dir; không in toàn bộ cấu hình npm hoặc file đăng nhập registry. action.yml của cache v6 dùng runtime Node 24; self-hosted runner cần tương thích trước khi áp dụng phiên bản action này.
Đọc cache-hit theo key chính xác
cache-hit phản ánh việc tìm đúng primary key, không phải một cờ “mọi dependency đã sẵn sàng”. Theo tài liệu actions/cache, output được dùng như string; khi cần kiểm tra exact hit, so sánh với 'true'.
Khi lockfile đổi, primary key đổi. Action có thể phục hồi cache phù hợp từ prefix trong restore-keys, giúp npm có cơ hội tái sử dụng dữ liệu tải xuống. Đó vẫn không phải exact hit với lockfile mới. Khi không tìm được cache, job cần cài từ nguồn bình thường.
Trong cả ba trường hợp, fragment đều chạy install. Bước test chỉ chạy tiếp nếu install thành công theo hành vi mặc định của job. Đừng thêm continue-on-error vào install chỉ để giữ pipeline xanh.
Kiểm tra bằng ba lượt chạy
Trên repository thử nghiệm, quan sát ba tình huống sau. Đây là kế hoạch kiểm tra theo hợp đồng tài liệu, không phải log GitHub đã chạy trong bài:
| Tình huống | Điều cần quan sát | Bước install |
|---|---|---|
| Lượt đầu chưa có cache | Miss, npm tải dữ liệu cần thiết | Vẫn chạy |
| Giữ nguyên lockfile | Có thể exact hit nếu cache còn tồn tại và truy cập được | Vẫn chạy |
| Lockfile đổi | Có thể phục hồi qua prefix hoặc miss | Vẫn chạy |
Thêm một ca package.json lệch lockfile. npm ci phải thất bại, dù cache có hay không. Cache không được dùng để che sự lệch hợp đồng dependency. Khi đo hiệu năng, tách thời gian restore, install và save; một cache lớn có thể tốn công truyền hơn lợi ích nó mang lại.
Key, phạm vi và dữ liệu nhạy cảm
Dependency caching reference mô tả cả key matching và giới hạn phạm vi truy cập theo branch. Đừng giả định chỉ cần cùng key là mọi workflow luôn đọc được cùng archive. Path và cache version cũng ảnh hưởng việc khớp.
Không cache .npmrc có credential, token hay toàn bộ thư mục người dùng. Với private registry, rà phạm vi người có thể đọc dữ liệu package đã cache, kể cả workflow từ pull request. Cache là dữ liệu có thể được chia sẻ trong phạm vi mà nền tảng cho phép, không phải kho bí mật.
Lỗi thường gặp và bước tiếp theo
- Cache
~/.npmnhưng bỏ install khi hit: thiếu cây dependency trong workspace. - Dùng key cố định mãi: khó phân biệt cache thuộc lockfile hoặc môi trường nào.
- Cache cả
node_modulesrồi vẫnnpm ci: cần hiểu lệnh sẽ xóa cây đó trước khi cài. - Trông chờ cache tồn tại vĩnh viễn: job phải chạy đúng khi miss hoặc cache bị loại bỏ.
Hãy giữ pipeline đúng khi không có cache, sau đó thêm cache như một tối ưu có thể đo được. Với npm download cache, một exact hit giúp tái sử dụng dữ liệu tải xuống; bước dựng dependency theo lockfile vẫn cần diễn ra.

