Một vài lưu ý với package.json và package-lock.json để sử dụng npm hiệu quả hơn

Một vài lưu ý với package.json và package-lock.json để sử dụng npm hiệu quả hơn

Những mẩu tin ngắn hàng ngày dành cho bạn
  • countless.dev là một trang web khá thú vị khi mà nó so sánh giá tiền sử dụng các mô hình LLMs của các nhà cung cấp khác nhau.

    Tại đây bạn có thể nhìn thấy tất cả các mô hình ngôn ngữ lớn phổ biến bởi các nhà cung cấp như OpenAI, Azure, Mistral... Bảng giá cho mỗi 1M tokens đầu vào/ra. Hoặc thậm chí có thể so sánh chúng với nhau để tìm ra nhà cung cấp hoặc mô hình rẻ nhất tuỳ theo mục đích sử dụng.

    » Xem thêm
  • 1,2 năm trước, Kubernetes (k8s) tự nhiên được nhắc đến như một hiện tượng, chắc vì nó bá quá nên ai cũng muốn học và sử dụng. Nó là một công cụ "Automating deployment, scaling, and management of containerized applications" - Vâng! nghe hay ho đấy chứ 🤤.

    Hồi đó thì mình đang đam mê với Docker, đặc biệt là Docker Swarm, cũng tương tự như k8s ý nhưng ở quy mô nhỏ hơn. Docker Swarm thì có vẻ ít phức tạp hơn nhiều so với k8s. Mà như thế cũng tốt vì nó đã và đang đáp ứng rất tốt nhu cầu sử dụng của mình lúc đó, lại còn bớt đi phần phức tạp, lằng nhằng.

    Ấy thế mà 1-2 tháng trở lại đây, các bài viết có tiêu đề "bạn có thực sự cần đến Kubernetes" lại đang nổi lên với tần suất dày hơn. Quả thật k8s rất mạnh nhưng cũng quá phức tạp. Tại sao phải cố dùng dao "mổ trâu để giết gà" cơ chứ? Trừ khi bạn lường trước được độ phức tạp khi muốn áp dụng một công nghệ. Một cái nữa k8s tiêu tốn tài nguyên và nguồn lực ghê ghớm, để vận hành được nó không đơn giản là dựng lên được là xong mà còn phải có rất nhiều nhiều kiến thức nữa 😨.

    À, chắc cũng một phần nữa là do các "ông lớn" đang tập trung đẩy mạnh vào Serverless, giảm bớt sự phức tạp trong khâu vận hành đi, thay vào đó là nên tập trung vào phát triển ứng dụng.

    Bên cạnh đó, thì cái tên WASM cũng đang được nhắc đến rất là nhiều 🤔

    Do you really need Kubernetes in your company/startup? | dev.to

    Do You Really Need Kubernetes?

    » Xem thêm
  • Trước mình cứ khen lấy khen để Serverless, rằng tối ưu chi phí xuống 0đ để duy trì blog các thứ. Đúng là như vậy thật! Nhưng bên cạnh đó serverless cũng có các mặt tối đáng để lưu tâm đấy!

    Hôm kia mình phải mất ngày trời để truy tìm và khắc phục sự cố chỉ vì gọi hàm build-in của Cloudflare KV. Cụ thể là hàm list với limit 1000 - tức là một lần gọi nó trả về 1000 keys của KV. Cơ mà đời không như là mơ. Con số 1000 chỉ là trên lý thuyết. Lúc thì trả về vài trăm, lúc thì vài chục, thậm chí lúc thì lẹt đẹt có vài cái. Thế là làm tắc nghẽn cả hệ thống. À mà cũng không phải là nghẽn mà là hệ thống "nhàn rỗi" quá không có việc gì để làm, trong khi thực tế đáng ra nó phải xử lý cả trăm ngàn cái keys cơ 🥲

    » Xem thêm

Vấn đề

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.

Semver

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:

  • Số phiên bản MAJOR: khi bạn có những thay đổi API lớn, không tương thích với phiên bản trước.
  • Số phiên bản MINOR: khi bạn thêm chức năng tương thích ngược với phiên bản trước.
  • Số phiên bản PATCH: khi bạn làm một bản vá lỗi tương thích ngược với phiên bản trước.

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 và package-lock.json

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.jsonpackage-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ột vài lưu ý sử dụng npm hiệu quả hơn

package version

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 --production

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

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à:

  • Nếu các gói phụ thuộc trong package-lock.json không khớp với các gói phụ thuộc trong package.json, npm ci sẽ báo lỗi.
  • Nó không bao giờ thay đổi package.json hoặc package-lock.json.

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

npm outdated

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.

npm outdated

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.

npm audit

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

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

Tổng kết

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.

Cao cấp
Hello

Bí mật ngăn xếp của Blog

Là một lập trình viên, bạn có tò mò về bí mật công nghệ hay những khoản nợ kỹ thuật về trang blog này? Tất cả bí mật sẽ được bật mí ngay bài viết dưới đây. Còn chờ đợi gì nữa, hãy bấm vào ngay!

Là một lập trình viên, bạn có tò mò về bí mật công nghệ hay những khoản nợ kỹ thuật về trang blog này? Tất cả bí mật sẽ được bật mí ngay bài viết dưới đây. Còn chờ đợi gì nữa, hãy bấm vào ngay!

Xem tất cả

Đăng ký nhận thông báo bài viết mới

hoặc
* Bản tin tổng hợp được gửi mỗi 1-2 tuần, huỷ bất cứ lúc nào.
Author

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ạn thấy bài viết này có ích?
Không

Bình luận (0)

Nội dung bình luận...