इस कोडलैब में, इस्तेमाल न की गई और ज़रूरत न पड़ने वाली डिपेंडेंसी को हटाकर, नीचे दिए गए ऐप्लिकेशन की परफ़ॉर्मेंस को बेहतर बनाएं.
मापें
ऑप्टिमाइज़ेशन जोड़ने से पहले, यह मेज़र करना हमेशा अच्छा होता है कि वेबसाइट कैसा परफ़ॉर्म करती है.
- साइट की झलक देखने के लिए, ऐप्लिकेशन देखें दबाएं. इसके बाद, फ़ुलस्क्रीन दबाएं.
अपनी पसंदीदा बिल्ली के बच्चे पर क्लिक करें! इस ऐप्लिकेशन में Firebase के रीयल टाइम डेटाबेस का इस्तेमाल किया जाता है. इसलिए, स्कोर रीयल-टाइम में अपडेट होता है और ऐप्लिकेशन का इस्तेमाल करने वाले हर व्यक्ति के साथ सिंक होता है. 🐈
- DevTools खोलने के लिए, `Control+Shift+J` दबाएं. Mac पर, `Command+Option+J` दबाएं.
- नेटवर्क टैब पर क्लिक करें.
- कैश मेमोरी की सुविधा बंद करें चेकबॉक्स को चुनें.
- ऐप्लिकेशन को फिर से लोड करें.
इस आसान ऐप्लिकेशन को लोड करने के लिए, करीब 1 एमबी का JavaScript भेजा जा रहा है!
DevTools में प्रोजेक्ट से जुड़ी चेतावनियां देखें.
- कंसोल टैब पर क्लिक करें.
- पक्का करें कि
Filter
इनपुट के बगल में मौजूद लेवल ड्रॉपडाउन में,Warnings
चालू हो.
- दिखाई गई चेतावनी देखें.
इस ऐप्लिकेशन में इस्तेमाल की जाने वाली लाइब्रेरी में से एक Firebase, डेवलपर को चेतावनी देकर एक अच्छा काम कर रहा है. इससे डेवलपर को पता चलता है कि पूरे पैकेज को इंपोर्ट करने के बजाय, सिर्फ़ इस्तेमाल किए जाने वाले कॉम्पोनेंट इंपोर्ट करें. दूसरे शब्दों में, इस ऐप्लिकेशन में ऐसी लाइब्रेरी मौजूद हैं जिनका इस्तेमाल नहीं किया जाता. इन लाइब्रेरी को हटाने पर, ऐप्लिकेशन तेज़ी से लोड होगा.
ऐसे मामले भी हो सकते हैं जिनमें किसी खास लाइब्रेरी का इस्तेमाल किया गया हो, लेकिन वहां कोई आसान विकल्प उपलब्ध हो. ग़ैर-ज़रूरी लाइब्रेरी हटाने के बारे में इस ट्यूटोरियल में आगे बताया गया है.
बंडल का विश्लेषण करना
ऐप्लिकेशन में दो मुख्य डिपेंडेंसी हैं:
- Firebase: यह एक ऐसा प्लैटफ़ॉर्म है जो iOS, Android या वेब ऐप्लिकेशन के लिए कई काम की सेवाएं उपलब्ध कराता है. यहां रीयलटाइम डेटाबेस का इस्तेमाल, हर बिल्ली के बच्चे की जानकारी को रीयल टाइम में सेव और सिंक करने के लिए किया जाता है.
- Moment.js: यह एक यूटिलिटी लाइब्रेरी है, जिसकी मदद से JavaScript में तारीखों को आसानी से मैनेज किया जा सकता है. हर बिल्ली के बच्चे के जन्म की तारीख, Firebase डेटाबेस में सेव की जाती है. साथ ही,
moment
का इस्तेमाल उसकी उम्र को हफ़्तों में कैलकुलेट करने के लिए किया जाता है.
सिर्फ़ दो डिपेंडेंसी, बंडल के साइज़ को करीब 1 एमबी कैसे बढ़ा सकती हैं? इसकी एक वजह यह है कि किसी भी डिपेंडेंसी की अपनी डिपेंडेंसी हो सकती हैं. इसलिए, अगर डिपेंडेंसी "ट्री" की हर गहराई/शाखा को ध्यान में रखा जाए, तो डिपेंडेंसी की संख्या दो से ज़्यादा हो सकती है. अगर कई डिपेंडेंसी शामिल की जाती हैं, तो किसी ऐप्लिकेशन का साइज़ तुलनात्मक रूप से तेज़ी से बड़ा हो सकता है.
बंडलर का विश्लेषण करके, यह बेहतर तरीके से समझें कि क्या हो रहा है. कम्यूनिटी के बनाए गए कई अलग-अलग टूल की मदद से, ऐसा किया जा सकता है. जैसे, webpack-bundle-analyzer
.
इस टूल का पैकेज, ऐप्लिकेशन में पहले से ही devDependency
के तौर पर शामिल है.
"devDependencies": {
//...
"webpack-bundle-analyzer": "^2.13.1"
},
इसका मतलब है कि इसका इस्तेमाल सीधे तौर पर webpack कॉन्फ़िगरेशन फ़ाइल में किया जा सकता है.
इसे webpack.config.js
की शुरुआत में इंपोर्ट करें:
const path = require("path");
//...
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
.BundleAnalyzerPlugin;
अब इसे plugins
कलेक्शन में, फ़ाइल के आखिर में प्लग इन के तौर पर जोड़ें:
module.exports = {
//...
plugins: [
//...
new BundleAnalyzerPlugin()
]
};
ऐप्लिकेशन फिर से लोड होने पर, आपको ऐप्लिकेशन के बजाय पूरे बंडल का विज़ुअलाइज़ेशन दिखेगा.
यह बिल्ली के बच्चों 🐱 को देखने जितना प्यारा नहीं है, लेकिन फिर भी यह काफ़ी मददगार है. किसी भी पैकेज पर कर्सर घुमाने पर, उसका साइज़ तीन अलग-अलग तरीकों से दिखता है:
आंकड़े का साइज़ | छोटा किए जाने या कंप्रेस किए जाने से पहले का साइज़. |
---|---|
पार्स किया गया साइज़ | बंडल को कंपाइल करने के बाद, उसमें मौजूद असल पैकेज का साइज़. इस ऐप्लिकेशन में इस्तेमाल किए गए webpack के वर्शन 4 में, संकलित की गई फ़ाइलों का साइज़ अपने-आप कम हो जाता है. इसलिए, यह आंकड़े के साइज़ से छोटा होता है. |
Gzip किया गया साइज़ | gzip एन्कोडिंग की मदद से कंप्रेस किए जाने के बाद, पैकेज का साइज़. इस विषय के बारे में, एक अलग गाइड में बताया गया है. |
webpack-bundle-analyzer टूल की मदद से, उन पैकेज की पहचान करना आसान हो जाता है जिन्हें इस्तेमाल नहीं किया गया है या जिनकी ज़रूरत नहीं है. ये पैकेज, बंडल का ज़्यादातर हिस्सा बनाते हैं.
इस्तेमाल नहीं किए जा रहे पैकेज हटाना
विज़ुअलाइज़ेशन से पता चलता है कि firebase
पैकेज में सिर्फ़ एक डाटाबेस के अलावा बहुत कुछ और भी है. इसमें अन्य पैकेज भी शामिल हैं, जैसे:
firestore
auth
storage
messaging
functions
ये सभी Firebase की बेहतरीन सेवाएं हैं. ज़्यादा जानने के लिए, दस्तावेज़ देखें. हालांकि, इनमें से किसी भी सेवा का इस्तेमाल ऐप्लिकेशन में नहीं किया जा रहा है. इसलिए, इन्हें इंपोर्ट करने की कोई ज़रूरत नहीं है.
ऐप्लिकेशन को फिर से देखने के लिए, webpack.config.js
में किए गए बदलावों को पहले जैसा करें:
- प्लग इन की सूची से
BundleAnalyzerPlugin
को हटाएं:
plugins: [
//...
new BundleAnalyzerPlugin()
];
- अब फ़ाइल में सबसे ऊपर मौजूद, इस्तेमाल न किए गए इंपोर्ट को हटाएं:
const path = require("path");
//...
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
अब ऐप्लिकेशन सामान्य रूप से लोड होना चाहिए. Firebase इंपोर्ट को अपडेट करने के लिए, src/index.js
में बदलाव करें.
import firebase from 'firebase';
import firebase from 'firebase/app';
import 'firebase/database';
अब जब ऐप्लिकेशन फिर से लोड होगा, तो DevTools की चेतावनी नहीं दिखेगी. DevTools के नेटवर्क पैनल को खोलने पर भी, बंडल के साइज़ में काफ़ी कमी दिखती है:
बंडल का आधा से ज़्यादा हिस्सा हटा दिया गया. Firebase कई अलग-अलग सेवाएं उपलब्ध कराता है. साथ ही, डेवलपर को सिर्फ़ उन सेवाओं को शामिल करने का विकल्प देता है जिनकी ज़रूरत होती है. इस ऐप्लिकेशन में, पूरे डेटा को सेव और सिंक करने के लिए सिर्फ़ firebase/database
का इस्तेमाल किया गया था. firebase/app
इंपोर्ट, हर अलग-अलग सेवा के लिए एपीआई प्लैटफ़ॉर्म को सेट अप करता है. यह इंपोर्ट हमेशा ज़रूरी होता है.
lodash
जैसी कई अन्य लोकप्रिय लाइब्रेरी भी डेवलपर को अपने पैकेज के अलग-अलग हिस्सों को चुनिंदा तौर पर इंपोर्ट करने की अनुमति देती हैं. ज़्यादा काम किए बिना, किसी ऐप्लिकेशन में लाइब्रेरी इंपोर्ट को अपडेट करके, सिर्फ़ इस्तेमाल किए जा रहे लाइब्रेरी इंपोर्ट को शामिल किया जा सकता है. इससे परफ़ॉर्मेंस में काफ़ी सुधार हो सकता है.
बंडल का साइज़ काफ़ी कम हो गया है, लेकिन अब भी हमें और काम करना है! 😈
ज़रूरत न पड़ने वाले पैकेज हटाना
Firebase के मुकाबले, moment
लाइब्रेरी के कुछ हिस्सों को आसानी से इंपोर्ट नहीं किया जा सकता. हालांकि, शायद इसे पूरी तरह से हटाया जा सकता है?
हर प्यारी बिल्ली के जन्म की तारीख को Firebase डेटाबेस में, Unix फ़ॉर्मैट (मिलीसेकंड) में सेव किया जाता है.
यह किसी खास तारीख और समय का टाइमस्टैंप है. इसे 1 जनवरी, 1970 को 00:00 यूटीसी से बीते मिलीसेकंड की संख्या से दिखाया जाता है. अगर मौजूदा तारीख और समय का हिसाब एक ही फ़ॉर्मैट में लगाया जा सकता है, तो हर बिल्ली के बच्चे की उम्र हफ़्तों में जानने के लिए, एक छोटा फ़ंक्शन बनाया जा सकता है.
हमेशा की तरह, यहां दिए गए निर्देशों को कॉपी और चिपकाने की कोशिश न करें. src/index.js
में इंपोर्ट किए गए डेटा से moment
को हटाकर शुरू करें.
import firebase from 'firebase/app';
import 'firebase/database';
import * as moment from 'moment';
हमारे डेटाबेस में वैल्यू में हुए बदलावों को मैनेज करने के लिए, Firebase इवेंट लिसनर का इस्तेमाल किया जाता है:
favoritesRef.on("value", (snapshot) => { ... })
इसके ऊपर, किसी दी गई तारीख से हफ़्तों की संख्या का हिसाब लगाने के लिए, एक छोटा फ़ंक्शन जोड़ें:
const ageInWeeks = birthDate => {
const WEEK_IN_MILLISECONDS = 1000 * 60 * 60 * 24 * 7;
const diff = Math.abs((new Date).getTime() - birthDate);
return Math.floor(diff / WEEK_IN_MILLISECONDS);
}
इस फ़ंक्शन में, मौजूदा तारीख और समय (new Date).getTime()
और जन्म की तारीख (birthDate
आर्ग्युमेंट, पहले से ही मिलीसेकंड में है) के बीच के मिलीसेकंड के अंतर का हिसाब लगाया जाता है. इसके बाद, इस अंतर को एक हफ़्ते में मिलीसेकंड की संख्या से भाग दिया जाता है.
आखिर में, इस फ़ंक्शन का इस्तेमाल करके इवेंट लिसनर में moment
के सभी इंस्टेंस हटाए जा सकते हैं:
favoritesRef.on("value", (snapshot) => { const { kitties, favorites, names, birthDates } = snapshot.val(); favoritesScores = favorites; kittiesList.innerHTML = kitties.map((kittiePic, index) => {const birthday = moment(birthDates[index]);return ` <li> <img src=${kittiePic} onclick="favKittie(${index})"> <div class="extra"> <div class="details"> <p class="name">${names[index]}</p><p class="age">${moment().diff(birthday, 'weeks')} weeks old</p><p class="age">${ageInWeeks(birthDates[index])} weeks old</p> </div> <p class="score">${favorites[index]} ❤</p> </div> </li> `}) });
अब ऐप्लिकेशन को फिर से लोड करें और नेटवर्क पैनल पर एक बार फिर से नज़र डालें.
हमारे बंडल का साइज़, आधे से ज़्यादा कम हो गया!
नतीजा
इस कोडलैब की मदद से, आपको किसी खास बंडल का विश्लेषण करने का तरीका समझ आ जाएगा. साथ ही, यह भी समझ आ जाएगा कि इस्तेमाल न किए गए या ज़रूरत न पड़ने वाले पैकेज हटाना क्यों ज़रूरी है. इस तकनीक का इस्तेमाल करके किसी ऐप्लिकेशन को ऑप्टिमाइज़ करने से पहले, यह जानना ज़रूरी है कि बड़े ऐप्लिकेशन में यह काफ़ी मुश्किल हो सकता है.
इस्तेमाल न की गई लाइब्रेरी हटाने के लिए, यह पता लगाने की कोशिश करें कि किसी बंडल के किन हिस्सों का इस्तेमाल किया जा रहा है और किनका नहीं. अगर आपको कोई ऐसा पैकेज मिलता है जिसका इस्तेमाल कहीं नहीं किया जा रहा है, तो थोड़ा रुकें और देखें कि टॉप-लेवल की किन डिपेंडेंसी को इसकी ज़रूरत पड़ सकती है. इन दोनों को अलग करने का तरीका ढूंढें.
ज़रूरत न पड़ने वाली लाइब्रेरी हटाने के लिए, थोड़ी मुश्किल हो सकती है. अपनी टीम के साथ मिलकर काम करना ज़रूरी है. साथ ही, यह देखना भी ज़रूरी है कि कोडबेस के कुछ हिस्सों को आसान बनाया जा सकता है या नहीं. इस ऐप्लिकेशन में moment
को हटाने से ऐसा लग सकता है कि हर बार ऐसा करना सही होगा. हालांकि, अगर टाइम ज़ोन और अलग-अलग स्थानीय भाषाओं को मैनेज करना ज़रूरी हो, तो क्या होगा? इसके अलावा, अगर तारीख में ज़्यादा बदलाव किए गए हों, तो क्या होगा? तारीखों/समय में बदलाव करने और उन्हें पार्स करने के दौरान, चीज़ें बहुत मुश्किल हो सकती हैं. हालांकि, moment
और date-fns
जैसी लाइब्रेरी, इस काम को काफ़ी आसान बनाती हैं.
हर चीज़ में समझौता करना पड़ता है. इसलिए, यह तय करना ज़रूरी है कि तीसरे पक्ष की लाइब्रेरी पर भरोसा करने के बजाय, कस्टम समाधान को रोल आउट करना कितना मुश्किल और समयसाध्य है.