اگر یک توسعه دهنده Node.js هستید، پس با npm و Yarn آشنا هستید. حتی ممکن است در مورد استفاده از یکی بر دیگری نظر قوی داشته باشید. برای سالها، توسعهدهندگان در هنگام کار با مدیران بستههای Node.js، بهویژه npm ، با مشکلی در ذخیرهسازی دیسک و زمان ساخت دست و پنجه نرم میکنند.
سپس، pnpm آمد، یک مدیر بسته که فضای ذخیره سازی بسته را به گونه ای متفاوت مدیریت می کند، فضای کاربران را ذخیره می کند و زمان ساخت را کاهش می دهد. در اینجا نحوه توصیف تفاوت pnpm آمده است:
هنگامی که یک بسته را نصب می کنید، آن را در یک فروشگاه جهانی روی دستگاه شما نگه می داریم، سپس به جای کپی کردن، یک لینک سخت از آن ایجاد می کنیم. برای هر نسخه از یک ماژول، تنها یک نسخه روی دیسک نگهداری می شود. به عنوان مثال، هنگام استفاده از npm یا نخ، اگر 100 بسته با استفاده از لوداش دارید، 100 نسخه از لوداش روی دیسک خواهید داشت. pnpm به شما اجازه می دهد تا در فضای دیسک گیگابایت صرفه جویی کنید!
جای تعجب نیست که pnpm در حال افزایش است و توسعه دهندگان بیشتری آن را مدیر بسته انتخابی خود می کنند. همراه با نرخ پذیرش رو به رشد، بسیاری از توسعه دهندگانی که برنامه های خود را روی Heroku اجرا می کنند (مثل من) می خواستند از pnpm پشتیبانی کنند.
خوشبختانه، pnpm از طریق Corepack در دسترس است که با Node.js توزیع شده است. بنابراین، از ماه می 2024، pnpm اکنون در Heroku در دسترس است !
در این پست، آنچه را که برای شروع کار با pnpm در Heroku نیاز است را پوشش خواهیم داد. و همچنین برخی از مزایای ذخیره سازی و زمان ساخت را که از استفاده از آن به دست می آورید، نشان خواهیم داد.
pnpm برای حل مشکل قدیمی Node.js Package Manager مربوط به فضای ذخیرهسازی اضافی و ناکارآمدی در مدیریت وابستگی ایجاد شده است. npm و Yarn وابستگی ها را در node_modules
هر پروژه کپی می کنند. در مقابل، pnpm همه بستهها را برای همه پروژهها در یک فروشگاه جهانی نگه میدارد و سپس به جای کپی کردن، پیوندهای سختی را برای این بستهها ایجاد میکند. این به چه معناست؟
بیایید فرض کنیم یک پروژه Node.js داریم که از lodash
استفاده می کند. به طور طبیعی، پروژه دارای یک پوشه node_modules
به همراه یک زیرپوشه به نام lodash
است که با فایلها پر شده است. به طور دقیق، [email protected]
دارای 639 فایل و یک زیر پوشه دیگر به نام fp
با 415 فایل دیگر است.
این بیش از هزار فایل تنها برای lodash
است!
من شش پروژه Node.js ایجاد کردم: دو پروژه با pnpm، دو پروژه با npm و دو پروژه با Yarn. هر کدام از آنها از lodash
استفاده می کنند. بیایید نگاهی به اطلاعات تنها یکی از فایلهای موجود در پوشه وابستگی 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
حجم فایل lodash.js
کمی بیش از نیم مگابایت است. ما لینکهای نرمافزاری را نمیبینیم، بنابراین در نگاه اول، واقعاً به نظر میرسد که هر پروژه کپی مخصوص به خود از این فایل را دارد. با این حال، در واقع اینطور نیست.
من ls
با پرچم -i
برای نمایش inode فایل lodash.js
استفاده کردم. می توانید در پروژه های pnpm-foo
و pnpm-bar
ببینید، هر دو فایل دارای inode یکسان هستند ( 15922696
). آنها به همان پرونده اشاره می کنند! این مورد برای npm یا Yarn نیست.
بنابراین، اگر چندین پروژه دارید که از npm یا Yarn استفاده میکنند، و آن پروژهها از lodash
استفاده میکنند، آنوقت دهها نسخه مختلف از lodash
به همراه کپیهایی از وابستگیهای دیگر در آن پروژههایی خواهید داشت که خودشان از lodash
استفاده میکنند. در pnpm، هر پروژه و وابستگی که به این نسخه خاص از lodash
نیاز دارد به همان نسخه تکی و سراسری اشاره دارد.
حجم کد [email protected]
کمتر از 5 مگابایت است. آیا ترجیح می دهید 100 نسخه اضافی از آن در دستگاه خود داشته باشید یا فقط یک نسخه جهانی؟
در پایان روز، نصب وابستگی با pnpm به طور قابل توجهی سریعتر است، به فضای دیسک کمتر و منابع کمتری نیاز دارد. برای توسعهدهندگانی که در چندین پروژه کار میکنند یا وابستگیها را بر روی پلتفرمهای ابری مدیریت میکنند، pnpm یک راه سادهتر و سریعتر برای مدیریت بستهها ارائه میدهد. این باعث می شود pnpm برای یک محیط استقرار ساده مانند Heroku ایده آل باشد.
آیا برای شروع استفاده از آن آماده اید؟ بیایید از طریق چگونه راه رفتن.
در اینجا نسخه Node.js است که ما با آن در دستگاه خود کار می کنیم:
$ node --version v20.18.0
همانطور که در بالا ذکر کردیم، Corepack با Node.js ارائه می شود، بنابراین ما فقط باید از corepack
برای فعال کردن و استفاده از pnpm استفاده کنیم. ما یک پوشه برای پروژه خود ایجاد می کنیم. سپس، این دستورات را اجرا می کنیم:
~/project-pnpm$ corepack enable pnpm ~/project-pnpm$ corepack use pnpm@latest Installing [email protected] in the project... Already up to date Done in 494ms
این یک فایل package.json
تولید می کند که به شکل زیر است:
{ "packageManager": "[email protected]+sha512.22721b3a11f81661ae1ec68ce1a7b879425a1ca5b991c975b074ac220b187ce56c708fe5db69f4c962c989452eee76c82877f4ee80f474cebd61ee13461b6228" }
این همچنین یک فایل pnpm-lock.yaml
تولید می کند.
در مرحله بعد، وابستگی هایی را به پروژه خود اضافه می کنیم. برای اهداف نمایشی، ما لیستی از dependencies
و devDependencies
موجود در این فایل معیاری package.json
را در GitHub کپی می کنیم. اکنون، فایل package.json
ما به شکل زیر است:
{ "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" }
سپس بسته ها را نصب می کنیم.
~/project-pnpm$ pnpm install
استفاده از pnpm تقریباً شبیه npm یا نخ است و بنابراین باید بصری باشد. در زیر جدولی وجود دارد که کاربردهای مختلف دستورات رایج را مقایسه می کند (برگرفته از این پست ).
اکنون که نحوه راهاندازی و اجرای یک پروژه با pnpm را نشان دادیم (خیلی ساده است، درست است)، میخواهیم زمانهای ساخت را برای مدیران بستههای مختلف هنگام اجرا بر روی Heroku مقایسه کنیم. ما سه پروژه را با وابستگی های یکسان راه اندازی کردیم - با استفاده از npm، Yarn و pnpm.
ابتدا وارد Heroku CLI ( heroku login
) می شویم.
سپس، ما یک برنامه برای یک پروژه ایجاد می کنیم. ما مراحل پروژه 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
ما یک buildpack پیدا کردیم که مهرهای زمانی را به مراحل ساخت در گزارش Heroku اضافه می کند تا بتوانیم زمان ساخت واقعی پروژه های خود را محاسبه کنیم. ما می خواهیم آن buildpack را به پروژه خود اضافه کنیم و قبل از buildpack استاندارد برای Node.js اجرا شود. این کار را با دو دستور زیر انجام می دهیم:
~/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.
همین! سپس، کد پروژه مدیریت شده با 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! ...
ما به زمانبندی مراحل زیر نگاه کردیم، تا زمانی که پیام Build succeeded
نزدیک به پایان رسید:
Installing dependencies
Build
Pruning devDependencies
Caching build
در کل با npm این ساخت 16 ثانیه طول کشید.
ما همین تنظیمات را برای پروژه مدیریت شده با pnpm اجرا کردیم، همچنین از buildpack زمانبندی استفاده کردیم.
~/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!
برای همان ساخت با pnpm، فقط 7 ثانیه طول کشید.
ما دریافتیم که صرفه جویی در زمان فقط برای آن نصب اولیه نیست. ساختهای بعدی که از کش وابستگی استفاده میکنند، با pnpm نیز سریعتر هستند.
وقتی برای اولین بار توسعه Node.js را شروع کردم، از npm استفاده کردم. چندین سال پیش به Yarn تغییر مکان دادم و این همان چیزی بود که از آن استفاده می کردم. . . تا همین اواخر اکنون، من به pnpm تغییر داده ام. در دستگاه محلی خود، میتوانم فضای قابل توجهی از دیسک را آزاد کنم. ساختها نیز سریعتر هستند. و اکنون، با پشتیبانی Heroku برای pnpm، این حلقه را می بندد تا بتوانم از آن به طور انحصاری از توسعه محلی تا استقرار در فضای ابری استفاده کنم.
کد نویسی مبارک!