کوچک کردن و فشرده کردن بار خالص شبکه با brotli

Michael DiBlasio
Michael DiBlasio

این codelab افزونه‌ای از codelab کوچک‌سازی و فشرده‌سازی بار خالص شبکه است و فرض می‌کند که با مفاهیم اولیه فشرده‌سازی آشنا هستید. در مقایسه با سایر الگوریتم‌های فشرده‌سازی مانند gzip، این codelab بررسی می‌کند که چگونه فشرده‌سازی Brotli (br) می‌تواند نسبت‌های فشرده‌سازی و اندازه کلی برنامه شما را بیشتر کاهش دهد.

نماگرفت برنامه

اندازه گرفتن

قبل‌از اینکه برای افزودن بهینه‌سازی‌ها دست‌به‌کار شوید، همیشه ایده خوبی است که ابتدا وضعیت فعلی برنامه را تجزیه‌وتحلیل کنید.

  1. روی بازآمیزی برای ویرایش کلیک کنید تا پروژه قابل‌ویرایش شود.
  2. برای پیش‌دید کردن سایت، مشاهده برنامه را فشار دهید. سپس تمام‌صفحه تمام‌صفحه را فشار دهید.

در کدلب «کوچک کردن و فشرده‌سازی بار خالص شبکه» قبلی، اندازه main.js را از ۲۲۵ کیلوبایت به ۶۱٫۶ کیلوبایت کاهش دادیم. در این codelab، شما بررسی خواهید کرد که چگونه فشرده‌سازی Brotli می‌تواند اندازه این بسته را حتی بیشتر کاهش دهد.

فشرده‌سازی Brotli

Brotli الگوریتم فشرده‌سازی جدیدتری است که می‌تواند نتایج فشرده‌سازی نوشتار بهتری نسبت‌به gzip ارائه دهد. طبق CertSimple، عملکرد Brotli عبارت است از:

  • ‫٪۱۴ کوچک‌تر از gzip برای جاوا اسکریپت
  • ‫۲۱٪ کوچک‌تر از gzip برای HTML
  • ‫۱۷٪ کوچک‌تر از gzip برای CSS

برای استفاده از Brotli، سرورتان باید از HTTPS پشتیبانی کند. Brotli در همه مرورگرهای نو پشتیبانی می‌شود. مرورگرهایی که از Brotli پشتیبانی می‌کنند br را در سرصفحه‌های Accept-Encoding اضافه خواهند کرد:

Accept-Encoding: gzip, deflate, br

می‌توانید بااستفاده از فیلد Content-Encoding در برگه «شبکه» در «ابزارهای توسعه‌دهنده Chrome» (Command+Option+I یا Ctrl+Alt+I) تعیین کنید که از کدام الگوریتم فشرده‌سازی استفاده می‌شود:

پانل «شبکه». ستون Content-encoding (کدبندی محتوا) کدبندی‌های مورداستفاده برای دارایی‌های مختلف را نمایش می‌دهد، ازجمله gzip و brotli (br).

نحوه فعال کردن Brotli

نحوه راه‌اندازی سرور وب برای ارسال منابع کدبندی‌شده با Brotli به نحوه برنامه‌ریزی شما برای کدبندی آن‌ها بستگی دارد. گزینه‌های شما این است که منابع را به‌طور پویا با Brotli در زمان درخواست فشرده کنید (پویا)، یا آن‌ها را پیش‌از موعد کدگذاری کنید تا در زمان درخواست کاربر فشرده شده باشند (ایستا).

فشرده‌سازی پویا

فشرده‌سازی پویا شامل فشرده‌سازی دارایی‌ها درحین اجرا است، یعنی زمانی که مرورگر آن‌ها را درخواست می‌کند.

مزیت‌ها

  • نیازی به ایجاد و به‌روزرسانی نسخه‌های فشرده ذخیره‌شده دارایی‌ها نیست.
  • فشرده‌سازی درحین اجرا به‌ویژه برای صفحه‌های وبی که به‌طور پویا تولید می‌شوند بسیار خوب کار می‌کند.

معایب

  • فشرده‌سازی فایل‌ها در سطوح بالاتر برای دستیابی به نسبت‌های فشرده‌سازی بهتر، زمان بیشتری می‌برد. این امر می‌تواند باعث افت عملکرد شود زیرا کاربر منتظر می‌ماند تا دارایی‌ها قبل‌از ارسال توسط سرور فشرده شوند.

فشرده‌سازی پویا با Node و Express

فایل server.js مسئول راه‌اندازی سرور Node است که برنامه را میزبانی می‌کند.

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 برای بار کردن همه فایل‌های HTML،‏ JS، و CSS ایستا در public/directory است (و این فایل‌ها توسط webpack با هر ساخت ایجاد می‌شوند).

برای اطمینان از اینکه همه دارایی‌ها هربار که درخواست می‌شوند بااستفاده از brotli فشرده می‌شوند، می‌توان از ماژول shrink-ray استفاده کرد. با افزودن آن به‌عنوان devDependency در package.json شروع کنید:

"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'));

اکنون برنامه را مجدداً بار کنید و به اندازه دسته در پانل «شبکه» نگاه کنید:

اندازه بسته با فشرده‌سازی Brotli پویا.

اکنون می‌توانید ببینید که brotli از bz در سرصفحه Content-Encoding اعمال شده است. ‫main.bundle.js از ۲۲۵ کیلوبایت به ۵۳٫۱ کیلوبایت کاهش یافت! این مقدار تقریباً ۱۴٪ کوچک‌تر از gzip (۶۱٫۶ کیلوبایت) است.

فشرده‌سازی ایستا

ایده پشت فشرده‌سازی ایستا این است که دارایی‌ها ازقبل فشرده و ذخیره شوند.

مزیت‌ها

  • تأخیر ناشی از سطوح فشرده‌سازی بالا دیگر نگران‌کننده نیست. نیازی نیست که فایل‌ها درحین انتقال فشرده شوند زیرا اکنون می‌توان آن‌ها را مستقیماً واکشی کرد.

معایب

  • دارایی‌ها باید با هر ساخت فشرده شوند. اگر از سطوح فشرده‌سازی بالا استفاده شود، زمان ساخت می‌تواند به‌طور قابل‌توجهی افزایش یابد.

فشرده‌سازی ثابت با Node و Express با webpack

ازآنجایی‌که فشرده‌سازی ایستا شامل فشرده‌سازی فایل‌ها ازقبل است، تنظیمات webpack را می‌توان تغییر داد تا دارایی‌ها را به‌عنوان بخشی از مرحله ساخت فشرده کند. brotli-webpack-plugin می‌تواند برای این کار استفاده شود.

با افزودن آن به‌عنوان devDependency در package.json شروع کنید:

"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 ختم می‌شوند) پردازش می‌شوند.

برای مثال، main.js به main.js.br تغییر نام خواهد داد.

وقتی برنامه دوباره بار می‌شود و بازسازی می‌شود، نسخه فشرده‌ای از دسته اصلی اکنون ایجاد شده است. «کنسول Glitch» را باز کنید تا ببینید چه چیزی در فهرست راهنمای نهایی public/ وجود دارد که توسط سرور Node ارائه می‌شود.

  1. روی دکمه ابزارها کلیک کنید.
  2. روی دکمه کنسول کلیک کنید.
  3. در کنسول، فرمان‌های زیر را اجرا کنید تا به فهرست راهنمای public بروید و همه فایل‌های آن را ببینید:
cd public
ls -lh
اندازه بسته با فشرده‌سازی Brotli ایستا

نسخه فشرده‌شده Brotli از دسته، main.bundle.js.br، اکنون در اینجا نیز ذخیره شده است و ~۷۶٪ کوچک‌تر (۲۲۵ کیلوبایت درمقابل ۵۳ کیلوبایت) از main.bundle.js است.

سپس به سرور بگویید که هرگاه نسخه‌های JS اصلی این فایل‌های فشرده‌شده با brotli درخواست شد، آن‌ها را ارسال کند. این کار را می‌توان با تعریف مسیر جدیدی در 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' به‌عنوان اولین آرگومان به این معنی است که این برای هر نقطه پایانی که برای واکشی فایل جاوااسکریپت فعال می‌شود کار می‌کند.
  • در بازخوان، .br به نشانی وب درخواست پیوست می‌شود و سرصفحه پاسخ Content-Encoding روی br تنظیم می‌شود.
  • سرصفحه Content-Type روی application/javascript; charset=UTF-8 تنظیم شده است تا نوع MIME را مشخص کند.
  • درنهایت، next() تضمین می‌کند که توالی به هر بازخوانی که ممکن است بعدی باشد ادامه یابد.

چون ممکن است برخی مرورگرها از فشرده‌سازی brotli پشتیبانی نکنند، قبل‌از برگرداندن فایل فشرده‌شده با brotli، با بررسی اینکه سرایند درخواست Accept-Encoding شامل br است، مطمئن شوید که از brotli پشتیبانی می‌شود:

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'));

وقتی برنامه دوباره بار شد، یک‌بار دیگر به پانل «شبکه» نگاه کنید.

اندازه بسته ۵۳٫۱ کیلوبایت (از ۲۲۵ کیلوبایت)

موفقیت‌آمیز بود. از فشرده‌سازی Brotli برای فشرده‌سازی بیشتر دارایی‌هایتان استفاده کرده‌اید!

نتیجه‌گیری

این codelab نشان داد که چگونه brotli می‌تواند اندازه کلی برنامه‌تان را بیشتر کاهش دهد. درصورت پشتیبانی، brotli الگوریتم فشرده‌سازی قدرتمندتری نسبت به gzip است.