Latest Post

Tăng thứ hạng và truy cập tự nhiên với 10 phương pháp SEO hay nhất Kiếm Tiền Online (mmo): Khái Niệm và Các Hình Thức Phổ Biến

package-lock.json là gì? Tại sao lại có file package-lock.json này trong khi chúng ta đã có package.json?

Nhiều bạn (bao gồm cả mình trước đây) thường hay bối rối về 2 file này, vì chúng có nhiều điểm tương đồng. Nhưng đừng lo lắng, sau khi đọc bài này bạn sẽ hiểu rõ hơn về chúng..

Đối với công dụng yarn.lock cũng tương tự như package-lock.json nhé, chỉ là format nó khác thôi

Khi chúng ta dùng nodejs hay npm để quản lý các thư viện javascript, chúng ta sẽ có file package.json để lưu version các package mà chúng ta cần cho dự án.

Ví dụ, nếu chúng ta muốn tạo một RESTful API bằng Express, chúng ta sẽ chạy lệnh npm install express

Sau đó, file package.json của chúng ta sẽ có thêm express với version là 4.0.0 trong phần dependencies.

json

{  "name": "my-app",  "version": "1.0.0",  "main": "index.js",  "dependency": {    "express": "4.0.0"  }}
Ứng dụng bạn cài `express`
Ứng dụng bạn cài `express`

Khi chúng ta cài đặt thư viện Express, cũng có nghĩa là chúng ta cài những thư viện mà Express dùng đến. Ví dụ Express dùng thư viện send để thực hiện chức năng static file server.

`express` dùng `send` nên ứng dụng của bạn cũng tải và cài `send`
`express` dùng `send` nên ứng dụng của bạn cũng tải và cài `send`

Thêm nữa, package send lại cần một package khác để hoạt động, đó là mime-types. Vì thế npm sẽ cài mime-types.

package `send` lại dùng `mime-types`, vậy là trong folder node_modules có thêm folder mime-types
package `send` lại dùng `mime-types`, vậy là trong folder node_modules có thêm folder mime-types

Cuối cùng khi cài đặt mime-types, npm nhận ra rằng mime-types cần mime-db, và nó cũng tải luôn mime-db

npm tải package `mime-db` vì nó là dependency của những dependency khác
npm tải package `mime-db` vì nó là dependency của những dependency khác

Nó giống như một quá trình đệ quy vậy, nó sẽ tải xuống các dependency của bạn và cả dependency của dependency. Đó là lý do folder node_modules của bạn rất nặng.

Ngay cả việc bạn chỉ cài một dependency express thôi, nếu bạn kiểm tra thư mục node_modules – thư mục mà npm lưu trữ những dependency của bạn – bạn sẽ thấy nhiều package tại đây.

txt

▾ node_modules/  ▸ accepts/  ▸ array-flatten/  ▸ body-parser/  ▸ bytes/  ▸ content-disposition/  ▸ content-type/  ▸ cookie-signature/  ▸ cookie/  ▸ debug/  ▸ depd/  ▸ destroy/  ▸ ee-first/  ▸ encodeurl/  ▸ escape-html/  ▸ etag/  ▸ express/  ▸ finalhandler/  ▸ forwarded/  ▸ fresh/  ▸ http-errors/  ▸ iconv-lite/  ▸ inherits/  ▸ ipaddr.js/  ▸ media-typer/  ▸ merge-descriptors/  ▸ methods/  ▸ mime-db/  ▸ mime-types/  ▸ mime/  ▸ ms/  ▸ negotiator/  ▸ on-finished/  ▸ parseurl/  ▸ path-to-regexp/  ▸ proxy-addr/  ▸ qs/  ▸ range-parser/  ▸ raw-body/  ▸ safe-buffer/  ▸ safer-buffer/  ▸ send/  ▸ serve-static/  ▸ setprototypeof/  ▸ statuses/  ▸ toidentifier/  ▸ type-is/  ▸ unpipe/  ▸ utils-merge/  ▸ vary/  package-lock.json  package.json

Giả sử nếu không có file package-lock.json và bạn chạy npm install vào buổi chiều, bạn có thể nhận được những dependency khác so với buổi sáng, dù cho bạn không thay đổi verson express trong package.json

Câu lệnh npm install có thể cài những package khác version quy định trong file package.json nếu không có file package-lock.json


🥇Tại sao cùng một package.json nhưng khi npm install lại tải về những dependency khác nhau?

Trong file package.json, bạn sẽ thấy các dependency có version có dấu ^ hoặc ~ đứng trước. Những dấu này có nghĩa là NPM không cần phải cài đặt đúng version đã chỉ định. NPM có thể cài đặt version “thích hợp” với dependency trong package.json

Ví dụ chúng ta không có file package-lock.json, trong package.json chúng ta có "express": "^4.0.0".

Trong trường hợp này khi chạy npm install thì chúng ta có thể nhận lại express version là 4.0.1 hoặc 4.1.0 (tất nhiên với điều kiện là express đã xuất bản version 4.0.1 hoặc 4.1.0)

Để lý giải cho điều này thì chúng ta cần hiểu về semantic version, mình có thể tóm gọn như thế này

Cấu trúc version có dạng MAJOR.MINOR.PATCH

  • Số version MAJOR đại diện cho những thay đổi lớn, không tương thích với phiên bản trước
  • Số version MINOR đại diện cho những chức năng mới được thêm vào, vẫn tương thích với phiên bản trước
  • Số version PATCH đại diện cho những bản vá lỗi, vẫn tương thích ngược với phiên bản trước

Ngoài ra còn một số prefix (tiền tố) khi những version này được ghi lại trong file package.json đó là

  • ^: Có thể cài version MINOR và PATCH. Ví dụ ^0.13.0 thì có thể cài 0.13.1, 0.14.0
  • ~: Có thể cài version PATCH. Ví dụ ~0.13.0 thì có thể cài 0.13.1 nhưng không thể cài 0.14.0

Oke. Đến đây bạn đã có câu trả lời cho câu hỏi “Tại sao cùng một package.json nhưng khi npm install lại tải về những dependency khác nhau?” rồi đúng không. Đó là do mấy cái tiền tố trước version.

Tại sao package-lock.json tồn tại và cách nó hoạt động

Tiếp tục nào!!!!

Nếu không dùng đến file package-lock.json, sử dụng ^~ có thể không xảy ra vấn đề gì. Vì theo semantic version mà mình đã nói ở trên, các version update sau minor và patch có khả năng tương thích ngược – nghĩa là không có bất kỳ “breaking change” nào với code bạn cả.

Tuy nhiên, là con người ai mà chả có lỗi lầm. Ví dụ, người tạo ra package chỉ sửa một lỗi nhỏ thôi, họ note rằng đây chỉ là một bản PATCH, trong khi đó có thể nó gây ra một sự thay đổi lớn trong code của bạn.

Ví dụ Chai từng đánh số version bị sai dẫn đến hàng triệu bản build trên khắp thế giới bị lỗi.

Vậy nghĩa là không sử dụng ^ hoặc ~ thì npm install sẽ luôn cài đúng phiên bản package đúng không?

Không, không hề 🙃

Ngay cả khi bạn không dùng ^~ trong file package.json của bạn thì những package của bạn nó cũng dùng ^ hoặc ~ để setting version các dependency mà nó phụ thuộc. Vậy nên nếu chạy npm install vẫn có thể tải về những version khác nhau.


🥇Cách package-lock.json giải quyết vấn đề version không ổn định

Khi bạn cài bất cứ package nào bằng câu lệnh npm install <packagename>, chúng ta sẽ có thêm file package-lock.json.

File package-lock.json sẽ liệt kê hết tất cả những package trong ứng dụng của bạn, bao gồm package của package,… Đó là lý do tại sao file package-lock.json nó lại dài hơn package.json.

  • Nếu bạn chạy chạy câu lệnh npm install mà có cả 2 file package.jsonpackage-lock.json thì bạn yên tâm rằng bạn luôn tải đúng version như đã ghi trong file package-lock.json. File package-lock.json cũng sẽ không bao giờ bị thay đổi
  • Nếu bạn thay đổi bằng tay version hoặc package được ghi trong file package.json và chạy npm install thì lúc này package-lock.json sẽ được cập nhật theo để tương thích với file package.json

Vậy nên nếu có file package-lock.json, bạn sẽ luôn nhận được chính xác version các package của bạn, cho dù đó là hàng ngàn năm sau.

Ngoài npm install, chúng ta còn có một câu lệnh khá là tương đồng là npm ci

npm ci thường được dùng trong các script tự động hóa CI CD.

Sự khác biệt giữa npm installnpm ci là:

  • Nếu những dependency trong package-lock.json không khớp với package.json thì npm ci sẽ ngừng lại và quăng ra lỗi
  • npm ci chỉ có thể cài tất cả các dependency trong project cùng một lúc, không thể cài từng cái như npm install được
  • Nếu node_modules tồn tại, nó sẽ bị xóa trước khi cài npm ci
  • npm ci sẽ không bao giờ viết lên file package.json hoặc package-lock.json

Ví dụ dưới đây sẽ cho bạn thấy công dụng thực tế của npm ci

Nếu có bạn thay đổi bằng tay file package.json ở dưới local, nhưng quên chạy lại câu lệnh npm install, điều này dẫn đến package-lock.json không tương thích với package.json. Bây giờ nếu trên server của bạn có flow là

  1. git pull để pull code mới từ Github về
  2. Sau đó chạy npm install

Nếu với flow này thì sau khi npm install, server bạn sẽ cập nhật file package-lock.json trên server, lúc này package-lock.json ở server khác với trên Github, lần sau bạn sẽ không thể thực hiện theo flow như trên được nữa vì git pull sẽ bị chặn do sự khác nhau giữa package-lock.json ở server và Github

Bạn thấy đấy, dùng npm install trong trường hợp này không hay cho lắm, nếu chúng ta dùng npm ci thì chúng ta sẽ không bao giờ sợ rằng file package-lock.json bị thay đổi, và luôn đảm bảo rằng package-lock.json luôn được đồng bộ với package.json


🥇Tóm lại

  • File package-lock.json sẽ giúp bạn cố định version khi bạn chạy npm install.
  • Bạn nên đưa package-lock.json vào git, đừng ignore nó để tránh những trường hợp lỗi code do update version.
  • Nếu ở local, khi cài package mới hay tải tất cả package trong project thì dùng npm install.
  • Nếu trên server thì nên dùng npm ci để không change bất cứ thứ gì.

Oke, bài viết đến đây là hết rồi đó, mong rằng bài viết có thể giúp bạn hiểu hơn về công dụng của package-lock.json cũng như là package.json

One thought on “Tại sao package-lock.json tồn tại và cách nó hoạt động

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *