paint-brush
आपको PNPM और YARN की आवश्यकता क्यों नहीं है?द्वारा@bormando
1,579 रीडिंग
1,579 रीडिंग

आपको PNPM और YARN की आवश्यकता क्यों नहीं है?

द्वारा Dmitrii Bormotov9m2024/07/23
Read on Terminal Reader

बहुत लंबा; पढ़ने के लिए

npm **Node.js** इकोसिस्टम के लिए एक डिफ़ॉल्ट पैकेज मैनेजर है। यह इंस्टॉलेशन पैकेज के साथ आता है, इसलिए जब आप अपनी मशीन पर **Node.js** इंस्टॉल करते हैं (या किसी भी **CI** प्रदाता में अगर आपने **Node.js** को वहां सेट किया है) तो यह मूल रूप से उपयोग के लिए तैयार है। यह स्थिर है और इसकी गति अन्य पैकेज मैनेजरों के साथ तुलनीय है।
featured image - आपको PNPM और YARN की आवश्यकता क्यों नहीं है?
Dmitrii Bormotov HackerNoon profile picture
0-item

सभी को नमस्कार!


मुझे यकीन है कि आपने Node.js प्रोजेक्ट्स को विभिन्न पैकेज प्रबंधकों का उपयोग करते हुए देखा होगा, जैसे:



मैंने खुद भी ऐसा देखा है और ऊपर बताए गए सभी तरीकों के साथ काम किया है, लेकिन मेरे मन में हमेशा एक सवाल रहता था - लोगों/टीमों को npm के बजाय यार्न या pnpm का उपयोग करने के लिए क्या प्रेरित करता है? इसके क्या फायदे हैं? क्या कोई नुकसान भी है?


खैर... चलो पता लगाते हैं!

प्रदर्शन तुलना नियम

मैंने एनपीएम , यार्न और पीएनपीएम की उनकी "गति" के संदर्भ में तुलना करने का निर्णय लिया...


आपको नीचे 3 उपाय दिखाई देंगे:


  1. बिना किसी कैश के लॉक फ़ाइल उत्पन्न करें.


  2. किसी भी कैश के बिना मौजूदा लॉक फ़ाइलों से निर्भरताएं स्थापित करें।


  3. वैश्विक कैश के साथ मौजूदा लॉक फ़ाइलों से निर्भरताएँ स्थापित करें।


कैश दो प्रकार के होते हैं:


  1. वैश्विक।

    आमतौर पर उपयोगकर्ता की होम निर्देशिका (fe, ~/.yarn/berry/cache ) में संग्रहीत किया जाता है।


  2. स्थानीय।

    प्रोजेक्ट निर्देशिका (fe, <project-dir>/.yarn ) में संग्रहीत.


जबकि मेरे अनुभव में #2 और #3 सबसे आम उपयोग के मामले हैं, मैंने सिर्फ मामले में #1 भी लिया (हालांकि यह एक बहुत ही दुर्लभ मामला है)।


मैंने बेंचमार्क के लिए उदाहरण के रूप में create-react-app से एक नमूना प्रोजेक्ट का उपयोग किया।

NPM

यह Node.js इकोसिस्टम के लिए एक डिफ़ॉल्ट पैकेज मैनेजर है - और क्या कहें? यह इंस्टॉलेशन पैकेज के साथ आता है, इसलिए यह मूल रूप से उपयोग के लिए तैयार है जब आप अपनी मशीन पर Node.js इंस्टॉल करते हैं (या किसी भी CI प्रदाता में यदि आपने Node.js को वहां सेट किया है)।


मेरे विचार में यह एक बहुत बड़ी "सुविधा" है - आपको इसे अलग से स्थापित करने की आवश्यकता नहीं है!


इसमें कुछ भी खास नहीं है - यह बस... काम करता है! और मैंने पिछले कई सालों में कोई बड़ी बग नहीं देखी है - यह काफी स्थिर लगता है और काम पूरा कर देता है।


एनपीएम की वे विशेषताएं जो मैंने अब तक उपयोग की हैं:


  1. निर्भरताएं प्रबंधित करें (इंस्टॉल करें, हटाएं, अपडेट करें)
  2. पैकेज प्रकाशित करें (निजी, सार्वजनिक)
  3. लिंक-स्थानीय पैकेज
  4. कार्यस्थान प्रबंधित करें.

निर्भरताएँ प्रबंधित करें

npm आपके प्रोजेक्ट रूट के node_modules फ़ोल्डर में निर्भरताएँ संग्रहीत करता है। बहुत सरल है।


ℹ️ package-lock.json सूचीबद्ध पैकेजों के लिए रजिस्ट्री के बारे में जानकारी संग्रहीत करता है - यह बहुत उपयोगी है यदि आपके पास एक ही दायरे से पैकेज हैं, यानी @example-company विभिन्न रजिस्ट्री में (उदाहरण के लिए - npm और GitHub पैकेज ):


पैकेज-लॉक.json प्रविष्टि


अब, आइए देखें कि यह इंस्टॉलेशन स्पीड के मामले में कैसा प्रदर्शन करता है...

बिना किसी कैश के package-lock.json उत्पन्न करें

package-lock.json उत्पन्न करें और बिना किसी कैश के निर्भरताएं स्थापित करें


इसमें 1 मिनट npm के लिए package-lock.json उत्पन्न करना और बिना किसी कैश के निर्भरताएं स्थापित करना।


प्रयुक्त आदेश:

 npm i

पैकेज-lock.json से बिना किसी कैश के निर्भरताएँ स्थापित करें

पैकेज-लॉक.json से बिना किसी कैश के निर्भरताएँ स्थापित करें


इसमें 18 सेकंड npm के लिए package-lock.json से बिना किसी कैश के निर्भरताएं स्थापित करना।


प्रयुक्त आदेश:

 npm ci

वैश्विक कैश के साथ package-lock.json से निर्भरताएँ स्थापित करें

वैश्विक कैश के साथ package-lock.json से निर्भरताएँ स्थापित करें


इसमें 8 सेकंड npm के लिए वैश्विक कैश के साथ package-lock.json से निर्भरताएं स्थापित करना।


प्रयुक्त आदेश:

 npm ci

कार्यस्थान प्रबंधित करें

मैं एक बार में संपूर्ण कार्यक्षेत्र बनाने और उसके लिए तथा विशिष्ट परियोजनाओं के लिए अलग से निर्भरताओं का प्रबंधन करने में सक्षम था।


दूसरे शब्दों में - यह बिना किसी बग/समस्या के काम पूरा कर देता है, और आधिकारिक दस्तावेज बहुत सरल है।


कार्यक्षेत्र सुविधाएँ जिनका मैंने अब तक उपयोग किया है:


  1. कार्यक्षेत्र के भीतर सभी परियोजनाओं के लिए निर्भरताएँ स्थापित करें.
  2. किसी एक विशिष्ट परियोजना के लिए निर्भरताएँ स्थापित करें.
  3. सभी परियोजनाओं के लिए एक ही स्क्रिप्ट को एक साथ पुनरावर्ती रूप से चलाएं।

धागा

ईमानदारी से कहूँ तो, मैंने यार्न की कुछ विशेषताओं को ज़्यादा नहीं आजमाया है। मेरा मतलब है, मैंने कुछ प्रोजेक्ट पर काम करते समय "निर्भरता स्थापित करने" के मामले में इसका बहुत उपयोग किया है, और बस इतना ही।


यार्न Node.js इंस्टॉलर के साथ नहीं आता है, इसलिए आपको इसे अलग से इंस्टॉल करना होगा। इसका मतलब है कि आपके CI पाइपलाइन में एक अतिरिक्त चरण होगा - आपको अपनी परियोजना निर्भरताएँ इंस्टॉल करने से पहले यार्न को सेट करना होगा।

निर्भरताएँ प्रबंधित करें

निर्भरता स्थापित करने के लिए यार्न के दो तरीके हैं:


  1. शून्य इंस्टॉल ” (डिफ़ॉल्ट) - .yarn फ़ोल्डर बनाता है और yarn.lock और .pnp.cjs फ़ाइलों में पैकेजों को सूचीबद्ध करता है।


  2. एक नियमित - npm के समान, निर्भरता को node_modules में संग्रहीत करता है और उन्हें yarn.lock फ़ाइल में सूचीबद्ध करता है।


ℹ️ यार्न लॉक फ़ाइलें सभी सूचीबद्ध पैकेजों के लिए रजिस्ट्री के बारे में जानकारी संग्रहीत करती हैं केवल तभी जब आप पुराने (नियमित) स्थापना दृष्टिकोण का उपयोग करते हैं।


⚠️ ध्यान रखें कि " शून्य इंस्टॉल " स्थानीय कैश में पैकेज संग्रहीत करता है और आपकी लॉक फ़ाइलों के लिंक प्रदान करता है:


पैकेज लिंक

यह आपके लिए महत्वपूर्ण हो सकता है यदि आपके पास एक Dockerfile या CI पाइपलाइन है जहां आप एक स्वच्छ वातावरण में निर्भरताएं स्थापित करते हैं और फिर इसे दूसरे में ले जाना चाहते हैं (आपको .yarn फ़ोल्डर और स्थानीय कैश दोनों की प्रतिलिपि बनानी होगी)।


चूंकि अब यार्न के लिए डिफ़ॉल्ट दृष्टिकोण " शून्य इंस्टॉल " है और पुराने दृष्टिकोण की तुलना में इसका प्रदर्शन बेहतर है - हम केवल इसी दृष्टिकोण के साथ बेंचमार्क रिकॉर्ड करने जा रहे हैं।

बिना किसी कैश के लॉक फ़ाइलें उत्पन्न करें

यार्न के साथ लॉक फ़ाइलें उत्पन्न करें और निर्भरताएँ स्थापित करें


इसमें 16.5 सेकंड यार्न के लिए yarn.lock फ़ाइल उत्पन्न करना और कैश के बिना निर्भरताएँ स्थापित करना।


प्रयुक्त आदेश:

 yarn install

बिना किसी कैश के मौजूदा लॉक फ़ाइलों से निर्भरताएँ स्थापित करें

"शून्य इंस्टॉल" दृष्टिकोण और बिना किसी कैश के निर्भरताएं स्थापित करें


इसमें 11 सेकंड यार्न के लिए "शून्य इंस्टॉल" दृष्टिकोण और बिना किसी कैश के निर्भरताएं स्थापित करना।


प्रयुक्त आदेश:

 yarn install --frozen-lockfile

ग्लोबल कैश के साथ मौजूदा लॉक फ़ाइलों से निर्भरताएँ स्थापित करें


"शून्य इंस्टॉल" दृष्टिकोण और वैश्विक कैश के साथ निर्भरताएं स्थापित करें


इसमें 8 सेकंड यार्न के लिए "शून्य इंस्टॉल" दृष्टिकोण और वैश्विक कैश के साथ निर्भरताएं स्थापित करना।


प्रयुक्त आदेश:

 yarn install --frozen-lockfile

कार्यस्थान प्रबंधित करें

मैं एक कार्यक्षेत्र बनाने और सभी परियोजनाओं के लिए एक साथ तथा विशिष्ट परियोजनाओं के लिए अलग से निर्भरताओं का प्रबंधन करने में सक्षम था।


कार्यक्षेत्र सुविधाएँ जिनका मैंने अब तक उपयोग किया है:


  1. कार्यक्षेत्र के भीतर सभी परियोजनाओं के लिए निर्भरताएँ स्थापित करें.
  2. किसी एक विशिष्ट परियोजना के लिए निर्भरताएँ स्थापित करें.
  3. सभी परियोजनाओं के लिए एक ही स्क्रिप्ट को एक साथ पुनरावर्ती रूप से चलाएं।


दस्तावेज़ीकरण तो ठीक है, लेकिन कमांड नाम और फ़्लैग कुछ हद तक भ्रामक हैं।


उदाहरण के लिए, मुझे रूट ( . ) और नेस्टेड b2b प्रोजेक्ट में test स्क्रिप्ट चलाने के लिए इसे निष्पादित करना होगा:


 yarn workspaces foreach -A --include '{.,b2b}' run test


एनपीएम की तुलना में:


 npm run test --workspace=b2b --include-workspace-root

पीएनपीएम

pnpm वर्तमान में काफी लोकप्रिय है - बहुत सारी कंपनियां और ओपन सोर्स परियोजनाएं इसका उपयोग करती हैं


यार्न की तरह ही - pnpm Node.js इंस्टॉलर के साथ नहीं आता है, इसलिए आपको इसे अलग से इंस्टॉल करना होगा। इसका मतलब है कि आपकी CI पाइपलाइन में एक अतिरिक्त चरण होगा - आपको अपनी प्रोजेक्ट निर्भरताएँ इंस्टॉल करने से पहले pnpm सेट करना होगा।

निर्भरताएँ प्रबंधित करें

pnpm को " तेज़, डिस्क स्थान कुशल पैकेज प्रबंधक " माना जाता है ...


वास्तव में, मैं स्थानीय स्तर पर निर्भरताओं के प्रबंधन के संदर्भ में "डिस्क स्थान कुशल" कथन से सहमत हूं।


डिफ़ॉल्ट रूप से, pnpm साझा निर्भरताओं को डी-डुप्लिकेट करता है। pnpm उन पैकेजों के लिए सिम्बलिंक बनाता है जो कई निर्भरताओं में उपयोग किए जाते हैं। यानी, अगर पैकेज a और b निर्भरता के रूप में पैकेज c का उपयोग करते हैं - pnpm पैकेज c एक एकल प्रतिलिपि के रूप में संग्रहीत करेगा और पैकेज a और b के लिए सिम्बलिंक बनाएगा। इस तरह, पैकेज प्रबंधक हार्ड कॉपी नहीं बनाता है और आपके SSD/HDD पर मेमोरी बचाता है।


ℹ️ pnpm-lock.yaml सूचीबद्ध पैकेजों के लिए रजिस्ट्री के बारे में जानकारी संग्रहीत नहीं करता है।


⚠️ ध्यान रखें कि pnpm कभी-कभी निर्भरता को प्रोजेक्ट के रूप में रखने के बजाय वैश्विक कैश में संग्रहीत करता है।

बिना किसी कैश के pnpm-lock.yaml उत्पन्न करें

pnpm-lock.yaml उत्पन्न करें


इसमें 31 सेकंड pnpm के लिए pnpm-lock.yaml उत्पन्न करना और बिना किसी कैश के निर्भरताएं स्थापित करना।


प्रयुक्त आदेश:

 pnpm install

वैश्विक कैश के बिना pnpm-lock.yaml से निर्भरताएँ स्थापित करें

वैश्विक कैश के बिना pnpm-lock.yaml से निर्भरताएँ स्थापित करें


इसमें 16 सेकंड pnpm के लिए कैश के बिना pnpm-lock.yaml से निर्भरताएं स्थापित करना।


प्रयुक्त आदेश:

 pnpm i --frozen-lockfile


ग्लोबल कैश के साथ मौजूदा लॉक फ़ाइल से निर्भरताएँ स्थापित करें

कैश के साथ pnpm-lock-yaml से निर्भरताएँ स्थापित करें


इसमें 5 सेकंड pnpm के लिए वैश्विक कैश के साथ pnpm-lock.yaml से निर्भरताएं स्थापित करना।


प्रयुक्त आदेश:

 pnpm i --frozen-lockfile

कार्यस्थान प्रबंधित करें

अब, यहीं से चीजें वास्तव में दिलचस्प हो जाती हैं...


pnpm में बहुत सारे कॉन्फ़िगरेशन विकल्प हैं, लेकिन कुछ मुख्य कार्यक्षमताएं काम नहीं करतीं!


आइये उन कुछ त्रुटियों की समीक्षा करें जिनका मुझे सामना करना पड़ा:

pnpm इंस्टॉल --फ़िल्टर

केवल विशिष्ट परियोजनाओं के लिए निर्भरताएं स्थापित करने में सक्षम होना महत्वपूर्ण है - यह मोनोरेपो के लिए काफी उपयोगी है जब आप कार्यक्षेत्र के भीतर विशिष्ट परियोजनाओं से संबंधित पाइपलाइन बनाते हैं।


यानी, कल्पना करें कि आपके कार्यस्थल में यह है:


  • एक वेब ऐप,
  • बैकएंड सर्वर,
  • परीक्षण परियोजना (अंत-से-अंत परीक्षण)।


ये सभी अलग-अलग एनपीएम परियोजनाएं हैं, लेकिन वे एक ही रेपो का हिस्सा हैं ☝️


अब, आप केवल एंड-टू-एंड टेस्ट चलाने के लिए पाइपलाइन चाहते हैं। तो, आपको केवल एंड-टू-एंड टेस्ट निर्भरता की आवश्यकता है, है ना?


खैर, आप ऐसा नहीं कर पाएंगे - pnpm आपको संपूर्ण कार्यक्षेत्र के लिए निर्भरताएं स्थापित करने के लिए बाध्य कर रहा है!


pnpm install --filter <project-name> केवल चयनित परियोजनाओं के लिए निर्भरताएं स्थापित करनी थी, लेकिन यह काम नहीं करता है।


यह एक साल पुराना बग है और इसे हाल ही में एक गैर-कार्यशील फिक्स के साथ बंद कर दिया गया है।

पुनरावर्ती-स्थापना=झूठ

जब आप pnpm install चलाते हैं तो pnpm डिफ़ॉल्ट रूप से संपूर्ण कार्यक्षेत्र (सभी प्रोजेक्ट) के लिए निर्भरताएँ स्थापित करता है


यदि आप अपने कार्यस्थान रूट में .npmrc में recursive-install=false सेट करते हैं तो आप इस व्यवहार को वैकल्पिक कर सकते हैं।


लेकिन इसमें एक और बग शामिल है जो लगभग 2 साल पुराना है

साझा-कार्यस्थान-लॉकफ़ाइल=गलत

pnpm डिफ़ॉल्ट रूप से निर्भरता सूची को एकल लॉक फ़ाइल में संग्रहीत करता है ( npm और यार्न के समान)।


यदि आप अपने वर्कस्पेस रूट में .npmrc में shared-workspace-lockfile=false सेट करते हैं, तो आप इस व्यवहार को वैकल्पिक भी कर सकते हैं।


इससे हमें वर्कस्पेस सुविधा को बनाए रखने और किसी विशिष्ट परियोजना के लिए निर्भरताएं स्थापित करने के लिए --ignore-workspace ध्वज का उपयोग करने की अनुमति मिल जाएगी।


वैसे, यह सेटिंग कुछ और समस्याएं भी उत्पन्न करती है:


  1. eslint और tsc --noEmit मेरे GitHub Actions पाइपलाइनों में "JavaScript Heap Out of Memory" त्रुटि फेंकते हैं।


  2. कुछ निर्भरताएँ वैश्विक कैश में संग्रहीत हैं और node_modules/.pnpm में सिमलिंक की गई हैं।

प्रदर्शन तुलना परिणाम

#

NPM

धागा

पीएनपीएम

लॉक फ़ाइल बनाएं

60 सेकंड

16.5 सेकंड

31 सेकंड

बिना किसी कैश के निर्भरताएँ स्थापित करें

18 सेकंड

11 सेकंड

8 सेकंड

वैश्विक कैश के साथ निर्भरताएँ स्थापित करें

8 सेकंड

8 सेकंड

5 सेकंड


उपरोक्त बेंचमार्क के अनुसार, npm सबसे धीमा पैकेज मैनेजर है ☝️


खैर, आइए इन परिणामों की व्याख्या करें...

लॉक फ़ाइल बनाएं

यह एक दुर्लभ मामला है। आम तौर पर, प्रोजेक्ट आरंभीकरण पर एक लॉक फ़ाइल बनाई जाती है और फिर जब आप पैकेज स्थापित/अपडेट करते हैं तो विस्तारित होती है।


इसे ध्यान में रखते हुए - ऐसा नहीं लगता कि पैकेज मैनेजर चुनते समय इस पर भरोसा करना बहुत महत्वपूर्ण बात है।

निर्भरताएँ स्थापित करें

अधिकांश मामलों में, आपकी परियोजनाएं निर्भरताओं की एक विशिष्ट सूची रखती हैं और आप शायद ही कभी कुछ जोड़ते/हटाते हैं।


सबसे अधिक संभावना यह है कि आप समय-समय पर अपने पैकेजों के संस्करणों में बदलाव करते रहेंगे - ये परिवर्तन छोटे होते हैं और आप कैश से शेष पैकेजों का पुनः उपयोग करेंगे।


दूसरे शब्दों में, सामान्य उपयोग मामला है - पैकेज रजिस्ट्री से नए पैकेज लाना और शेष को कैश से प्राप्त करना।


pnpm (5-8 सेकंड) मध्य में यार्न (8-11 सेकंड) के साथ npm (8-18 सेकंड) की तुलना में लगभग दोगुना तेज है।

निष्कर्ष

तथ्य

  • pnpm वास्तव में "एक तेज़ और डिस्क कुशल" पैकेज प्रबंधक है - यह वर्तमान समीक्षा में बिल्कुल स्पष्ट है!


  • pnpm वर्कस्पेस सुविधा में खामियां हैं और कुछ खामियां वर्षों से अनसुलझी हैं।


  • pnpm और यार्न दोनों को CI पाइपलाइनों में अतिरिक्त सेटअप की आवश्यकता होती है, जबकि npm को इसकी आवश्यकता नहीं होती।


  • pnpm और यार्न दोनों ही अपने लॉक फाइलों में पैकेज रजिस्ट्री जानकारी संग्रहीत नहीं करते हैं, जबकि npm ऐसा करता है।

लेखक के विचार

मुझे लगता है कि यदि पैकेज मैनेजर के लिए आपकी आवश्यकता "केवल निर्भरताएं स्थापित करें" जैसी सरल है, तो pnpm सबसे अच्छा काम करता है।


भले ही pnpm Node.js इंस्टॉलर के साथ नहीं आता है, फिर भी इसे कोरपैक या मौजूदा एक्शन के साथ CI पाइपलाइनों में सेट करना आसान है।


मैं npm को प्राथमिकता देता हूं, क्योंकि:


  • यह स्थिर है (विशेषकर कार्यस्थलों पर),


  • Node.js के साथ आता है और CI पाइपलाइन में अतिरिक्त सेटअप की आवश्यकता नहीं होती है,


  • पैकेज रजिस्ट्री को package-lock.json में संग्रहीत करता है ताकि आप विभिन्न रजिस्ट्री से एकल स्कोप के साथ निर्भरताएं स्थापित कर सकें।


ये फायदे उस गति और डिस्क स्थान के सेकंड से अधिक हैं जो मैं यार्न या पीएनपीएम के साथ बचा सकता था।


पैकेज मैनेजर चुनने के लिए आपके मानदंड क्या हैं? संकोच न करें, और नीचे टिप्पणी अनुभाग में मुझे अपने विचार बताएं! 👇😊