- vừa được xem lúc

Package-lock.json và những điều có thể bạn chưa biết

0 0 33

Người đăng: olaugh

Theo Viblo Asia

Giới thiệu

Với những lập trình viên nodejs nói riêng cũng như các lập trình viên web nói chung hẳn không còn lạ gì khi thấy trong một project tồn tại một file tên là package.json. Okay, có thể nói đơn giản thì package.json là một file chứa thông tin giúp bạn biết được để vận hành được project cần đến những modules nào. Có thể coi những modules chính là sức mạnh của nodejs với một bộ mã nguồn mở khổng lồ cũng như cộng đồng lớn mạnh đến nỗi cứ vài phút lại có một module mới. Wait, thế còn package-lock.json thì sao ? Bài viết này mình sẽ chia sẻ những kiến thức nhỏ bé của mình về cái file mà mình tưởng chừng như vô dụng này =)) . Bài viết mình tham khảo chính được viết trên medium với 9.4k claps, các bạn có thể tham khảo tại đây: Everything You Wanted To Know About package-lock.json But Were Too Afraid To Ask

Tóm lược

Những phần chính để mọi người có thể overview qua về package-lock.json :

  • package-lock.json sẽ tự động được tạo khi bạn sử dụng npm từ bản ^5.x.x
  • Nên giữ lại file package-lock.json để đảm bảo tính tương thích giữa các dependencies
  • Nên COMMIT package-lock.json vào hệ thống quản lý code mà bạn sử dụng (Git, SVN,...)
  • Không được xóa package-lock.json chỉ để chạy npm install và generate lại nó
  • Từ phiên bản ^5.1.x, package.json có quyền hạn cao hơn package-lock.json (source of truth)

Kiến thức nên tảng

Semantic Versioning (semver)

Các bạn có thể tạm hiểu đây chính là tập hợp các luật để quy định về cách đánh version cho một modules. Các bạn vẫn khai báo những dependencies theo cách này :

Các bạn có thể thấy rõ rằng mỗi module đều được mô tả phiên bản dưới dạng X.Y.Z, hay chính xác hơn là MAJOR.MINOR.PATCH .Các bạn có thể đọc thêm chi tiết về phần này tại đây : https://semver.org/. Trong khuôn khổ bài viết mình chỉ giải thích cơ bản để các bạn có thể hiểu về 3 chỉ số này có ý nghĩa gì với các module:

  • MAJOR : Thay đổi (hay còn gọi là breaking changes) khi những API cũ không còn tương thích nữa . VD : gọi là 2.0.0 khi các api từ bản 1.0.0 không còn dùng được nữa.
  • MINOR: Thay đổi khi thêm những tính năng mới tuy nhiên những API từ phiên phản trước đó vẫn có thể dùng trong phiên bản này. VD: Phiên bản 1.1.0 thêm một số tính năng tuy nhiên những API từ phiên bản 1.0.0 vẫn được giữ nguyên
  • PATCH: Phiên bản thay đổi khi có những fix bug cho những phiên bản trước đó và API hoàn toàn vẫn tương thích với các phiên bản cũ.

Quản lý các package

Các dev hẳn sẽ không lạ lẫm gì với trình quản lý các modules npm . Nhờ có npm việc quản lý các dependencies cho project dễ dàng hơn rất nhiều. Thử tưởng tượng một dự án của bạn có thể chứa đến hàng trăm các dependencies, trong những dependencies đó lại chứa tiếp các dependencies khác => dependencies hell => khá đau đầu. Nhưng nhờ có các trình quản lý các gói module như npm thì chúng ta sẽ chỉ phải quẳng gánh lo đi mà sống: khai báo các dependencies vào package.jsonnpm install

Có một điều cần note lại khi install các package có kí hiệu ^ thì trình quản lý dependencies sẽ tự động install phiên bản mới nhất cùng MAJOR version. VD với

"redux-thunk": "^2.3.0"

npm sẽ tự động tải xuống phiên bản 2.3.0 hoặc những phiên bản nâng cấp thay đổi MINOR hoặc PATCH

Chia sẻ mã nguồn

Các mã nguồn chia sẻ trên nền tảng github (đặc biệt là các javascript project) các bạn có thể thấy thường có 1 file package.json để định nghĩa những dependencies cần thiết để có thể run được thành công project. Lý thuyết là vậy nhưng vẫn có những trường hợp ngoại lệ, dưới đây chính là một trong những trường hợp có thể xảy ra:

Trong project có định nghĩa một dependencies trong file package.json như sau :

"redux-thunk": "^2.3.0"

Như giải thích ở trên, với tiền tố ^ , npm sẽ tự động install phiên bản mới nhất miễn là nó cùng MAJOR version. Một kịch bản có thể xảy ra ở đây là : Owner của dự án đặt version của gói redux-thunk như trên, tuy nhiên khi bạn clone về và chạy npm install thì gói redux-thunk mới được cập nhật một bản vá và hiện tại đang ở 2.3.1 . Tất nhiên là ở phiên bản clone của bạn npm sẽ tự động tải xuống phiên bản mới nhất. Và biết sao được, chẳng may với bản và này lại gây xung đột với những chức năng đang sử dụng, và khi đó kết quả chạy của 2 phiên bản 2.3.12.3.0 sẽ khác nhau

package-lock

Mục đích

Mục đích của package-lock.json chính là việc ngăn chặn những tính huống được mô tả phía trên : Cài đặt các dependencies từ cùng một file package.json nhưng lại dẫn đến 2 phiên bản cài đặt khác nhau

Định dạng

Mở package-lock.json lên các bạn có thể thấy nó có vẻ gì đó rất giống package.json nhưng dài dòng hơn nhiều. Dưới đây là một list các dependencies của express:

"express": { "version": "4.15.4", "resolved": "https://registry.npmjs.org/express/-/express-4.15.4.tgz", "integrity": "sha1-Ay4iU0ic+PzgJma+yj0R7XotrtE=", "requires": { "accepts": "1.3.3", "array-flatten": "1.1.1", "content-disposition": "0.5.2", "content-type": "1.0.2", "cookie": "0.3.1", "cookie-signature": "1.0.6", "debug": "2.6.8", "depd": "1.1.1", "encodeurl": "1.0.1", "escape-html": "1.0.3", "etag": "1.8.0", "finalhandler": "1.0.4", "fresh": "0.5.0", "merge-descriptors": "1.0.1", "methods": "1.1.2", "on-finished": "2.3.0", "parseurl": "1.3.1", "path-to-regexp": "0.1.7", "proxy-addr": "1.1.5", "qs": "6.5.0", "range-parser": "1.2.0", "send": "0.15.4", "serve-static": "1.12.4", "setprototypeof": "1.0.3", "statuses": "1.3.1", "type-is": "1.6.15", "utils-merge": "1.0.0", "vary": "1.1.1" } },

Ý tưởng ở đây là sẽ sử dụng package-lock.json thay vì package.json để cài đặt các modules do package-lock.json đã chỉ định rõ phiên bản, location, mã băm toàn vẹn integrity cho mỗi module và từng dependencies của nó => Cài đặt của nó tạo ra sẽ luôn giống nhau cho dù bạn cài đặt vào lúc nào.

Bàn luận

Từ những ý trên có thể thấy package-lock.json được cho là có thể giải quyết các vấn đề phổ biến tuy nhiên những tìm kiếm hàng đầu trên Google lại thường hỏi cách disabled nó cũng như hỏi về tác dụng của nó.

Trước phiên bản npm 5.x.x, package.json được coi là một "source of truth" cho dự án. Tất cả những gì được định nghĩa trong package.json sẽ được tự động install. Các dev tỏ ra khá hưởng ứng với mô hình này . Tuy nhiên khi package-lock.json được giới thiệu thì nó lại không hoạt động như sự kì vọng của nhiều người. Sự thay đổi trong package.json không được phản ánh trong package-lock.json. Trong 2 trường hợp dưới đây sẽ thể hiện rõ lí do khiến package-lock.json đã làm cho người dùng có chút thất vọng:

Trường hợp 1: Gói A có phiên bản 1.0.0 trong package.json và package-lock.json, tuy nhiên trong package.json được chỉnh sửa thủ công lại thành phiên bản 1.1.0, khi đó nếu người dùng vẫn tin tưởng package.json là "source of truth" thì họ sẽ hi vọng phiên bản 1.1.0 được install tuy nhiên sự thật thì phiên bản 1.0.0 mới là thứ được instaall

Trường hợp 2 : Một module không tồn tại trong package-lock.json, nhưng nó tồn tại trong package.json. Là một người dùng xem package.json là "source of truth", mong muốn module sẽ được cài đặt. Tuy nhiên, do module không có trong package-lock.json, nó không được cài đặt và code bị lỗi vì không thể tìm thấy module.

Do đó, những người sử dụng không hiểu tại sao những dependencies của mình không được cài đặt chính xác và do đó họ tìm cách xóa package-lock.json rồi cài đặt lại hoặc tìm cách disabled nó.

Tuy nhiên trong PR #17508, các maintainers của Npm đã thêm một thay đổi khiến cho package.json ghi đè package-lock.json nếu package.json đã được cập nhật. Bây giờ trong cả hai trường hợp trên, các gói mà người dùng mong đợi được cài đặt sẽ được cài đặt chính xác.

Kết luận

Trên đây là những kiến thức mình đã tham khảo cũng như tìm hiểu về những thứ vẫn thường được dùng nhưng lại khá ít người biết tại sao lại dùng chúng. Trong bài này mình chủ yếu nói về trình quản lý gói npm, tuy nhiên về các ý tưởng hay concepts nó cũng khá tương đồng với các trình quản lý gói khác như yarn, gem, ... Hi vọng bài viết có thể giúp ích cho các bạn.

Bình luận

Bài viết tương tự

- vừa được xem lúc

Giới thiệu Typescript - Sự khác nhau giữa Typescript và Javascript

Typescript là gì. TypeScript là một ngôn ngữ giúp cung cấp quy mô lớn hơn so với JavaScript.

0 0 525

- vừa được xem lúc

Cài đặt WSL / WSL2 trên Windows 10 để code như trên Ubuntu

Sau vài ba năm mình chuyển qua code trên Ubuntu thì thật không thể phủ nhận rằng mình đã yêu em nó. Cá nhân mình sử dụng Ubuntu để code web thì thật là tuyệt vời.

0 0 396

- vừa được xem lúc

Đặt tên commit message sao cho "tình nghĩa anh em chắc chắn bền lâu"????

. Lời mở đầu. .

1 1 738

- vừa được xem lúc

Tìm hiểu về Resource Controller trong Laravel

Giới thiệu. Trong laravel, việc sử dụng các route post, get, group để gọi đến 1 action của Controller đã là quá quen đối với các bạn sử dụng framework này.

0 0 358

- vừa được xem lúc

Phân quyền đơn giản với package Laravel permission

Như các bạn đã biết, phân quyền trong một ứng dụng là một phần không thể thiếu trong việc phát triển phần mềm, dù đó là ứng dụng web hay là mobile. Vậy nên, hôm nay mình sẽ giới thiệu một package có thể giúp các bạn phân quyền nhanh và đơn giản trong một website được viết bằng PHP với framework là L

0 0 449

- vừa được xem lúc

Bạn đã biết các tips này khi làm việc với chuỗi trong JavaScript chưa ?

Hi xin chào các bạn, tiếp tục chuỗi chủ đề về cái thằng JavaScript này, hôm nay mình sẽ giới thiệu cho các bạn một số thủ thuật hay ho khi làm việc với chuỗi trong JavaScript có thể bạn đã hoặc chưa từng dùng. Cụ thể như nào thì hãy cùng mình tìm hiểu trong bài viết này nhé (go).

0 0 433