gzip की मदद से नेटवर्क पेलोड कम करें और कंप्रेस करें

यह कोडलैब इस बात का पता लगाता है कि नीचे दिए गए ऐप्लिकेशन के JavaScript बंडल को छोटा करने और कंप्रेस करने, दोनों ही ऐप्लिकेशन के अनुरोध आकार को कम करके पेज की परफ़ॉर्मेंस को कैसे बेहतर बनाते हैं.

ऐप्लिकेशन का स्क्रीनशॉट

दूरी मापें

ऑप्टिमाइज़ेशन जोड़ने से पहले, ऐप्लिकेशन की मौजूदा स्थिति का विश्लेषण कर लेना हमेशा एक अच्छा तरीका होता है.

  • साइट की झलक देखने के लिए, ऐप्लिकेशन देखें दबाएं. इसके बाद, फ़ुलस्क्रीन फ़ुलस्क्रीन दबाएं.

इस ऐप्लिकेशन की मदद से, अपनी पसंदीदा बिल्ली के बच्चे को वोट दिया जा सकता है. यह ऐप्लिकेशन "इस्तेमाल नहीं किया गया कोड हटाएं" कोडलैब में भी शामिल था. 🐈

अब देखें कि यह ऐप्लिकेशन कितना बड़ा है:

  1. DevTools खोलने के लिए, `Control+Shift+J` (या Mac पर `Command+Option+J`) दबाएं.
  2. नेटवर्क टैब पर क्लिक करें.
  3. कैश मेमोरी बंद करें चेकबॉक्स चुनें.
  4. ऐप्लिकेशन को फिर से लोड करें.

नेटवर्क पैनल में मूल बंडल का साइज़

हालांकि, इस बंडल के साइज़ को छोटा करने के लिए, "इस्तेमाल नहीं किया गया कोड हटाएं" कोडलैब में काफ़ी बदलाव किए गए हैं, लेकिन 225 केबी का साइज़ अब भी काफ़ी बड़ा है.

छोटा करना

कोड के नीचे दिए गए ब्लॉक पर गौर करें.

function soNice() {
  let counter = 0;

  while (counter < 100) {
    console.log('nice');
    counter++;
  }
}

अगर इस फ़ंक्शन को खुद की फ़ाइल में सेव किया जाता है, तो फ़ाइल का साइज़ करीब 112 B (बाइट) होगा.

अगर सभी खाली सफ़ेद जगह को हटा दिया जाता है, तो मिलने वाला कोड ऐसा दिखेगा:

function soNice(){let counter=0;while(counter<100){console.log("nice");counter++;}}

अब फ़ाइल का साइज़ करीब 83 B हो जाएगा. अगर वैरिएबल के नाम की लंबाई को कम करके और कुछ एक्सप्रेशन में बदलाव करके इसे और ज़्यादा नुकसान पहुंचाया जाता है, तो आखिरी कोड कुछ ऐसा दिख सकता है:

function soNice(){for(let i=0;i<100;)console.log("nice"),i++}

फ़ाइल का साइज़ अब 62 B हो जाएगा.

हर चरण के साथ, कोड को पढ़ना मुश्किल होता जा रहा है. हालांकि, ब्राउज़र का JavaScript इंजन इनमें से हर एक को एक ही तरीके से समझता है. इस तरह से कोड को अस्पष्ट बनाने से फ़ाइल का आकार छोटा हो सकता है. 112 B वाकई में शुरुआत करने के लिए ज़्यादा नहीं था, लेकिन फिर भी साइज़ में 50% की कमी आई थी!

इस ऐप्लिकेशन में, webpack के वर्शन 4 का इस्तेमाल मॉड्यूल बंडलर के तौर पर किया जाता है. इसके खास वर्शन को package.json में देखा जा सकता है.

"devDependencies": {
  //...
  "webpack": "^4.16.4",
  //...
}

वर्शन 4, प्रोडक्शन मोड के दौरान बंडल को डिफ़ॉल्ट रूप से छोटा कर देता है. यह Terser के लिए, TerserWebpackPlugin प्लगिन का इस्तेमाल करता है. Treser एक लोकप्रिय टूल है, जिसका इस्तेमाल JavaScript कोड को कंप्रेस करने के लिए किया जाता है.

यह जानने के लिए कि छोटा किया गया कोड कैसा दिखता है, DevTools नेटवर्क पैनल में रहते हुए main.bundle.js पर क्लिक करें. अब जवाब टैब पर क्लिक करें.

कम से कम जवाब

जवाब के मुख्य हिस्से में, यह कोड आखिरी रूप में दिखता है, जिसे छोटा किया गया है, और अलग किया गया है. यह जानने के लिए कि अगर बंडल को छोटा नहीं किया गया, तो वह कितना बड़ा हो सकता था, webpack.config.js खोलें और mode कॉन्फ़िगरेशन को अपडेट करें.

module.exports = {
  mode: 'production',
  mode: 'none',
  //...

ऐप्लिकेशन को फिर से लोड करें और DevTools Network पैनल के ज़रिए बंडल के साइज़ को फिर से देखें

बंडल का साइज़ 767 केबी

यह बहुत बड़ा अंतर है! 😅

जारी रखने से पहले, यहां किए गए बदलावों को पहले जैसा करना न भूलें.

module.exports = {
  mode: 'production',
  mode: 'none',
  //...

अपने ऐप्लिकेशन में कोड को छोटा करने की प्रोसेस शामिल करना, उन टूल पर निर्भर करता है जिनका इस्तेमाल आप करते हैं:

  • अगर webpack v4 या इससे नए वर्शन का इस्तेमाल किया जाता है, तो आपको कुछ और करने की ज़रूरत नहीं है. ऐसा इसलिए, क्योंकि प्रोडक्शन मोड में कोड को डिफ़ॉल्ट रूप से छोटा किया जाता है. 👍
  • अगर वेबपैक के पुराने वर्शन का इस्तेमाल किया जा रहा है, तो वेबपैक बनाने की प्रोसेस में TerserWebpackPlugin को इंस्टॉल करें और उसे शामिल करें. दस्तावेज़ में इस बारे में विस्तार से बताया गया है.
  • छोटा करने से जुड़े दूसरे प्लग इन भी मौजूद हैं और इनके बजाय BabelMinifyWebpackPlugin और ClosureCompilerPlugin जैसे प्लगिन का इस्तेमाल किया जा सकता है.
  • अगर किसी मॉड्यूल बंडलर का इस्तेमाल बिलकुल नहीं किया जा रहा है, तो सीएलआई टूल के तौर पर Terser का इस्तेमाल करें या इसे सीधे डिपेंडेंसी के तौर पर शामिल करें.

संपीड़न

हालांकि, कभी-कभी "कम्प्रेशन" शब्द का इस्तेमाल यह बताने के लिए किया जाता है कि छोटा करने की प्रोसेस के दौरान कोड को कैसे कम किया जाता है. हालांकि, इसे लिटरल तौर पर कंप्रेस नहीं किया जाता.

कंप्रेशन आम तौर पर, उस कोड को कहा जाता है जिसमें डेटा कंप्रेशन के एल्गोरिदम का इस्तेमाल करके बदलाव किया गया है. छोटा करने की इस प्रोसेस से, कोड को पूरी तरह से मान्य कोड मिलता है, जबकि इस्तेमाल करने से पहले कंप्रेस किए गए कोड को डिकंप्रेस किया गया होना चाहिए.

हर एचटीटीपी अनुरोध और जवाब के साथ, ब्राउज़र और वेब सर्वर, फ़ेच किए जाने या पाए गए ऐसेट के बारे में ज़्यादा जानकारी शामिल करने के लिए headers जोड़ सकते हैं. इसे DevTools नेटवर्क पैनल के Headers टैब में देखा जा सकता है, जहां तीन तरह के विकल्प दिखते हैं:

  • General, ऐसे सामान्य हेडर दिखाता है जो अनुरोध-जवाब के सभी इंटरैक्शन के लिए काम के होते हैं.
  • रिस्पॉन्स हेडर, सर्वर से मिलने वाले असल रिस्पॉन्स के लिए खास तौर पर बनाए गए हेडर की सूची दिखाता है.
  • अनुरोध हेडर, क्लाइंट के अनुरोध से जुड़े हेडर की सूची दिखाता है.

Request Headers में accept-encoding हेडर पर एक नज़र डालें.

एन्कोडिंग हेडर स्वीकार करें

ब्राउज़र, accept-encoding का इस्तेमाल यह तय करने के लिए करता है कि कॉन्टेंट को किस फ़ॉर्मैट या कंप्रेशन एल्गोरिदम पर लागू किया जा सकता है. टेक्स्ट-कंप्रेशन वाले कई एल्गोरिदम मौजूद हैं, लेकिन एचटीटीपी नेटवर्क अनुरोधों के कंप्रेशन (और डिकंप्रेशन) के लिए, यहां सिर्फ़ तीन एल्गोरिदम काम करते हैं:

  • Gzip (gzip): सर्वर और क्लाइंट इंटरैक्शन के लिए सबसे ज़्यादा इस्तेमाल किया जाने वाला कंप्रेशन फ़ॉर्मैट. यह Deflate Algorithm के आधार पर बनता है और सभी मौजूदा ब्राउज़र पर काम करता है.
  • कम करें (deflate): आम तौर पर इस्तेमाल नहीं किया जाता.
  • ब्रोटली (br): यह एक नया कंप्रेशन एल्गोरिदम है, जिसका मकसद कंप्रेशन रेशियो को और बेहतर बनाना है. इससे पेज तेज़ी से लोड हो सकते हैं. यह ज़्यादातर ब्राउज़र के नए वर्शन में काम करती है.

इस ट्यूटोरियल में दिया गया सैंपल ऐप्लिकेशन, "इस्तेमाल नहीं किया गया कोड हटाएं" कोडलैब में पूरे किए गए ऐप्लिकेशन की तरह होता है. इसमें सिर्फ़ एक्सप्रेस का इस्तेमाल सर्वर फ़्रेमवर्क के तौर पर किया जाता है. अगले कुछ सेक्शन में, स्टैटिक और डाइनैमिक, दोनों कंप्रेशन के बारे में बताया गया है.

डाइनैमिक कंप्रेशन

डाइनैमिक कंप्रेशन में, ब्राउज़र के अनुरोध पर ऐसेट को तुरंत कंप्रेस किया जाता है.

फ़ायदे

  • एसेट के कंप्रेस किए गए वर्शन बनाने और अपडेट करने की ज़रूरत नहीं है.
  • तुरंत कंप्रेस करने की सुविधा, डाइनैमिक रूप से जनरेट होने वाले वेब पेजों के लिए कारगर साबित होती है.

नुकसान

  • बेहतर कंप्रेशन रेशियो पाने के लिए, फ़ाइलों को ज़्यादा लेवल पर कंप्रेस करने में ज़्यादा समय लगता है. इससे परफ़ॉर्मेंस पर असर पड़ सकता है, क्योंकि सर्वर से भेजे जाने से पहले उपयोगकर्ता, ऐसेट के कंप्रेस होने का इंतज़ार करता है.

नोड/एक्सप्रेस के साथ डाइनैमिक कंप्रेशन

server.js फ़ाइल की मदद से, ऐप्लिकेशन को होस्ट करने वाला नोड सर्वर सेट अप किया जाता है.

const express = require('express');

const app = express();

app.use(express.static('public'));

const listener = app.listen(process.env.PORT, function() {
  console.log('Your app is listening on port ' + listener.address().port);
});

फ़िलहाल, ये सभी काम express को इंपोर्ट करते हैं और express.static मिडलवेयर का इस्तेमाल करके public/ डायरेक्ट्री में सभी स्टैटिक एचटीएमएल, JS, और सीएसएस फ़ाइलों को लोड करते हैं. इन फ़ाइलों को हर बिल्ड के साथ webpack के ज़रिए बनाया जाता है.

यह पक्का करने के लिए कि हर बार अनुरोध किए जाने पर सभी ऐसेट को कंप्रेस किया जाए, कंप्रेशन मिडलवेयर लाइब्रेरी का इस्तेमाल किया जा सकता है. इसे package.json में devDependency के तौर पर जोड़कर शुरू करें:

"devDependencies": {
  //...
  "compression": "^1.7.3"
},

और इसे सर्वर फ़ाइल, server.js में इंपोर्ट करें:

const express = require('express');
const compression = require('compression');

express.static को माउंट करने से पहले, इसे मिडलवेयर के तौर पर जोड़ें:

//...

const app = express();

app.use(compression());

app.use(express.static('public'));

//...

अब ऐप्लिकेशन को फिर से लोड करें और नेटवर्क पैनल में बंडल के साइज़ को देखें.

डाइनैमिक कंप्रेशन के साथ बंडल का साइज़

225 केबी से 61.6 केबी तक! अब Response Headers में, content-encoding हेडर दिखाता है कि सर्वर gzip की कोड में बदली गई फ़ाइल भेज रहा है.

कॉन्टेंट एन्कोडिंग हेडर

स्टैटिक कंप्रेशन

स्टैटिक कंप्रेशन के पीछे का आइडिया यह है कि समय से पहले, ऐसेट को कंप्रेस करके सेव किया जाए.

फ़ायदे

  • उच्च संपीड़न स्तर के कारण लेटेंसी अब चिंता का विषय नहीं है. फ़ाइलों को कंप्रेस करने के लिए तुरंत कुछ करने की ज़रूरत नहीं होती, क्योंकि अब उन्हें सीधे फ़ेच किया जा सकता है.

नुकसान

  • ऐसेट को हर बिल्ड के साथ कंप्रेस करना ज़रूरी है. ज़्यादा कंप्रेशन लेवल का इस्तेमाल करने पर, बिल्ड टाइम काफ़ी बढ़ सकता है.

नोड/एक्सप्रेस और वेबपैक के साथ स्टैटिक कंप्रेशन

स्टैटिक कंप्रेशन में, समय से पहले फ़ाइलों को कंप्रेस करना शामिल होता है. इसलिए, बिल्ड चरण के हिस्से के तौर पर Webpack की सेटिंग में बदलाव करके, ऐसेट को कंप्रेस किया जा सकता है. इसके लिए, CompressionPlugin का इस्तेमाल किया जा सकता है.

इसे package.json में devDependency के तौर पर जोड़कर शुरू करें:

"devDependencies": {
  //...
  "compression-webpack-plugin": "^1.1.11"
},

किसी भी दूसरे Webpack प्लगिन की तरह, इसे कॉन्फ़िगरेशन फ़ाइल में इंपोर्ट करें, webpack.config.js:

const path = require("path");

//...

const CompressionPlugin = require("compression-webpack-plugin");

साथ ही, इसे plugins कलेक्शन में शामिल करें:

module.exports = {
  //...
  plugins: [
    //...
    new CompressionPlugin()
  ]
}

डिफ़ॉल्ट रूप से, प्लगिन gzip का इस्तेमाल करके बिल्ड फ़ाइलों को कंप्रेस करता है. अलग एल्गोरिदम का इस्तेमाल करने या कुछ फ़ाइलों को शामिल करने या बाहर रखने के विकल्प जोड़ने का तरीका जानने के लिए, दस्तावेज़ देखें.

जब ऐप्लिकेशन फिर से लोड और फिर से बनता है, तो अब मुख्य बंडल का कंप्रेस किया गया वर्शन बन जाता है. नोड सर्वर से दी जाने वाली आखिरी public/ डायरेक्ट्री में क्या-क्या है, यह देखने के लिए Glitch Console खोलें.

  • टूल बटन पर क्लिक करें.
  • कंसोल बटन पर क्लिक करें.
  • कंसोल में, public डायरेक्ट्री में बदलने और इसकी सभी फ़ाइलें देखने के लिए, इन निर्देशों का पालन करें:
cd public
ls

सार्वजनिक डायरेक्ट्री में आउटपुट वाली आखिरी फ़ाइलें

बंडल का gzip किया गया वर्शन, main.bundle.js.gz अब यहां भी सेव किया गया है. CompressionPlugin, डिफ़ॉल्ट रूप से index.html को भी कंप्रेस कर देता है.

इसके बाद यह ज़रूरी है कि जब भी उनके मूल JS वर्शन का अनुरोध किया जाए, तब सर्वर को ये gzip की गई फ़ाइलें भेजने के लिए कहें. express.static के साथ फ़ाइलें दिखाने से पहले, server.js में एक नया रूट तय करके ऐसा किया जा सकता है.

const express = require('express');
const app = express();

app.get('*.js', (req, res, next) => {
  req.url = req.url + '.gz';
  res.set('Content-Encoding', 'gzip');
  next();
});

app.use(express.static('public'));

//...

app.get का इस्तेमाल, सर्वर को यह बताने के लिए किया जाता है कि किसी खास एंडपॉइंट के लिए जीईटी अनुरोध का जवाब कैसे दिया जाए. इसके बाद, कॉलबैक फ़ंक्शन का इस्तेमाल यह तय करने के लिए किया जाता है कि इस अनुरोध को कैसे मैनेज करना है. रास्ता इस तरह से काम करता है:

  • '*.js' को पहला आर्ग्युमेंट बनाने का मतलब है कि यह हर उस एंडपॉइंट के लिए काम करता है जिसे JS फ़ाइल फ़ेच करने के लिए फ़ायर किया जाता है.
  • कॉलबैक में, .gz, अनुरोध के यूआरएल से जुड़ा होता है और Content-Encoding रिस्पॉन्स हेडर, gzip पर सेट होता है.
  • आखिर में, next() यह पक्का करता है कि क्रम, आगे होने वाले किसी भी कॉलबैक पर जारी रहे.

ऐप्लिकेशन के फिर से लोड होने पर, Network पैनल को एक बार फिर से देखें.

स्टैटिक कंप्रेशन के साथ बंडल का साइज़ छोटा करने की सुविधा

पहले की तरह ही, बंडल के साइज़ में भारी कमी!

नतीजा

इस कोडलैब में, सोर्स कोड को छोटा करने और कंप्रेस करने की प्रोसेस बताई गई है. आज-कल उपलब्ध कई टूल में, ये दोनों तकनीकें डिफ़ॉल्ट हो रही हैं. इसलिए, यह पता लगाना ज़रूरी है कि क्या आपका टूलचेन पहले से इन टूल के साथ काम करता है या आपको दोनों प्रोसेस को खुद ही लागू करना चाहिए.