npm là một kho quản lý package khổng lồ dành cho tất cả lập trình viên. Thông qua npm để chia sẻ, tải về và sử dụng các thư viện trong chính dự án của mình. Thậm là chí "mượn" npm để tạo các kho lưu trữ riêng tư lưu hành trong nội bộ.
Nhưng khi một dự án sử dụng quá nhiều phụ thuộc thì nó lại trở thành một cơn "ác mộng phụ thuộc". Bạn không chủ động quản lý được gói của người khác trên npm. Một ngày nào đó gói bạn đang sử dụng bị lỗi, bị xóa, bị hack... gây ra những mối nguy hiểm tiềm tàng cho dự án của chính bản thân.
Thực tế, tôi gặp nhiều vấn đề liên quan đến phiên bản của các gói phụ thuộc. Một trong những lý do thường thấy là mặc dù môi trường development và production sử dụng các gói giống nhau, nhưng vì một lý do nào đó mà một trong hai có vẻ không hoạt động giống nhau.
Nói thì có vẻ thâm sâu, nhưng việc đồng ý sử dụng package cũng có nghĩa là bạn chấp nhận một phần rủi ro. Những rủi ro đó hoàn toàn có thể hạn chế được phần nào nếu bạn đọc tiếp bài viết dưới đây.
Trước tiên, có thể nói bạn sẽ biết cách làm việc hiệu quả hơn với các package nếu biết đến semver. npm khuyến khích các package tuân thủ theo semver, nếu tuân thủ hoặc tuân thủ chặt chẽ nhiều phiền muộn sẽ tan biến.
Về cơ bản, semver đưa ra một cấu trúc phiên bản MAJOR.MINOR.PATCH, nó được gia tăng theo những quy tắc sau:
Ví dụ một phiên bản semver hợp lệ là 1.0.0, 1.0.0-0...
npm tuân thủ semver đến mức nó có thể tự động nâng cấp phiên bản đến MINOR mỗi khi bạn dùng lệnh npm install
. Bởi vì những bản nâng cấp ở mức PATCH hoặc MINOR có khả năng tương thích ngược. Chưa biết thay đổi là gì nhưng npm "nghĩ" rằng phiên bản mới "chắc chắn" đáng giá hơn bản cũ.
Đó là trên lý thuyết, thực tế đội ngũ nhà phát triển mới là người quyết định việc tuân thủ hay không. Dù vô tình hay cố ý không tuân thủ semver, package đó có thể phá hủy dự án của bạn. Tưởng tượng sẽ ra sao nếu họ phát hành một phiên bản PATCH nhưng lại xóa hoặc thay đổi một hàm không tương thích ngược trước đó.
package.json
là một file quan trọng trong dự án. Nó cung cấp nhiều thông tin cũng như chỉ dẫn dự án hoạt động. Một trong số đó là nó quản lý các gói phụ thuộc cùng phiên bản của chúng.
{
"dependencies": {
"dayjs": "^1.11.7"
}
}
Tồn tại song song cùng package.json
là package-lock.json
. Nếu không chịu khó tìm hiểu, nhiều người không biết mục đích thực sự của nó là gì. package-lock.json
được sinh ra mỗi khi chạy npm install
, nó lưu vết lại tất cả thông tin gói phụ thuộc tại thời điểm chạy install. Về mục đích tại sao phải sinh ra file lock, tôi xin phép trình bày trong mục npm ci
phía dưới.
Mỗi khi cần cài đặt một package, npm install <package>
giúp bạn làm điều đó. Ngay cả khi muốn cài đặt lại tất cả gói phụ thuộc trong dự án, theo quán tính chúng ta dùng npm install
.
Nhưng bạn có để ý hoặc thắc mắc tại sao mỗi lần chạy npm install
thì package.json
, package-lock.json
bị thay đổi? Đó là vì npm install
tự động nâng cấp phiên bản của package.
{
"dependencies": {
"dayjs": "^1.11.7"
}
}
Mỗi khi bạn cài đặt package bằng npm install
, nó xuất hiện dấu ^
trước phiên bản với ý nghĩa "được phép cập nhật" phiên bản của gói.
Ví dụ: ^1.2.3
được cập nhật lên phiên bản dưới 2.0.0-0
, ^0.2.3
được cập nhật lên phiên bản dưới 0.3.0-0
...
Một dấu thường thấy nữa là ~
, nó cũng cho phép npm cập nhật phiên bản.
Ví dụ: ~1.2.3
được cập nhật lên phiên bản dưới 1.3.0-0
, ~0.2.3
được cập nhật lên phiên bản dưới 0.3.0-0
...
Có rất nhiều quy tắc, bạn đọc tìm hiểu thêm tại Advanced Range Syntax.
Nếu chấp nhận những thay đổi phiên bản khi install
, có thể bạn không cần bận tâm điều gì. Còn nếu không, hãy xóa các dấu trước phiên bản để npm cài đặt chính xác từng phiên bản đó. Hoặc cài đặt gói cùng với cờ --save-exact
:
$ npm install --save-exact dayjs
npm install
cài đặt tất cả gói phụ thuộc có trong dependencies
và cả devDependencies
. Trong devDependencies
chứa các gói chỉ cần thiết để phát triển và thử nghiệm cục bộ, ví dụ như các công cụ unittest hoặc linting. Những gói đó không nhất thiết phải được cài đặt trong môi trường production, vì thế bạn có thể loại bỏ chúng bằng cách chỉ cài đặt các gói có trong dependencies
bằng cờ --production
.
$ npm install --production
npm ci
tương tự như npm install
, nó cũng cài đặt tất cả các gói phụ thuộc, nhưng là trong package-lock.json
hoặc npm-shrinkwrap.json
. Có vài lưu ý khi làm việc với package-lock.json
, bạn đọc tìm hiểu thêm tại npm-ci Description. Một vài lưu ý đặc biệt là:
npm ci
được khuyến khích dùng trong các môi trường tự động như nền tảng thử nghiệm, tích hợp liên tục và triển khai -- hoặc bất kỳ tình huống nào mà bạn muốn đảm bảo rằng bạn đang thực hiện cài đặt sạch các phụ thuộc của mình.
Kể cả trong production, bạn vẫn nên sử dụng npm ci
để cài đặt chính xác phiên bản của các gói. Tránh trường hợp chạy trên development thì được nhưng lúc chạy trên production thì bị lỗi. Tương tự như npm install
, sử dụng cờ --production
để cài các gói trong dependencies
.
$ npm ci --production
Nếu "fix cứng" phiên bản của các gói, làm cách nào để tôi biết gói nào có cập nhật? Đó chính là lúc npm outdated
giúp bạn. Mỗi khi cần kiểm tra các bản cập nhật thì chạy nó. Câu lệnh cung cấp thông tin về phiên bản hiện tại, phiên bản MINOR tương thích ngược hoặc phiên bản nâng cấp MAJOR toàn diện.
Hãy thận trọng với các phiên bản MAJOR bởi vì nó thường mang những thay đổi rất lớn đến mức làm hỏng dự án hiện tại của bạn. Các bản cập nhật MINOR hoặc PATCH thường an toàn hơn. Tuy nhiên, tránh nâng cấp toàn bộ phiên bản của các gói cùng một lúc. Thay vào đó hãy nâng cấp từng gói một mà bạn cho là an toàn trước tiên, nếu có lỗi xảy ra thì dễ truy vết lại gói nào không tương thích để kịp thời hoàn tác.
Quá nhiều package, mỗi package lại mang trong mình nhiều gói phụ thuộc khác, từ đó cơn "ác mộng phụ thuộc" ra đời. Một vấn đề liên quan đến nó chính là bảo mật. Sẽ ra sao nếu một package được rất nhiều package khác sử dụng dính lỗ hổng bảo mật? npm sớm quan tâm đến việc này, chính vì thế công cụ cung cấp một tính năng "quét" các lỗ hổng trong package và trong cả các dependencies của chúng.
$ npm audit
Khi chạy npm audit
, npm liệt kê ra tất cả các gói cùng dependencies của nó mà đang dính lỗi bảo mật. Thông tin in ra khá là rõ ràng, gồm có "Mức độ" nguy hiểm của mỗi, thông tin chi tiết (More info), cùng cách giải quyết (# Run ... ) và một số thông tin khác.
Để khắc phục tất cả lỗ hổng, chúng ta chạy lệnh fix
.
$ npm audit fix
Về cơ bản, npm audit fix
chạy lệnh npm install <package>
bên dưới. Nó giống như là câu lệnh trong # Run. Do đó, có những package phải thay đổi cả phiên bản MAJOR thì mới sửa được lỗi. Khi đó, npm audit fix
không tùy tiện cập nhật phiên bản MAJOR gây nguy cơ hỏng cả dự án. Tuy nhiên, nếu biết bạn đang làm gì và bỏ qua cảnh báo thì bạn có thể sử dụng thêm cờ --force
để chấp nhận bản sửa lỗi.
$ npm audit fix --force
npm
khuyến khích nhà phát triển đặt phiên bản cho các gói theo quy tắc semver. Có thể nói nhiều phiền muộn khi sử dụng npm cũng như các gói có trên đó bắt nguồn từ các phiên bản, "địa ngục phụ thuộc" cũng góp phần tạo nên sự phiền muộn đó. Hy vọng qua bài viết này cung cấp cho bạn đọc một góc nhìn về phiên bản gói cùng một vài phương pháp sử dụng npm để giải quyết phần nào vấn đề nêu ra.
Tôi & khao khát "chơi chữ"
Bạn đã thử viết? Và rồi thất bại hoặc chưa ưng ý? Tại 2coffee.dev chúng tôi đã có quãng thời gian chật vật với công việc viết. Đừng nản chí, vì giờ đây chúng tôi đã có cách giúp bạn. Hãy bấm vào để trở thành hội viên ngay!
Đăng ký nhận thông báo bài viết mới
Xin chào, tôi tên là Hoài - một anh Dev kể chuyện bằng cách viết ✍️ và làm sản phẩm 🚀. Với nhiều năm kinh nghiệm lập trình, tôi đã đóng góp một phần công sức cho nhiều sản phẩm mang lại giá trị cho người dùng tại nơi đang làm việc, cũng như cho chính bản thân. Sở thích của tôi là đọc, viết, nghiên cứu... Tôi tạo ra trang Blog này với sứ mệnh mang đến những bài viết chất lượng cho độc giả của 2coffee.dev.Hãy theo dõi tôi qua các kênh LinkedIn, Facebook, Instagram, Telegram.
Bình luận (0)