Brotli की मदद से, नेटवर्क पेलोड को छोटा और कंप्रेस करें

Michael DiBlasio
Michael DiBlasio

यह कोडलैब, नेटवर्क पेलोड को छोटा और कंप्रेस करें कोडलैब का एक्सटेंशन है. इसमें यह माना गया है कि आपको कंप्रेशन के बुनियादी कॉन्सेप्ट के बारे में पता है. इस कोडलैब में बताया गया है कि gzip जैसे अन्य कंप्रेस करने वाले एल्गोरिदम की तुलना में, Brotli कंप्रेस करने वाले एल्गोरिदम (br) से कंप्रेस करने के अनुपात को और कम किया जा सकता है. साथ ही, इससे आपके ऐप्लिकेशन का कुल साइज़ भी कम हो जाता है.

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

मापें

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

  1. प्रोजेक्ट में बदलाव करने के लिए, बदलाव करने के लिए रीमिक्स करें पर क्लिक करें.
  2. साइट की झलक देखने के लिए, ऐप्लिकेशन देखें दबाएं. इसके बाद, फ़ुलस्क्रीन फ़ुलस्क्रीन दबाएं.

पिछले नेटवर्क पेलोड को छोटा और कंप्रेस करने के बारे में जानकारी देने वाले कोडलैब में, हमने main.js का साइज़ 225 केबी से घटाकर 61.6 केबी कर दिया था. इस कोडलैब में, आपको यह जानने को मिलेगा कि Brotli कंप्रेशन की मदद से, इस बंडल के साइज़ को और भी कम कैसे किया जा सकता है.

Brotli Compression

Brotli, कॉन्टेंट को कंप्रेस करने के लिए नया एल्गोरिदम है. यह gzip की तुलना में, टेक्स्ट को और भी बेहतर तरीके से कंप्रेस कर सकता है. CertSimple के मुताबिक, Brotli की परफ़ॉर्मेंस इस तरह है:

  • JavaScript के लिए gzip से 14% छोटा
  • एचटीएमएल के लिए, gzip से 21% छोटा
  • सीएसएस के लिए, gzip से 17% छोटा

Brotli का इस्तेमाल करने के लिए, आपके सर्वर पर एचटीटीपीएस काम करना चाहिए. Brotli, सभी आधुनिक ब्राउज़र पर काम करता है. Brotli के साथ काम करने वाले ब्राउज़र, Accept-Encoding हेडर में br शामिल करेंगे:

Accept-Encoding: gzip, deflate, br

Chrome डेवलपर टूल के नेटवर्क टैब में मौजूद Content-Encoding फ़ील्ड (Command+Option+I या Ctrl+Alt+I) का इस्तेमाल करके, यह पता लगाया जा सकता है कि किस कंप्रेसर एल्गोरिदम का इस्तेमाल किया गया है:

नेटवर्क पैनल. Content-encoding कॉलम में, अलग-अलग ऐसेट के लिए इस्तेमाल किए गए कोड दिखते हैं. इनमें gzip और brotli (br) शामिल हैं.

Brotli को चालू करने का तरीका

Brotli-encoded संसाधन भेजने के लिए वेब सर्वर को सेट अप करने का तरीका इस बात पर निर्भर करता है कि आपको उन्हें कैसे एन्कोड करना है. आपके पास दो विकल्प हैं. पहला, अनुरोध के समय Brotli का इस्तेमाल करके संसाधनों को डाइनैमिक तरीके से कंप्रेस करना (डाइनैमिक). दूसरा, उन्हें पहले से ही कंप्रेस करके रखना, ताकि उपयोगकर्ता के अनुरोध करने से पहले ही वे कंप्रेस हो जाएं (स्टैटिक).

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

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

फ़ायदे

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

नुकसान

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

Node और Express की मदद से डाइनैमिक कंप्रेशन

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/directory में मौजूद सभी स्टैटिक एचटीएमएल, JS, और सीएसएस फ़ाइलों को लोड करता है. साथ ही, उन फ़ाइलों को हर बिल्ड के साथ webpack बनाता है.

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

"devDependencies": {
  // ...
  "shrink-ray": "^0.1.3"
},

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

const express = require('express');
const shrinkRay = require('shrink-ray');

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

// ...
const app = express();

// Compress all requests
app.use(shrinkRay());
app.use(express.static('public'));

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

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

अब आपको Content-Encoding हेडर में दिखेगा कि bz से brotli लागू किया गया है. main.bundle.js का साइज़ 225 केबी से घटकर 53.1 केबी हो गया है! यह gzip (61.6 केबी) की तुलना में ~14% छोटा है.

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

स्टैटिक कंप्रेशन का मकसद, ऐसेट को पहले से कंप्रेस करके सेव करना है.

फ़ायदे

  • कंप्रेशन के ज़्यादा लेवल की वजह से होने वाली लेटेन्सी अब कोई समस्या नहीं है. फ़ाइलों को कंप्रेस करने के लिए, कुछ भी करने की ज़रूरत नहीं है. ऐसा इसलिए, क्योंकि अब उन्हें सीधे तौर पर फ़ेच किया जा सकता है.

नुकसान

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

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

स्टैटिक कंप्रेस करने की सुविधा में, फ़ाइलों को पहले से कंप्रेस किया जाता है. इसलिए, webpack की सेटिंग में बदलाव करके, ऐसेट को कंप्रेस किया जा सकता है. इसके लिए, brotli-webpack-plugin का इस्तेमाल किया जा सकता है.

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

"devDependencies": {
  // ...
 "brotli-webpack-plugin": "^1.1.0"
},

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

var path = require("path");

//...
var BrotliPlugin = require('brotli-webpack-plugin');

इसके बाद, इसे प्लगिन के कलेक्शन में शामिल करें:

module.exports = {
  // ...
  plugins: [
    // ...
    new BrotliPlugin({
      asset: '[file].br',
      test: /\.(js)$/
    })
  ]
},

प्लगिन ऐरे में इन तर्कों का इस्तेमाल किया जाता है:

  • asset: टारगेट ऐसेट का नाम.
  • [file] की जगह, ऐसेट की ओरिजनल फ़ाइल का नाम दिखता है.
  • test: इस RegExp से मेल खाने वाली सभी ऐसेट (यानी कि .js से खत्म होने वाली JavaScript ऐसेट) प्रोसेस की जाती हैं.

उदाहरण के लिए, main.js का नाम बदलकर main.js.br कर दिया जाएगा.

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

  1. टूल बटन पर क्लिक करें.
  2. Console बटन पर क्लिक करें.
  3. कंसोल में, public डायरेक्ट्री में जाने और उसकी सभी फ़ाइलें देखने के लिए, यहां दिए गए निर्देश चलाएं:
cd public
ls -lh
स्टैटिक ब्रॉटली कंप्रेशन के साथ बंडल का साइज़

बंडल का ब्रॉटली कंप्रेस किया गया वर्शन, main.bundle.js.br, अब यहां भी सेव हो गया है. साथ ही, यह main.bundle.js की तुलना में ~76% छोटा है (225 केबी बनाम 53 केबी).

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

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

app.get('*.js', (req, res, next) => {
  req.url = req.url + '.br';
  res.set('Content-Encoding', 'br');
  res.set('Content-Type', 'application/javascript; charset=UTF-8');
  next();
});

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

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

  • पहले आर्ग्युमेंट के तौर पर '*.js' को तय करने का मतलब है कि यह हर उस एंडपॉइंट के लिए काम करता है जिसे JS फ़ाइल फ़ेच करने के लिए ट्रिगर किया जाता है.
  • कॉलबैक के दौरान, .br को अनुरोध के यूआरएल से जोड़ा जाता है. साथ ही, Content-Encoding रिस्पॉन्स हेडर को br पर सेट किया जाता है.
  • MIME टाइप तय करने के लिए, Content-Type हेडर को application/javascript; charset=UTF-8 पर सेट किया गया है.
  • आखिर में, next() यह पक्का करता है कि क्रम में अगला कोई भी कॉलबैक जारी रहे.

ऐसा हो सकता है कि कुछ ब्राउज़र, ब्रॉटली कंप्रेस करने की सुविधा के साथ काम न करें. इसलिए, ब्रॉटली कंप्रेस की गई फ़ाइल को वापस भेजने से पहले, यह पक्का करें कि ब्रॉटली कंप्रेस करने की सुविधा काम करती हो. इसके लिए, Accept-Encoding अनुरोध हेडर में br की जांच करें:

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

app.get('*.js', (req, res, next) => {
  if (req.header('Accept-Encoding').includes('br')) {
    req.url = req.url + '.br';
    console.log(req.header('Accept-Encoding'));
    res.set('Content-Encoding', 'br');
    res.set('Content-Type', 'application/javascript; charset=UTF-8');
  }

  next();
});

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

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

बंडल का साइज़ 53.1 केबी (225 केबी से कम)

हो गया! आपने अपनी ऐसेट को और कंप्रेस करने के लिए, Brotli कंप्रेस करने की सुविधा का इस्तेमाल किया है!

नतीजा

इस कोडलैब में बताया गया है कि brotli, आपके ऐप्लिकेशन के कुल साइज़ को और कैसे कम कर सकता है. जहां brotli काम करता है वहां यह gzip की तुलना में, कॉन्टेंट को कंप्रेस करने के लिए ज़्यादा बेहतर एल्गोरिदम है.