Nếu bạn là một nhà phát triển Node.js , thì bạn đã quen thuộc với npm và Yarn . Bạn thậm chí có thể có quan điểm mạnh mẽ về việc sử dụng cái này hơn cái kia. Trong nhiều năm, các nhà phát triển đã phải vật lộn với tình trạng phình to — về lưu trữ đĩa và thời gian xây dựng — khi làm việc với các trình quản lý gói Node.js, đặc biệt là npm .
Sau đó, pnpm xuất hiện, một trình quản lý gói xử lý lưu trữ gói theo cách khác, giúp người dùng tiết kiệm không gian và giảm thời gian xây dựng. Sau đây là cách pnpm mô tả sự khác biệt :
“Khi bạn cài đặt một gói, chúng tôi lưu trữ nó trong một kho lưu trữ toàn cầu trên máy của bạn, sau đó chúng tôi tạo một liên kết cứng từ nó thay vì sao chép. Đối với mỗi phiên bản của một mô-đun, chỉ có một bản sao được lưu trên đĩa. Ví dụ, khi sử dụng npm hoặc yarn, nếu bạn có 100 gói sử dụng lodash, bạn sẽ có 100 bản sao của lodash trên đĩa. pnpm cho phép bạn tiết kiệm hàng gigabyte dung lượng đĩa!”
Không có gì ngạc nhiên khi pnpm đang ngày càng được ưa chuộng, với ngày càng nhiều nhà phát triển lựa chọn trình quản lý gói của họ. Cùng với tỷ lệ áp dụng ngày càng tăng đó, nhiều nhà phát triển chạy ứng dụng của họ trên Heroku (như tôi) muốn thấy pnpm được hỗ trợ.
May mắn thay, pnpm có sẵn thông qua Corepack , được phân phối với Node.js. Vì vậy, kể từ tháng 5 năm 2024, pnpm hiện đã có sẵn trong Heroku !
Trong bài đăng này, chúng tôi sẽ đề cập đến những gì cần thiết để bắt đầu với pnpm trên Heroku. Và chúng tôi cũng sẽ giới thiệu một số lợi ích về lưu trữ và thời gian xây dựng mà bạn nhận được khi sử dụng nó.
pnpm được tạo ra để giải quyết vấn đề tồn tại lâu dài của trình quản lý gói Node.js về lưu trữ dư thừa và sự thiếu hiệu quả trong việc xử lý phụ thuộc . npm và Yarn sao chép các phụ thuộc vào node_modules
của từng dự án. Ngược lại, pnpm lưu trữ tất cả các gói cho tất cả các dự án trong một kho lưu trữ toàn cục duy nhất và sau đó tạo các liên kết cứng đến các gói này thay vì sao chép chúng. Điều này có nghĩa là gì?
Giả sử chúng ta có một dự án Node.js sử dụng lodash
. Đương nhiên, dự án sẽ có một thư mục node_modules
, cùng với một thư mục con có tên là lodash
, chứa đầy các tệp. Chính xác thì [email protected]
có 639 tệp và một thư mục con khác có tên là fp
, với 415 tệp khác.
Chỉ riêng lodash
đã có hơn một nghìn tập tin rồi!
Tôi đã tạo sáu dự án Node.js: hai dự án với pnpm, hai dự án với npm và hai dự án với Yarn. Mỗi dự án đều sử dụng lodash
. Chúng ta hãy xem thông tin chỉ dành cho một trong các tệp trong thư mục phụ thuộc lodash
.
~/six-projects$ ls -i npm-foo/node_modules/lodash/lodash.js 14754214 -rw-rw-r-- 544098 npm-foo/node_modules/lodash/lodash.js ~/six-projects$ ls -i npm-bar/node_modules/lodash/lodash.js 14757384 -rw-rw-r-- 544098 npm-bar/node_modules/lodash/lodash.js ~/six-projects$ ls -i yarn-foo/node_modules/lodash/lodash.js 14760047 -rw-r--r-- 544098 yarn-foo/node_modules/lodash/lodash.js ~/six-projects$ ls -i yarn-bar/node_modules/lodash/lodash.js 14762739 -rw-r--r-- 544098 yarn-bar/node_modules/lodash/lodash.js ~/six-projects$ ls -i pnpm-foo/node_modules/lodash/lodash.js 15922696 -rw-rw-r-- 544098 pnpm-foo/node_modules/lodash/lodash.js ~/six-projects$ ls -i pnpm-bar/node_modules/lodash/lodash.js 15922696 -rw-rw-r-- 544098 pnpm-bar/node_modules/lodash/lodash.js
Tệp lodash.js
có kích thước hơn nửa megabyte một chút. Chúng tôi không thấy liên kết mềm, vì vậy thoạt nhìn, có vẻ như mỗi dự án đều có bản sao riêng của tệp này. Tuy nhiên, thực tế không phải vậy.
Tôi đã sử dụng ls
với cờ -i
để hiển thị inode của tệp lodash.js
. Bạn có thể thấy trong các dự án pnpm-foo
và pnpm-bar
, cả hai tệp đều có cùng inode ( 15922696
). Chúng đang trỏ đến cùng một tệp! Không phải trường hợp của npm hoặc Yarn.
Vì vậy, nếu bạn có hàng chục dự án sử dụng npm hoặc Yarn, và các dự án đó sử dụng lodash
, thì bạn sẽ có hàng chục bản sao khác nhau của lodash
, cùng với các bản sao từ các phụ thuộc khác trong các dự án đó sử dụng lodash
. Trong pnpm, mọi dự án và phụ thuộc yêu cầu phiên bản lodash
cụ thể này đều trỏ đến cùng một bản sao toàn cục duy nhất.
Mã cho [email protected]
chỉ có kích thước dưới 5 MB. Bạn muốn có 100 bản sao dự phòng của nó trên máy của mình hay chỉ một bản sao toàn cầu?
Vào cuối ngày, cài đặt dependency với pnpm nhanh hơn đáng kể, yêu cầu ít dung lượng đĩa và ít tài nguyên hơn. Đối với các nhà phát triển làm việc trên nhiều dự án hoặc quản lý các dependency trên nền tảng đám mây, pnpm cung cấp một cách tinh gọn hơn, nhanh hơn để quản lý các gói. Điều này làm cho pnpm trở nên lý tưởng cho một môi trường triển khai hợp lý như Heroku.
Bạn đã sẵn sàng để bắt đầu sử dụng chưa? Chúng ta hãy cùng tìm hiểu cách thực hiện.
Sau đây là phiên bản Node.js mà chúng tôi đang sử dụng trên máy của mình:
$ node --version v20.18.0
Như đã đề cập ở trên, Corepack đi kèm với Node.js, vì vậy chúng ta chỉ cần sử dụng corepack
để kích hoạt và sử dụng pnpm. Chúng ta tạo một thư mục cho dự án của mình. Sau đó, chúng ta chạy các lệnh sau:
~/project-pnpm$ corepack enable pnpm ~/project-pnpm$ corepack use pnpm@latest Installing [email protected] in the project... Already up to date Done in 494ms
Lệnh này sẽ tạo ra tệp package.json
trông như thế này:
{ "packageManager": "[email protected]+sha512.22721b3a11f81661ae1ec68ce1a7b879425a1ca5b991c975b074ac220b187ce56c708fe5db69f4c962c989452eee76c82877f4ee80f474cebd61ee13461b6228" }
Lệnh này cũng tạo ra tệp pnpm-lock.yaml
.
Tiếp theo, chúng ta thêm các dependency vào dự án của mình. Để minh họa, chúng ta sao chép danh sách dependencies
và devDependencies
được tìm thấy trong tệp package.json
chuẩn này trên GitHub . Bây giờ, tệp package.json
của chúng ta trông như thế này:
{ "version": "0.0.1", "dependencies": { "animate.less": "^2.2.0", "autoprefixer": "^10.4.17", "babel-core": "^6.26.3", "babel-eslint": "^10.1.0", ... "webpack-split-by-path": "^2.0.0", "whatwg-fetch": "^3.6.20" }, "devDependencies": { "nan-as": "^1.6.1" }, "packageManager": "[email protected]+sha512.22721b3a11f81661ae1ec68ce1a7b879425a1ca5b991c975b074ac220b187ce56c708fe5db69f4c962c989452eee76c82877f4ee80f474cebd61ee13461b6228" }
Sau đó, chúng ta cài đặt các gói.
~/project-pnpm$ pnpm install
Cách sử dụng pnpm khá giống với npm hoặc yarn, do đó nó phải trực quan. Dưới đây là bảng so sánh các cách sử dụng khác nhau cho các lệnh phổ biến (trích từ bài đăng này ).
Bây giờ chúng tôi đã chỉ cho bạn cách để đưa một dự án vào hoạt động với pnpm (khá đơn giản, phải không?), chúng tôi muốn so sánh thời gian xây dựng cho các trình quản lý gói khác nhau khi chạy trên Heroku. Chúng tôi thiết lập ba dự án với các phụ thuộc giống hệt nhau — sử dụng npm, Yarn và pnpm.
Đầu tiên, chúng ta đăng nhập vào Heroku CLI ( heroku login
).
Sau đó, chúng tôi tạo một ứng dụng cho một dự án. Chúng tôi sẽ trình bày các bước cho dự án npm.
~/project-npm$ heroku apps:create --stack heroku-24 npm-timing Creating ⬢ npm-timing... done, stack is heroku-24 https://npm-timing-5d4e30a1c656.herokuapp.com/ | https://git.heroku.com/npm-timing.git
Chúng tôi đã tìm thấy một buildpack thêm dấu thời gian vào các bước build trong nhật ký Heroku để chúng tôi có thể tính toán thời gian build thực tế cho các dự án của mình. Chúng tôi muốn thêm buildpack đó vào dự án của mình và chạy nó trước buildpack chuẩn cho Node.js. Chúng tôi thực hiện điều đó bằng hai lệnh sau:
~/project-npm$ heroku buildpacks:add \ --index=1 \ https://github.com/edmorley/heroku-buildpack-timestamps.git \ --app pnpm-timing ~/project-npm$ heroku buildpacks:add \ --index=2 heroku/nodejs \ --app npm-timing Buildpack added. Next release on npm-timing will use: 1. https://github.com/edmorley/heroku-buildpack-timestamps.git 2. heroku/nodejs Run git push heroku main to create a new release using these buildpacks.
Vậy là xong! Sau đó, chúng ta đẩy mã lên cho dự án được quản lý bằng npm.
~/project-npm$ git push heroku main ... remote: Updated 4 paths from 5af8e67 remote: Compressing source files... done. remote: Building source: remote: remote: -----> Building on the Heroku-24 stack remote: -----> Using buildpacks: remote: 1. https://github.com/edmorley/heroku-buildpack-timestamps.git remote: 2. heroku/nodejs remote: -----> Timestamp app detected remote: -----> Node.js app detected ... remote: 2024-10-22 22:31:29 -----> Installing dependencies remote: 2024-10-22 22:31:29 Installing node modules remote: 2024-10-22 22:31:41 remote: 2024-10-22 22:31:41 added 1435 packages, and audited 1436 packages in 11s remote: 2024-10-22 22:31:41 remote: 2024-10-22 22:31:41 184 packages are looking for funding remote: 2024-10-22 22:31:41 run `npm fund` for details remote: 2024-10-22 22:31:41 remote: 2024-10-22 22:31:41 96 vulnerabilities (1 low, 38 moderate, 21 high, 36 critical) remote: 2024-10-22 22:31:41 remote: 2024-10-22 22:31:41 To address issues that do not require attention, run: remote: 2024-10-22 22:31:41 npm audit fix remote: 2024-10-22 22:31:41 remote: 2024-10-22 22:31:41 To address all issues possible (including breaking changes), run: remote: 2024-10-22 22:31:41 npm audit fix --force remote: 2024-10-22 22:31:41 remote: 2024-10-22 22:31:41 Some issues need review, and may require choosing remote: 2024-10-22 22:31:41 a different dependency. remote: 2024-10-22 22:31:41 remote: 2024-10-22 22:31:41 Run `npm audit` for details. remote: 2024-10-22 22:31:41 npm notice remote: 2024-10-22 22:31:41 npm notice New minor version of npm available! 10.8.2 -> 10.9.0 remote: 2024-10-22 22:31:41 npm notice Changelog: https://github.com/npm/cli/releases/tag/v10.9.0 remote: 2024-10-22 22:31:41 npm notice To update run: npm install -g [email protected] remote: 2024-10-22 22:31:41 npm notice remote: 2024-10-22 22:31:41 remote: 2024-10-22 22:31:41 -----> Build remote: 2024-10-22 22:31:41 remote: 2024-10-22 22:31:41 -----> Caching build remote: 2024-10-22 22:31:41 - npm cache remote: 2024-10-22 22:31:41 remote: 2024-10-22 22:31:41 -----> Pruning devDependencies remote: 2024-10-22 22:31:44 remote: 2024-10-22 22:31:44 up to date, audited 1435 packages in 4s remote: 2024-10-22 22:31:44 remote: 2024-10-22 22:31:44 184 packages are looking for funding remote: 2024-10-22 22:31:44 run `npm fund` for details remote: 2024-10-22 22:31:45 remote: 2024-10-22 22:31:45 96 vulnerabilities (1 low, 38 moderate, 21 high, 36 critical) remote: 2024-10-22 22:31:45 remote: 2024-10-22 22:31:45 To address issues that do not require attention, run: remote: 2024-10-22 22:31:45 npm audit fix remote: 2024-10-22 22:31:45 remote: 2024-10-22 22:31:45 To address all issues possible (including breaking changes), run: remote: 2024-10-22 22:31:45 npm audit fix --force remote: 2024-10-22 22:31:45 remote: 2024-10-22 22:31:45 Some issues need review, and may require choosing remote: 2024-10-22 22:31:45 a different dependency. remote: 2024-10-22 22:31:45 remote: 2024-10-22 22:31:45 Run `npm audit` for details. remote: 2024-10-22 22:31:45 npm notice remote: 2024-10-22 22:31:45 npm notice New minor version of npm available! 10.8.2 -> 10.9.0 remote: 2024-10-22 22:31:45 npm notice Changelog: https://github.com/npm/cli/releases/tag/v10.9.0 remote: 2024-10-22 22:31:45 npm notice To update run: npm install -g [email protected] remote: 2024-10-22 22:31:45 npm notice remote: 2024-10-22 22:31:45 remote: 2024-10-22 22:31:45 -----> Build succeeded! ...
Chúng tôi đã xem xét thời gian cho các bước sau, cho đến khi thông báo Build succeeded
gần cuối:
Installing dependencies
Build
Pruning devDependencies
Caching build
Tổng cộng, với npm, quá trình xây dựng này mất 16 giây.
Chúng tôi đã chạy thiết lập tương tự cho dự án do pnpm quản lý, cũng sử dụng gói xây dựng thời gian.
~/project-pnpm$ heroku apps:create --stack heroku-24 pnpm-timing ~/project-pnpm$ heroku buildpacks:add \ --index=1 \ https://github.com/edmorley/heroku-buildpack-timestamps.git \ --app pnpm-timing ~/project-pnpm$ heroku buildpacks:add \ --index=2 heroku/nodejs \ --app pnpm-timing ~/project-pnpm$ git push heroku main … remote: 2024-10-22 22:38:34 -----> Installing dependencies remote: 2024-10-22 22:38:34 Running 'pnpm install' with pnpm-lock.yaml … remote: 2024-10-22 22:38:49 remote: 2024-10-22 22:38:49 dependencies: remote: 2024-10-22 22:38:49 + animate.less 2.2.0 remote: 2024-10-22 22:38:49 + autoprefixer 10.4.20 remote: 2024-10-22 22:38:49 + babel-core 6.26.3 … remote: 2024-10-22 22:38:51 -----> Build succeeded!
Với bản dựng tương tự bằng pnpm, chỉ mất 7 giây.
Chúng tôi thấy rằng tiết kiệm thời gian không chỉ dành cho cài đặt ban đầu. Các bản dựng tiếp theo, sử dụng bộ đệm phụ thuộc, cũng nhanh hơn với pnpm.
Khi tôi mới bắt đầu phát triển Node.js , tôi đã sử dụng npm. Vài năm trước, tôi đã chuyển sang Yarn và đó là những gì tôi đã sử dụng... cho đến gần đây. Bây giờ, tôi đã chuyển sang pnpm. Trên máy cục bộ của mình, tôi có thể giải phóng đáng kể dung lượng đĩa. Việc xây dựng cũng nhanh hơn. Và bây giờ, với sự hỗ trợ của Heroku cho pnpm, điều này khép lại vòng lặp để tôi có thể sử dụng nó độc quyền từ quá trình phát triển cục bộ cho đến khi triển khai trên đám mây.
Chúc bạn viết mã vui vẻ!