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 प्लगिन का इस्तेमाल करता है. terser एक लोकप्रिय टूल है, जिसका इस्तेमाल JavaScript कोड को कंप्रेस करने के लिए किया जाता है.

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

कम से कम जवाब

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

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

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

बंडल का साइज़ 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): आम तौर पर इस्तेमाल नहीं किया जाता.
  • Bromli (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 को इंपोर्ट किया जाता है. साथ ही, public/ डायरेक्ट्री में सभी स्टैटिक एचटीएमएल, JS, और सीएसएस फ़ाइलों को लोड करने के लिए, express.static मिडलवेयर का इस्तेमाल किया जाता है. ये फ़ाइलें हर बिल्ड के साथ वेबपैक की मदद से बनाई जाती हैं.

यह पक्का करने के लिए कि हर बार अनुरोध किए जाने पर सभी ऐसेट को कंप्रेस किया जाए, कंप्रेस मिडलवेयर लाइब्रेरी का इस्तेमाल किया जा सकता है. इसे 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.config.js:

const path = require("path");

//...

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

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

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

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

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

  • टूल बटन पर क्लिक करें.
  • कंसोल बटन पर क्लिक करें.
  • इसकी सभी फ़ाइलें देखने और 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 पैनल पर नज़र डालें.

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

पहले की तरह ही, बंडल के साइज़ में काफ़ी कमी आई है!

नतीजा

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