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

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

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

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

اندازه گرفتن

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

  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 ) تعیین کنید که کدام الگوریتم فشرده‌سازی استفاده می‌شود:

پنل شبکه

فعال کردن Brotli

فشرده سازی دینامیک

فشرده‌سازی پویا شامل فشرده‌سازی دارایی‌ها در لحظه به محض درخواست مرورگر است.

طرفداران

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

منفی

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

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

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

var express = require('express');

var app = express();

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

var 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 وارد کنید:

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

و قبل از نصب express.static آن را به عنوان میان افزار اضافه کنید:

//...
var 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 و 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. روی دکمه 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 انجام داد.

var express = require('express');

var 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 پشتیبانی می‌شود:

var express = require('express');

var 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 است.