Format & sort .env.example | Env formatter trước khi mở PR
.env.example là “hợp đồng key” của repo — phải đọc được trong 30 giây. Format = sort KEY, một key một dòng, comment mô tả chứ không dán secret. Dùng .env Formatter (local trên trình duyệt) trước PR khi file lộn A/Z hoặc nghi trùng key. Best practices bảo mật / onboard → bài .env best practices; bài này chỉ góc formatter + convention diff.
Freelance Nest/Next nhận repo khách: .env.example 80 dòng, STRIPE_* nằm giữa Z_* và A_*, ba comment # TODO, hai lần DATABASE_URL=. App vẫn boot trên máy lead (last-wins lấy dòng dưới). Bạn copy example → thiếu key thật sự cần → “works on my machine” vòng hai. Env formatter không sửa bảo mật — nó làm file đọc được và so sánh được trước khi ai đó merge.
Ai nên đọc bài này
- Dev / freelancer phải cập nhật
.env.examplemỗi khi thêm biến - Reviewer mệt vì diff env nhảy lung tung không theo alphabet
- Lead muốn convention “sort trước khi mở PR” thay vì tranh luận style trong Slack
Nếu bạn cần checklist không commit secret / vault / validate boot — đọc best practices .env. Ở đây tập trung format & sort.
Env formatter thực sự làm gì
Tool Kawa .env Formatter xử lý trong trình duyệt:
- Tách dòng
# commentvà dòngKEY=value - Sort key theo alphabet (
localeComparetiếng Anh — ổn vớiSCREAMING_SNAKE) - Đưa toàn bộ comment lên đầu, rồi một dòng trống, rồi danh sách key đã sort
- Bỏ dòng trống thừa ở giữa; trim khoảng trắng quanh dòng
Không đổi tên key, không validate schema Zod, không upload server. Output chỉ sạch hơn để bạn paste lại vào repo.
# Trước — khó review
Z_FEATURE=1
DATABASE_URL=postgresql://local/db
# payment
STRIPE_SECRET_KEY=sk_test_xxx
API_URL=http://localhost:3000
DATABASE_URL=postgresql://local/db2
# Sau sort — duplicate DATABASE_URL nằm cạnh nhau
# payment
API_URL=http://localhost:3000
DATABASE_URL=postgresql://local/db
DATABASE_URL=postgresql://local/db2
STRIPE_SECRET_KEY=sk_test_xxx
Z_FEATURE=1
Hai dòng DATABASE_URL cạnh nhau = tín hiệu đỏ. Xóa một dòng trước khi commit example.
Không dán .env production vào formatter — kể cả tool local. Chỉ dùng placeholder hoặc giá trị đã che. Lỡ dán rồi: coi như lộ → rotate key trong paste.
Vì sao sort quan trọng hơn “trông đẹp”
1. Diff PR nhỏ và ổn định
Thêm REDIS_URL vào file đã sort A–Z → diff khoảng 1–3 dòng. Thêm vào file lộn xộn → Git báo nửa file đổi chỗ, reviewer bỏ qua.
2. Last-wins im lặng
Hầu hết loader Node dotenv / nhiều framework: cùng key xuất hiện hai lần → giá trị sau thắng. Không có error. Triệu chứng:
| Hiện tượng | Nguyên nhân hay gặp |
|---|---|
| “Đã sửa key mà không ăn” | Sửa dòng trên; dòng dưới vẫn ghi đè |
| Local OK, CI fail | File khác / thiếu key; hoặc duplicate khác nhau giữa máy |
| Staging ≠ prod | Dashboard platform ghi đè file trên một bên |
Sort không “sửa” last-wins — nhưng kéo hai dòng trùng sát nhau để mắt người bắt được trước merge.
3. Onboard freelancer nhanh hơn
Example sorted + comment đầu file = checklist key trong 1 phút. Example lộn = người mới hỏi Zalo “anh gửi giúp env thật” — đúng anti-pattern bài best practices đã cảnh báo.
Convention đề xuất cho team Việt / outsourcing
Không cần quy tắc dài. Ba dòng trong README đủ:
- Commit
.env.example, gitignore.env - Key SCREAMING_SNAKE, không space quanh
= - Trước PR đụng env: format/sort (tool hoặc script), xóa duplicate
Tùy chọn nâng cao — nhóm theo prefix rồi sort trong nhóm (APP_*, DB_*, STRIPE_*). Formatter Kawa hiện sort toàn bộ A–Z (comment gom đầu). Nếu team giữ nhóm thủ công, sort từng khối trước khi dán, hoặc chấp nhận A–Z phẳng cho example nhỏ (dưới 40 key).
| Nên đưa vào formatter | Giữ nguyên tay | Không đưa vào tool |
|---|---|---|
| .env.example placeholder | Thứ tự nhóm theo domain (nếu team quy ước) | .env production / staging thật |
| Bản copy đã che secret | PEM/multiline phức tạp — test loader trước | File vừa nhận qua Slack chưa rotate |
| Draft trước khi mở PR | Comment giải thích nghiệp vụ dài | Export chứa token live |
Quy trình 5 phút trước PR
- Mở .env Formatter — không cần đăng ký
- Dán nội dung
.env.examplehiện tại - Bấm Định dạng → xem output
- Quét cặp key giống nhau liền kề; xóa thừa
- Copy về editor →
git diff→ commit riêng message kiểuchore: sort .env.example
🛠️ Kiểm tra định dạng .env ngay tại đây
Kiểm tra nhanh bằng shell (optional)
# Liệt kê key trùng trong .env.example (bỏ comment)
grep -v '^#' .env.example | grep '=' | cut -d= -f1 | sort | uniq -d
Có output → còn duplicate. CI có thể fail job nếu lệnh này không rỗng.
Case study ngắn
A. Freelancer thêm Stripe
Thêm STRIPE_SECRET_KEY và STRIPE_WEBHOOK_SECRET vào cuối file 60 dòng không sort. Reviewer thấy diff “+2” nhưng không biết đã có STRIPE_SECRET_KEY ở dòng 12 với giá trị cũ sk_test_replace_me. Merge → last-wins lấy dòng cuối; lead vẫn nghĩ đang dùng placeholder cũ trên staging.
Cách tránh: sort trước → hai STRIPE_SECRET_KEY cạnh nhau → xóa một → PR sạch.
B. Repo khách Nhật, example tiếng Anh lẫn comment tiếng Nhật
Comment # 本番はVercelのEnvironment vẫn giữ được sau format (gom đầu). Giá trị vẫn placeholder. Freelancer đọc comment biết production inject từ dashboard — không xin file .env qua chat.
Quote và khoảng trắng — formatter không “đoán” giúp bạn
Sort không tự thêm/bỏ quote. Bạn vẫn phải viết đúng:
PORT=3000
DISPLAY_NAME="Ada Lovelace"
# Sai: khoảng trắng quanh = hoặc value có space không quote
# API_KEY = sk live
Sau format, boot app một lần với key throwaway; log độ dài secret (không log giá trị) nếu nghi quote thừa bám vào value. Chi tiết quote / # trong value → best practices.
Checklist trước khi merge thay đổi env
-
.env.exampleđã sort (hoặc nhóm ổn định theo README) - Không còn key trùng (
uniq -drỗng) - Mỗi key mới có placeholder + comment một dòng
-
.envlocal không stage - Không dán secret thật vào tool / PR / screenshot
- README ghi rõ: copy example → điền local; prod dùng platform env