इस कोडलैब में, इस्तेमाल न की गई और ज़रूरत न पड़ने वाली डिपेंडेंसी हटाकर, नीचे दिए गए ऐप्लिकेशन की परफ़ॉर्मेंस को बेहतर बनाएं.
मापें
ऑप्टिमाइज़ेशन जोड़ने से पहले, यह मेज़र करना हमेशा अच्छा होता है कि वेबसाइट कैसा परफ़ॉर्म करती है.
- साइट की झलक देखने के लिए, ऐप्लिकेशन देखें दबाएं. इसके बाद, फ़ुलस्क्रीन दबाएं.
अपनी पसंदीदा बिल्ली के बच्चे पर क्लिक करें! इस ऐप्लिकेशन में Firebase के रीयल टाइम डेटाबेस का इस्तेमाल किया जाता है. इसलिए, स्कोर रीयल-टाइम में अपडेट होता है और ऐप्लिकेशन का इस्तेमाल करने वाले हर व्यक्ति के साथ सिंक होता है. 🐈
- DevTools खोलने के लिए, `Control+Shift+J` दबाएं. Mac पर, `Command+Option+J` दबाएं.
- नेटवर्क टैब पर क्लिक करें.
- कैश मेमोरी बंद करें चेकबॉक्स चुनें.
- ऐप्लिकेशन को फिर से लोड करें.
इस आसान ऐप्लिकेशन को लोड करने के लिए, करीब 1 एमबी का JavaScript भेजा जा रहा है!
DevTools में प्रोजेक्ट से जुड़ी चेतावनियां देखें.
- कंसोल टैब पर क्लिक करें.
- पक्का करें कि
Filter
इनपुट के बगल में मौजूद, लेवल ड्रॉपडाउन मेंWarnings
चालू हो.
- दिखाई गई चेतावनी देखें.
इस ऐप्लिकेशन में इस्तेमाल की जाने वाली लाइब्रेरी में से एक Firebase है. यह डेवलपर को चेतावनी देकर, उनके लिए एक अच्छा काम कर रहा है. इस चेतावनी से डेवलपर को पता चलता है कि 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
जैसी लाइब्रेरी, इस काम को काफ़ी आसान बनाती हैं.
हर चीज़ में समझौता करना पड़ता है. इसलिए, यह तय करना ज़रूरी है कि तीसरे पक्ष की लाइब्रेरी पर भरोसा करने के बजाय, कस्टम समाधान को रोल आउट करना कितना मुश्किल और समयसाध्य है.