کوچک کردن و فشرده سازی محموله های شبکه با brotli

مایکل دی بلازیو
Michael DiBlasio

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

اسکرین شات برنامه

اندازه گیری کنید

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

  1. روی Remix to Edit کلیک کنید تا پروژه قابل ویرایش باشد.
  2. برای پیش نمایش سایت، View App را فشار دهید. سپس تمام صفحه را فشار دهید تمام صفحه .

در نسخه قبلی Minify and compres payloads network ، اندازه main.js را از 225 کیلوبایت به 61.6 کیلوبایت کاهش دادیم. در این نرم‌افزار، خواهید دید که چگونه فشرده‌سازی Brotli می‌تواند این اندازه بسته را حتی بیشتر کاهش دهد.

فشرده سازی بروتلی

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

  • 14٪ کوچکتر از gzip برای جاوا اسکریپت
  • 21٪ کوچکتر از gzip برای HTML
  • 17٪ کوچکتر از 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 (و این فایل‌ها توسط بسته وب با هر ساختنی ایجاد می‌شوند).

برای اطمینان از اینکه همه دارایی ها هر بار که درخواست می شوند با استفاده از 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 از 225 کیلوبایت به 53.1 کیلوبایت کاهش یافته است! این در مقایسه با gzip (61.6 کیلوبایت) 14٪ کوچکتر است.

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

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

مزایا

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

معایب

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

فشرده سازی استاتیک با Node و Express با بسته وب

از آنجایی که فشرده‌سازی استاتیک شامل فشرده‌سازی فایل‌ها قبل از زمان می‌شود، تنظیمات بسته وب را می‌توان برای فشرده‌سازی دارایی‌ها به عنوان بخشی از مرحله ساخت تغییر داد. برای این کار می توان 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. روی دکمه Tools کلیک کنید.
  2. روی دکمه Console کلیک کنید.
  3. در کنسول، دستورات زیر را اجرا کنید تا به دایرکتوری public تغییر دهید و همه فایل‌های آن را ببینید:
cd public
ls -lh
اندازه بسته نرم افزاری با فشرده سازی استاتیک Brotli

نسخه فشرده‌شده brotli، main.bundle.js.br ، اکنون در اینجا نیز ذخیره شده است و 76 درصد اندازه آن (225 کیلوبایت در مقابل 53 کیلوبایت) از 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 برای یک نقطه پایانی خاص پاسخ دهد استفاده می شود. سپس یک تابع callback برای تعریف نحوه رسیدگی به این درخواست استفاده می شود. مسیر به این صورت عمل می کند:

  • تعیین '*.js' به عنوان اولین آرگومان به این معنی است که برای هر نقطه پایانی که برای واکشی یک فایل JS فعال می شود، کار می کند.
  • در پاسخ به تماس، .br URL درخواست وصل می شود و سرصفحه پاسخ 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'));

پس از بارگیری مجدد برنامه، یک بار دیگر به پنل شبکه نگاهی بیندازید.

حجم بسته 53.1 کیلوبایت (از 225 کیلوبایت)

موفقیت! شما از فشرده سازی Brotli برای فشرده سازی بیشتر دارایی های خود استفاده کرده اید!

نتیجه گیری

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