jvinhit//lab

Search posts

Type to search across journal entries.

navigate open esc close

Command Line cho Developer · Part 8 - Node, npm, pnpm & Package Scripts

Workflow Node/package manager trong terminal: node/npm/pnpm version, corepack, npm run, pnpm exec/dlx, npm ci, frozen lockfile, env vars, npm ls và pnpm why.

Đây là Phần 8. Với frontend/fullstack JavaScript, rất nhiều việc hằng ngày đi qua package manager:

  • cài dependencies;
  • chạy dev server;
  • chạy build/test/lint;
  • gọi CLI local của project;
  • debug dependency bị lệch version.

Bài này tập trung vào workflow terminal, không đào sâu toàn bộ package manager. Muốn học sâu hơn, xem series Node Package Managers & the Supply Chain.


Kiểm tra version

node --version
npm --version
pnpm --version

Xem Node đang ở đâu:

command -v node
node -p "process.execPath"
node -p "process.version"

Nếu team dùng version manager như nvm, fnm, asdf, hãy kiểm tra file:

ls -la | rg '.nvmrc|.node-version|package.json'

Node version lệch là nguồn lỗi rất thường gặp, nhất là khi native dependency hoặc framework mới yêu cầu version cụ thể.


Corepack và package manager

Corepack giúp pin package manager theo packageManager trong package.json.

corepack enable
corepack prepare pnpm@latest --activate

Xem project yêu cầu gì:

node -p "require('./package.json').packageManager"

Nếu repo có pnpm-lock.yaml, thường dùng pnpm. Nếu có package-lock.json, thường dùng npm. Đừng trộn package manager nếu team không chủ động làm vậy.


Đọc scripts trong package.json

npm run
pnpm run

Chạy script:

npm run dev
npm run build
npm run test

Với pnpm:

pnpm dev
pnpm build
pnpm test

Nhưng dạng rõ nhất vẫn là:

pnpm run build

Trong repo lạ, đọc script trước:

node -p "require('./package.json').scripts"

Hoặc đẹp hơn nếu có jq:

jq '.scripts' package.json

Gọi CLI local: npm exec, pnpm exec, dlx

Dependency CLI cài trong project nằm ở node_modules/.bin.

Chạy CLI local:

npm exec astro -- --version
pnpm exec astro --version

Với pnpm, pnpm exec rất thường dùng:

pnpm exec tsc --noEmit
pnpm exec prettier --check .

Chạy package tạm thời không cài vào project:

npm exec cowsay hello
pnpm dlx cowsay hello

dlx hợp cho tool một lần. Với tool team cần lặp lại, nên đưa vào devDependencies và scripts để mọi người chạy cùng version.


Cài dependency

Npm:

npm install react
npm install -D vitest

Pnpm:

pnpm add react
pnpm add -D vitest

Cài đúng theo lockfile trong CI:

npm ci
pnpm install --frozen-lockfile

Khác biệt quan trọng:

LệnhDùng khi
npm installdev local, có thể update lockfile
npm ciCI, cài sạch theo lockfile
pnpm installdev local
pnpm install --frozen-lockfileCI, không cho lockfile đổi

Debug dependency

Npm:

npm ls react
npm explain react

Pnpm:

pnpm why react
pnpm list react

Xem version package trực tiếp:

node -p "require('astro/package.json').version"

Nếu import fail:

node -e "console.log(require.resolve('astro/package.json'))"

Với ESM-only package, require có thể không load module chính, nhưng package.json thường vẫn resolve được.


Env khi chạy script

NODE_ENV=production npm run build
DEBUG=1 pnpm test
PORT=4322 pnpm run dev

Trên Windows cmd, cú pháp env inline khác. Nếu team cần cross-platform scripts, dùng tool như cross-env hoặc để config trong file/framework.

Xem env trong script:

node -e "console.log(process.env.NODE_ENV)"

Đừng commit .env chứa secret. Commit .env.example để người khác biết cần biến nào.


Dọn cài đặt khi dependency rối

Trước tiên đọc lỗi. Nếu thật sự cần reset:

rm -rf node_modules
npm ci

Với pnpm:

rm -rf node_modules
pnpm install --frozen-lockfile

Nếu lockfile bị đổi ngoài ý muốn, xem diff:

git diff -- package-lock.json pnpm-lock.yaml

Không xóa lockfile chỉ để “cho nó chạy” nếu bạn không hiểu hậu quả. Lockfile là một phần của source truth.


Recipe trong repo lạ

node --version
npm --version
pnpm --version
ls -la
jq '.packageManager, .scripts' package.json
git status --short

Nếu là pnpm:

pnpm install --frozen-lockfile
pnpm run build
pnpm run check

Nếu là npm:

npm ci
npm run build
npm run check

Bài tập

  1. In scripts của project bằng npm run hoặc pnpm run.
  2. Dùng jq hoặc node -p đọc packageManager.
  3. Chạy một CLI local bằng pnpm exec hoặc npm exec.
  4. Dùng npm ls hoặc pnpm why kiểm tra một dependency.
Lời giải tham khảo
pnpm run
node -p "require('./package.json').packageManager"
pnpm exec astro --version
pnpm why astro

Điều cốt lõi

Package manager không chỉ để cài package. Nó là entrypoint của workflow project: scripts, CLI local, dependency graph, CI reproducibility. Đọc package.json, tôn trọng lockfile, và chạy tool qua package manager để đúng version của repo.