HomeLập trìnhJavaScriptGiới thiệu về...

Giới thiệu về cách thức hoạt động của trình quản lý gói JavaScript


Ashley Williams là một trong những người lãnh đạo cộng đồng Node.js. Cô ấy đã tweet về một người quản lý gói mới.

Tôi không thực sự hiểu ý của cô ấy, vì vậy tôi quyết định tìm hiểu sâu hơn và đọc về cách thức hoạt động của các trình quản lý gói.

Điều này đúng khi ứng dụng mới nhất trong khối trình quản lý gói JavaScript – Sợi – vừa xuất hiện và đang tạo ra nhiều tiếng vang.

Vì vậy, tôi đã tận dụng cơ hội này để hiểu cách thức và lý do Yarn làm những việc khác với npm.

Tôi đã có rất nhiều niềm vui khi nghiên cứu điều này. Tôi ước tôi đã làm như vậy từ lâu rồi. Vì vậy, tôi đã viết phần giới thiệu đơn giản này về npm và Yarn để chia sẻ những gì tôi đã học được.

Hãy bắt đầu với một số định nghĩa:

một gói là gì?

Gói là một phần mềm có thể tái sử dụng, có thể tải xuống từ sổ đăng ký toàn cầu vào môi trường cục bộ của nhà phát triển. Mỗi gói có thể có hoặc không phụ thuộc vào các gói khác.

Trình quản lý gói là gì?

Nói một cách đơn giản — trình quản lý gói là một phần mềm cho phép bạn quản lý phụ thuộc (mã bên ngoài do bạn hoặc người khác viết) mà dự án của bạn cần để hoạt động chính xác.

Hầu hết các trình quản lý gói sắp xếp các phần sau trong dự án của bạn:

Mã số dự án

Đây là mã của dự án mà bạn cần quản lý các phụ thuộc khác nhau. Thông thường, tất cả mã này được kiểm tra trong một hệ thống kiểm soát phiên bản như Git.

Tệp kê khai

Đây là tệp theo dõi tất cả các phụ thuộc của bạn (các gói sẽ được quản lý). Nó cũng chứa siêu dữ liệu khác về dự án của bạn. Trong thế giới JavaScript, tệp này là của bạn package.json

mã phụ thuộc

Mã này cấu thành các phụ thuộc của bạn. Nó không nên bị thay đổi trong suốt thời gian tồn tại của ứng dụng của bạn và mã dự án của bạn có thể truy cập được trong bộ nhớ khi cần.

Khóa tập tin

Tệp này được viết tự động bởi chính trình quản lý gói. Nó chứa tất cả thông tin cần thiết để tái tạo cây nguồn phụ thuộc đầy đủ. Nó chứa thông tin về từng thành phần phụ thuộc của dự án, cùng với các phiên bản tương ứng của chúng.

Đọc thêm  Học JavaScript bằng cách tạo trò chơi Tetris

Tại thời điểm này, đáng để chỉ ra rằng Sợi sử dụng tệp khóa, trong khi npm thì không. Chúng ta sẽ nói về hậu quả của sự khác biệt này một chút.

Bây giờ tôi đã giới thiệu cho bạn các phần của trình quản lý gói, chúng ta hãy tự thảo luận về các phụ thuộc.

Phụ thuộc phẳng so với lồng nhau

Để hiểu sự khác biệt giữa lược đồ phụ thuộc phẳng so với lồng nhau, hãy thử hình dung biểu đồ phụ thuộc của các phụ thuộc trong dự án của bạn.

Điều quan trọng cần lưu ý là các yếu tố phụ thuộc mà dự án của bạn phụ thuộc vào có thể có các yếu tố phụ thuộc của riêng chúng. Và những phụ thuộc này có thể có một số phụ thuộc chung.

Để làm rõ điều này, giả sử ứng dụng của chúng ta phụ thuộc vào các phụ thuộc A, B và C và C phụ thuộc vào A.

Phụ thuộc phẳng

1*QFSdXpqBdeuJIJDzr0KfZg
Biểu đồ phụ thuộc trong trường hợp phụ thuộc phẳng

Như được hiển thị trong hình ảnh, cả ứng dụng và C đều có A là phần phụ thuộc của chúng. Để giải quyết vấn đề phụ thuộc trong sơ đồ phụ thuộc phẳng, chỉ có một lớp phụ thuộc mà trình quản lý gói của bạn cần duyệt qua.

Tóm lại – bạn chỉ có thể có một phiên bản của một gói cụ thể trong cây nguồn của mình, vì có một không gian tên chung cho tất cả các phần phụ thuộc của bạn.

Giả sử gói A được nâng cấp lên phiên bản 2.0. Nếu ứng dụng của bạn tương thích với phiên bản 2.0, nhưng gói C thì không, thì chúng tôi cần hai phiên bản của gói A để làm cho ứng dụng của chúng tôi hoạt động chính xác. Đây được biết là một Địa ngục phụ thuộc.

Phụ thuộc lồng nhau

1*GWq1l9Mxe0k7teuJCIOlYw
Biểu đồ phụ thuộc trong trường hợp phụ thuộc lồng nhau

Một giải pháp đơn giản để giải quyết vấn đề Địa ngục phụ thuộc là có hai phiên bản khác nhau của gói A — phiên bản 1.0 và phiên bản 2.0.

Đây là nơi các phụ thuộc lồng nhau phát huy tác dụng. Trong trường hợp các phần phụ thuộc lồng nhau, mỗi phần phụ thuộc có thể tách các phần phụ thuộc của chính nó khỏi các phần phụ thuộc khác, trong một không gian tên khác.

Trình quản lý gói cần phải vượt qua nhiều cấp độ để giải quyết vấn đề phụ thuộc.

Đọc thêm  Cách thêm JavaScript vào ứng dụng Rails 6 của bạn

Chúng tôi có thể có một số bản sao của một phụ thuộc duy nhất trong sơ đồ như vậy.

Nhưng như bạn có thể đoán, điều này cũng dẫn đến một số vấn đề. Điều gì sẽ xảy ra nếu chúng tôi thêm một gói khác — gói D — và nó cũng phụ thuộc vào phiên bản 1.0 của gói A?

Vì vậy, với kế hoạch này, chúng ta có thể kết thúc với trùng lặp của phiên bản 1.0 của gói A. Điều này có thể gây nhầm lẫn và chiếm dung lượng ổ đĩa không cần thiết.

Một giải pháp cho vấn đề trên là có hai phiên bản của gói A, v1.0 và v2.0, nhưng chỉ có một bản v1.0 để tránh trùng lặp không cần thiết. Đây là cách tiếp cận được thực hiện bởi npm v3, giúp giảm đáng kể thời gian duyệt cây phụ thuộc.

Như Ashley Williams giải thích, npm v2 cài đặt các phụ thuộc theo cách lồng nhau. Đó là lý do tại sao npm v3 nhanh hơn đáng kể khi so sánh.

Chủ nghĩa quyết định vs Chủ nghĩa không xác định

Một khái niệm quan trọng khác trong trình quản lý gói là tính quyết định. Trong ngữ cảnh của hệ sinh thái JavaScript, tính tất định có nghĩa là tất cả các máy tính có package.json tất cả các tệp sẽ có cùng một cây nguồn phụ thuộc chính xác được cài đặt trên chúng trong node_modules thư mục.

Nhưng với trình quản lý gói không xác định, điều này không được đảm bảo. Ngay cả khi bạn có cùng một package.json trên hai máy tính khác nhau, cách bố trí của bạn node_modules có thể khác nhau giữa chúng.

Chủ nghĩa quyết định là mong muốn. Nó giúp bạn tránh “làm việc trên máy của tôi nhưng nó bị hỏng khi chúng tôi triển khai nó” các vấn đề, phát sinh khi bạn có sự khác biệt node_modules trên các máy tính khác nhau.

1*i4QK4sSGX7Q4RRgOytkSuw
Meme dành cho nhà phát triển nổi tiếng này minh họa các vấn đề với thuyết không tất định.

npm v3, theo mặc định có các lượt cài đặt không xác định và cung cấp tính năng thu nhỏ để làm cho các lượt cài đặt trở nên xác định. Điều này ghi tất cả các gói trên đĩa vào một tệp khóa, cùng với các phiên bản tương ứng của chúng.

Sợi cung cấp các lượt cài đặt xác định vì nó sử dụng tệp khóa để khóa tất cả các phụ thuộc theo cách đệ quy ở cấp ứng dụng. Vì vậy, nếu gói A phụ thuộc vào v1.0 của gói C và gói B phụ thuộc vào v2.0 của gói A, thì cả hai sẽ được ghi vào tệp khóa riêng.

Đọc thêm  Hướng dẫn JavaScript Array.forEach() – Cách lặp qua các phần tử trong một mảng

Khi biết chính xác phiên bản của các phần phụ thuộc mà bạn đang làm việc, bạn có thể dễ dàng tạo lại các bản dựng, sau đó theo dõi và cô lập các lỗi.

“Để làm cho nó rõ ràng hơn, của bạn package.json Những trạng thái “những gì tôi muốn” cho dự án trong khi lockfile của bạn nói “những gì tôi đã có” về mặt phụ thuộc. — Dan Abramov

Vì vậy, bây giờ chúng ta có thể quay lại câu hỏi ban đầu đã khiến tôi bắt đầu cuộc học tập này ngay từ đầu: Tại sao nó được coi là một thực hành tốt để có các tệp khóa cho các ứng dụng, nhưng không phải cho các thư viện?

Lý do chính là bạn thực sự triển khai các ứng dụng. Vì vậy, bạn cần phải có các yếu tố phụ thuộc mang tính quyết định dẫn đến các bản dựng có thể tái sản xuất trong các môi trường khác nhau — thử nghiệm, dàn dựng và sản xuất.

Nhưng điều này không đúng với các thư viện. Thư viện không được triển khai. Chúng được sử dụng để xây dựng các thư viện khác hoặc trong chính ứng dụng. Các thư viện cần linh hoạt để có thể tương thích tối đa.

Nếu chúng ta có một tệp khóa cho mỗi phần phụ thuộc (thư viện) mà chúng tôi đã sử dụng trong một ứng dụng và ứng dụng buộc phải tôn trọng các tệp khóa này, thì sẽ không thể tiến gần đến cấu trúc phụ thuộc phẳng mà chúng ta đã nói trước đó, với phiên bản ngữ nghĩa tính linh hoạt, đây là trường hợp tốt nhất để giải quyết vấn đề phụ thuộc.

Đây là lý do: nếu ứng dụng của bạn phải tôn trọng đệ quy các tệp khóa của tất cả các phần phụ thuộc của bạn, thì sẽ có xung đột phiên bản ở mọi nơi — ngay cả trong các dự án tương đối nhỏ. Điều này sẽ gây ra một lượng lớn trùng lặp không thể tránh khỏi do lập phiên bản ngữ nghĩa.

Điều này không có nghĩa là các thư viện không thể có tệp khóa. Họ chắc chắn có thể. Nhưng vấn đề chính là các trình quản lý gói như Sợi và npm — sử dụng các thư viện này — sẽ không tôn trọng các tệp khóa đó.

Cảm ơn vì đã đọc! Nếu bạn cho rằng bài đăng này hữu ích, vui lòng nhấn vào “︎❤” để giúp quảng bá tác phẩm này tới những người khác.

1*L-UrDWXiwdc5hHgjzlRDjg



Zik.vn – Biên dịch & Biên soạn Lại

spot_img

Create a website from scratch

Just drag and drop elements in a page to get started with Newspaper Theme.

Buy Now ⟶

Bài viết liên quang

DMCA.com Protection Status