सभी को नमस्कार!
मुझे यकीन है कि आपने Node.js प्रोजेक्ट्स को विभिन्न पैकेज प्रबंधकों का उपयोग करते हुए देखा होगा, जैसे:
मैंने खुद भी ऐसा देखा है और ऊपर बताए गए सभी तरीकों के साथ काम किया है, लेकिन मेरे मन में हमेशा एक सवाल रहता था - लोगों/टीमों को npm के बजाय यार्न या pnpm का उपयोग करने के लिए क्या प्रेरित करता है? इसके क्या फायदे हैं? क्या कोई नुकसान भी है?
खैर... चलो पता लगाते हैं!
मैंने एनपीएम , यार्न और पीएनपीएम की उनकी "गति" के संदर्भ में तुलना करने का निर्णय लिया...
आपको नीचे 3 उपाय दिखाई देंगे:
बिना किसी कैश के लॉक फ़ाइल उत्पन्न करें.
किसी भी कैश के बिना मौजूदा लॉक फ़ाइलों से निर्भरताएं स्थापित करें।
वैश्विक कैश के साथ मौजूदा लॉक फ़ाइलों से निर्भरताएँ स्थापित करें।
कैश दो प्रकार के होते हैं:
वैश्विक।
आमतौर पर उपयोगकर्ता की होम निर्देशिका (fe, ~/.yarn/berry/cache
) में संग्रहीत किया जाता है।
स्थानीय।
प्रोजेक्ट निर्देशिका (fe, <project-dir>/.yarn
) में संग्रहीत.
जबकि मेरे अनुभव में #2 और #3 सबसे आम उपयोग के मामले हैं, मैंने सिर्फ मामले में #1 भी लिया (हालांकि यह एक बहुत ही दुर्लभ मामला है)।
मैंने बेंचमार्क के लिए उदाहरण के रूप में create-react-app से एक नमूना प्रोजेक्ट का उपयोग किया।
यह Node.js इकोसिस्टम के लिए एक डिफ़ॉल्ट पैकेज मैनेजर है - और क्या कहें? यह इंस्टॉलेशन पैकेज के साथ आता है, इसलिए यह मूल रूप से उपयोग के लिए तैयार है जब आप अपनी मशीन पर Node.js इंस्टॉल करते हैं (या किसी भी CI प्रदाता में यदि आपने Node.js को वहां सेट किया है)।
मेरे विचार में यह एक बहुत बड़ी "सुविधा" है - आपको इसे अलग से स्थापित करने की आवश्यकता नहीं है!
इसमें कुछ भी खास नहीं है - यह बस... काम करता है! और मैंने पिछले कई सालों में कोई बड़ी बग नहीं देखी है - यह काफी स्थिर लगता है और काम पूरा कर देता है।
एनपीएम की वे विशेषताएं जो मैंने अब तक उपयोग की हैं:
npm आपके प्रोजेक्ट रूट के node_modules
फ़ोल्डर में निर्भरताएँ संग्रहीत करता है। बहुत सरल है।
ℹ️ package-lock.json
सूचीबद्ध पैकेजों के लिए रजिस्ट्री के बारे में जानकारी संग्रहीत करता है - यह बहुत उपयोगी है यदि आपके पास एक ही दायरे से पैकेज हैं, यानी @example-company
विभिन्न रजिस्ट्री में (उदाहरण के लिए - npm और GitHub पैकेज ):
अब, आइए देखें कि यह इंस्टॉलेशन स्पीड के मामले में कैसा प्रदर्शन करता है...
इसमेंpackage-lock.json
उत्पन्न करना और बिना किसी कैश के निर्भरताएं स्थापित करना।
प्रयुक्त आदेश:
npm i
इसमेंpackage-lock.json
से बिना किसी कैश के निर्भरताएं स्थापित करना।
प्रयुक्त आदेश:
npm ci
इसमेंpackage-lock.json
से निर्भरताएं स्थापित करना।
प्रयुक्त आदेश:
npm ci
मैं एक बार में संपूर्ण कार्यक्षेत्र बनाने और उसके लिए तथा विशिष्ट परियोजनाओं के लिए अलग से निर्भरताओं का प्रबंधन करने में सक्षम था।
दूसरे शब्दों में - यह बिना किसी बग/समस्या के काम पूरा कर देता है, और आधिकारिक दस्तावेज बहुत सरल है।
कार्यक्षेत्र सुविधाएँ जिनका मैंने अब तक उपयोग किया है:
ईमानदारी से कहूँ तो, मैंने यार्न की कुछ विशेषताओं को ज़्यादा नहीं आजमाया है। मेरा मतलब है, मैंने कुछ प्रोजेक्ट पर काम करते समय "निर्भरता स्थापित करने" के मामले में इसका बहुत उपयोग किया है, और बस इतना ही।
यार्न Node.js इंस्टॉलर के साथ नहीं आता है, इसलिए आपको इसे अलग से इंस्टॉल करना होगा। इसका मतलब है कि आपके CI पाइपलाइन में एक अतिरिक्त चरण होगा - आपको अपनी परियोजना निर्भरताएँ इंस्टॉल करने से पहले यार्न को सेट करना होगा।
निर्भरता स्थापित करने के लिए यार्न के दो तरीके हैं:
“ शून्य इंस्टॉल ” (डिफ़ॉल्ट) - .yarn
फ़ोल्डर बनाता है और yarn.lock
और .pnp.cjs
फ़ाइलों में पैकेजों को सूचीबद्ध करता है।
एक नियमित - npm के समान, निर्भरता को node_modules
में संग्रहीत करता है और उन्हें yarn.lock
फ़ाइल में सूचीबद्ध करता है।
ℹ️ यार्न लॉक फ़ाइलें सभी सूचीबद्ध पैकेजों के लिए रजिस्ट्री के बारे में जानकारी संग्रहीत करती हैं केवल तभी जब आप पुराने (नियमित) स्थापना दृष्टिकोण का उपयोग करते हैं।
⚠️ ध्यान रखें कि " शून्य इंस्टॉल " स्थानीय कैश में पैकेज संग्रहीत करता है और आपकी लॉक फ़ाइलों के लिंक प्रदान करता है:
यह आपके लिए महत्वपूर्ण हो सकता है यदि आपके पास एक Dockerfile या CI पाइपलाइन है जहां आप एक स्वच्छ वातावरण में निर्भरताएं स्थापित करते हैं और फिर इसे दूसरे में ले जाना चाहते हैं (आपको .yarn
फ़ोल्डर और स्थानीय कैश दोनों की प्रतिलिपि बनानी होगी)।
चूंकि अब यार्न के लिए डिफ़ॉल्ट दृष्टिकोण " शून्य इंस्टॉल " है और पुराने दृष्टिकोण की तुलना में इसका प्रदर्शन बेहतर है - हम केवल इसी दृष्टिकोण के साथ बेंचमार्क रिकॉर्ड करने जा रहे हैं।
इसमेंyarn.lock
फ़ाइल उत्पन्न करना और कैश के बिना निर्भरताएँ स्थापित करना।
प्रयुक्त आदेश:
yarn install
इसमें
प्रयुक्त आदेश:
yarn install --frozen-lockfile
इसमें
प्रयुक्त आदेश:
yarn install --frozen-lockfile
मैं एक कार्यक्षेत्र बनाने और सभी परियोजनाओं के लिए एक साथ तथा विशिष्ट परियोजनाओं के लिए अलग से निर्भरताओं का प्रबंधन करने में सक्षम था।
कार्यक्षेत्र सुविधाएँ जिनका मैंने अब तक उपयोग किया है:
दस्तावेज़ीकरण तो ठीक है, लेकिन कमांड नाम और फ़्लैग कुछ हद तक भ्रामक हैं।
उदाहरण के लिए, मुझे रूट ( . ) और नेस्टेड 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 install
इसमेंpnpm-lock.yaml
से निर्भरताएं स्थापित करना।
प्रयुक्त आदेश:
pnpm i --frozen-lockfile
इसमेंpnpm-lock.yaml
से निर्भरताएं स्थापित करना।
प्रयुक्त आदेश:
pnpm i --frozen-lockfile
अब, यहीं से चीजें वास्तव में दिलचस्प हो जाती हैं...
pnpm में बहुत सारे कॉन्फ़िगरेशन विकल्प हैं, लेकिन कुछ मुख्य कार्यक्षमताएं काम नहीं करतीं!
आइये उन कुछ त्रुटियों की समीक्षा करें जिनका मुझे सामना करना पड़ा:
केवल विशिष्ट परियोजनाओं के लिए निर्भरताएं स्थापित करने में सक्षम होना महत्वपूर्ण है - यह मोनोरेपो के लिए काफी उपयोगी है जब आप कार्यक्षेत्र के भीतर विशिष्ट परियोजनाओं से संबंधित पाइपलाइन बनाते हैं।
यानी, कल्पना करें कि आपके कार्यस्थल में यह है:
ये सभी अलग-अलग एनपीएम परियोजनाएं हैं, लेकिन वे एक ही रेपो का हिस्सा हैं ☝️
अब, आप केवल एंड-टू-एंड टेस्ट चलाने के लिए पाइपलाइन चाहते हैं। तो, आपको केवल एंड-टू-एंड टेस्ट निर्भरता की आवश्यकता है, है ना?
खैर, आप ऐसा नहीं कर पाएंगे - pnpm आपको संपूर्ण कार्यक्षेत्र के लिए निर्भरताएं स्थापित करने के लिए बाध्य कर रहा है!
pnpm install --filter <project-name>
केवल चयनित परियोजनाओं के लिए निर्भरताएं स्थापित करनी थी, लेकिन यह काम नहीं करता है।
यह एक साल पुराना बग है और इसे हाल ही में एक गैर-कार्यशील फिक्स के साथ बंद कर दिया गया है।
जब आप pnpm install
चलाते हैं तो pnpm डिफ़ॉल्ट रूप से संपूर्ण कार्यक्षेत्र (सभी प्रोजेक्ट) के लिए निर्भरताएँ स्थापित करता है
यदि आप अपने कार्यस्थान रूट में .npmrc
में recursive-install=false
सेट करते हैं तो आप इस व्यवहार को वैकल्पिक कर सकते हैं।
लेकिन इसमें एक और बग शामिल है जो लगभग 2 साल पुराना है ।
pnpm डिफ़ॉल्ट रूप से निर्भरता सूची को एकल लॉक फ़ाइल में संग्रहीत करता है ( npm और यार्न के समान)।
यदि आप अपने वर्कस्पेस रूट में .npmrc
में shared-workspace-lockfile=false
सेट करते हैं, तो आप इस व्यवहार को वैकल्पिक भी कर सकते हैं।
इससे हमें वर्कस्पेस सुविधा को बनाए रखने और किसी विशिष्ट परियोजना के लिए निर्भरताएं स्थापित करने के लिए --ignore-workspace
ध्वज का उपयोग करने की अनुमति मिल जाएगी।
वैसे, यह सेटिंग कुछ और समस्याएं भी उत्पन्न करती है:
eslint
और tsc --noEmit
मेरे GitHub Actions पाइपलाइनों में "JavaScript Heap Out of Memory" त्रुटि फेंकते हैं।
कुछ निर्भरताएँ वैश्विक कैश में संग्रहीत हैं और 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 Node.js इंस्टॉलर के साथ नहीं आता है, फिर भी इसे कोरपैक या मौजूदा एक्शन के साथ CI पाइपलाइनों में सेट करना आसान है।
मैं npm को प्राथमिकता देता हूं, क्योंकि:
package-lock.json
में संग्रहीत करता है ताकि आप विभिन्न रजिस्ट्री से एकल स्कोप के साथ निर्भरताएं स्थापित कर सकें।
ये फायदे उस गति और डिस्क स्थान के सेकंड से अधिक हैं जो मैं यार्न या पीएनपीएम के साथ बचा सकता था।
पैकेज मैनेजर चुनने के लिए आपके मानदंड क्या हैं? संकोच न करें, और नीचे टिप्पणी अनुभाग में मुझे अपने विचार बताएं! 👇😊