"express": "^4.18.2" và "typescript": "~5.4.5" nằm cạnh nhau trong hàng nghìn tệp package.json, và phần lớn mọi người không nói chính xác được mỗi dòng cho phép những phiên bản nào. Khác biệt đó quyết định lần npm install mới sẽ kéo về gì, và đó là lý do lỗi "máy tôi chạy được mà" thường bắt đầu từ đây. Bài này giải thích Semantic Versioning, rồi đọc cú pháp range của npm trên một danh sách phiên bản cụ thể, dùng công cụ kiểm tra range semver cho mọi kết quả.
Số phiên bản hứa hẹn điều gì
Semantic Versioning 2.0.0 gán ý nghĩa cho ba số MAJOR.MINOR.PATCH:
- PATCH tăng khi sửa lỗi mà vẫn tương thích ngược.
- MINOR tăng khi thêm tính năng mới vẫn tương thích ngược, và đặt PATCH về 0.
- MAJOR tăng khi có thay đổi phá vỡ tương thích, và đặt hai số còn lại về 0.
- 0.y.z là giai đoạn phát triển ban đầu: mọi thứ có thể đổi bất cứ lúc nào.
Một phiên bản còn có thể mang phần pre-release (1.4.0-beta.1), thấp hơn bản chính thức mà nó dẫn tới, và phần build (1.4.0+20261014), bị bỏ qua khi sắp thứ tự. Các phần pre-release so từ trái sang phải, số so theo giá trị: beta.11 cao hơn beta.2.
Đó là lời hứa của con người chứ không phải bảo đảm, nhưng cú pháp range của npm được xây trên những lời hứa ấy.
Một gói, mười range
Giả sử một gói đã phát hành các phiên bản:
1.2.3, 1.2.9, 1.3.0, 1.4.0-beta.1, 1.4.0, 1.10.2, 2.0.0-rc.1, 2.0.0, 2.1.0
| Range | Nghĩa là | Các bản khớp | npm install chọn |
|---|---|---|---|
^1.2.3 | >=1.2.3 <2.0.0-0 | 1.2.3, 1.2.9, 1.3.0, 1.4.0, 1.10.2 | 1.10.2 |
~1.2.3 | >=1.2.3 <1.3.0-0 | 1.2.3, 1.2.9 | 1.2.9 |
1.2.x | >=1.2.0 <1.3.0-0 | 1.2.3, 1.2.9 | 1.2.9 |
1.x | >=1.0.0 <2.0.0-0 | như ^1.2.3 cộng mọi bản từ 1.0 đến 1.2.2 | 1.10.2 |
>=1.2.3 <2 | >=1.2.3 <2.0.0-0 | như ^1.2.3 | 1.10.2 |
1.2 - 1.4 | >=1.2.0 <1.5.0-0 | 1.2.3, 1.2.9, 1.3.0, 1.4.0 | 1.4.0 |
~1.4.0-beta.1 | >=1.4.0-beta.1 <1.5.0-0 | 1.4.0-beta.1, 1.4.0 | 1.4.0 |
^1.4.0-beta.1 | >=1.4.0-beta.1 <2.0.0-0 | 1.4.0-beta.1, 1.4.0, 1.10.2 | 1.10.2 |
^2.0.0-rc.1 | >=2.0.0-rc.1 <3.0.0-0 | 2.0.0-rc.1, 2.0.0, 2.1.0 | 2.1.0 |
* | mọi bản | mọi bản chính thức, không pre-release | 2.1.0 |
Quy luật: caret giữ nguyên major, tilde giữ nguyên major và minor. Để ý 1.10.2 cao hơn 1.4.0: các số được so theo giá trị chứ không theo chữ. Còn range gạch nối có đầu trên thiếu, - 1.4, nghĩa là "mọi bản bắt đầu bằng 1.4", nên dừng dưới 1.5.0 chứ không dừng ở 1.4.0.
Quy tắc pre-release
Nhìn lại dòng đầu: ^1.2.3 không khớp 1.4.0-beta.1, dù 1.4.0-beta.1 nằm giữa 1.2.3 và 2.0.0. npm cố ý để các bản pre-release ra ngoài trừ khi bạn yêu cầu: một bản pre-release chỉ khớp range có nhắc tới pre-release của cùng major.minor.patch. Vì vậy ^1.4.0-beta.1 khớp 1.4.0-beta.1 nhưng sẽ không khớp một bản 1.5.0-beta.1 sau này. Đuôi -0 của các cận trên như <2.0.0-0 có mặt cũng vì lý do đó: nó loại mọi pre-release của 2.0.0 cùng chính 2.0.0. Cờ --include-prerelease của npm (ô đánh dấu trong công cụ) tắt quy tắc này.
Bản 0.x chặt hơn
Trước 1.0.0, dấu caret coi số minor như số major, vì ở 0.x thứ gì cũng có thể vỡ:
| Range | Nghĩa là | Từ 0.0.3, 0.0.4, 0.4.1, 0.4.5, 0.5.0 |
|---|---|---|
^0.4.1 | >=0.4.1 <0.5.0-0 | 0.4.1, 0.4.5 |
~0.4.1 | >=0.4.1 <0.5.0-0 | 0.4.1, 0.4.5 |
^0.0.3 | >=0.0.3 <0.0.4-0 | chỉ 0.0.3 |
~0.0.3 | >=0.0.3 <0.1.0-0 | 0.0.3, 0.0.4 |
Vậy với 0.0.x, caret còn chặt hơn tilde, ngược với điều nhiều người nghĩ.
Chọn phiên bản tiếp theo
Khi phát hành, lệnh version của npm tự tăng số cho bạn. Từ 1.4.0-beta.1, "patch" và "minor" đều cho 1.4.0 (chúng hoàn tất bản pre-release thay vì nhảy qua), "major" cho 2.0.0, "prerelease" cho 1.4.0-beta.2. Từ 1.3.0, "preminor beta" cho 1.4.0-beta.0 và "prerelease rc" cho 1.3.1-rc.0. Thẻ tăng phiên bản của công cụ liệt kê cả bảy kiểu cùng lúc.
Các lỗi thường gặp
- Nghĩ ^ là "bản mới nhất". Nó là "bản mới nhất cùng major", và với 0.x còn hẹp hơn.
- Dựa vào range mà không có tệp lock. Hãy commit package-lock.json; khi đó range chỉ có tác dụng khi bạn chủ động cập nhật.
- Mong bản beta tự được cài. Không đâu, trừ khi range nhắc tới bản cùng x.y.z hoặc bạn bật tùy chọn.
- So phiên bản như chuỗi. Theo thứ tự chữ "1.10.0" < "1.9.0"; theo SemVer thì cao hơn.
- Số 0 ở đầu và số thứ tư.
1.02.0và1.2.3.4không phải SemVer hợp lệ và npm từ chối chúng.
Thử ngay
Dán kết quả của npm view <gói> versions vào công cụ kiểm tra range semver, gõ range trong package.json, và xem lần cài mới sẽ nhận bản nào cùng lý do từng bản khác bị loại. Để kiểm tra chính tệp package.json có hợp lệ không, dùng công cụ định dạng JSON.