يمثّل هذا الدرس التطبيقي حول الترميز امتدادًا للدرس التطبيقي حول الترميز: تصغير وضغط حمولات البيانات في الشبكة، ويفترض أنّك على دراية بالمفاهيم الأساسية للضغط. مقارنةً بخوارزميات الضغط الأخرى مثل gzip
، يستكشف هذا الدرس التطبيقي حول الترميز كيفية تقليل نِسب الضغط وحجم تطبيقك بشكل أكبر،
قياس
قبل البدء بإضافة تحسينات، من الأفضل دائمًا تحليل الحالة الحالية للتطبيق أولاً.
- انقر على إنشاء ريمكس لتعديله ليصبح المشروع قابلاً للتعديل.
- لمعاينة الموقع الإلكتروني، اضغط على عرض التطبيق، ثم اضغط على ملء الشاشة .
في الدرس التطبيقي السابق حول ترميز حمولات البيانات وتصغيرها للشبكة، خفّضنا حجم main.js
من 225 كيلوبايت إلى 61.6 كيلوبايت. في هذا الدرس التطبيقي حول الترميز، سوف تستكشف كيف يمكن
لضغط Brotli تقليل حجم الحزمة بشكل أكبر.
ضغط بروتلي
Butli هي خوارزمية ضغط أحدث يمكنها تقديم نتائج ضغط أفضل للنصوص مقارنةً بـ gzip
. وفقًا لـ CertSimple، فإن أداء Brotli هو:
- أقل من
gzip
بنسبة 14% في JavaScript - أصغر بنسبة% 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
مسؤولاً عن إعداد خادم العقدة الذي يستضيف
التطبيق.
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
(ويتم إنشاء هذه الملفات بواسطة حزمة ويب مع كل إصدار).
وللتأكّد من ضغط جميع مواد العرض باستخدام botli في كل مرة يتم طلبها، يمكن استخدام وحدة 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
من bz
في عنوان Content-Encoding
.
تم خفض main.bundle.js
من 225 كيلوبايت إلى 53.1 كيلوبايت. وهو أصغر بنسبة% 14 تقريبًا
مقارنةً بـ gzip
(61.6 كيلوبايت).
الضغط الثابت
يكمن الغرض من الضغط الثابت في ضغط الأصول وحفظها مسبقًا.
الإيجابيات
- لم يعد وقت الاستجابة بسبب مستويات الضغط العالية مصدر قلق. لا يلزم أن يحدث أي شيء لحظيًا لضغط الملفات، حيث يمكن الآن جلبها مباشرةً.
السلبيات
- يجب ضغط مواد العرض مع كل إصدار. يمكن أن تزيد أوقات الإنشاء بشكل كبير إذا تم استخدام مستويات ضغط عالية.
ضغط ثابت باستخدام Node/Express وwebpack
بما أنّ الضغط الثابت يتضمّن ضغط الملفات مسبقًا، يمكن تعديل إعدادات حزمة الويب لضغط الأصول كجزء من خطوة التصميم. ويمكن استخدام
brotli-webpack-plugin
لهذا الغرض.
ابدأ بإضافته كـ devDependency
في package.json
:
"devDependencies": {
//...
"brotli-webpack-plugin": "^1.1.0"
},
وكما هو الحال مع أي مكوّن إضافي آخر لحزمة الويب، يمكنك استيراده في ملف الإعدادات،
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
: تتم معالجة جميع مواد العرض التي تتطابق مع هذا التعبير العادي (أي مواد عرض JavaScript التي تنتهي بـ.js
).
على سبيل المثال، سيتم تغيير اسم main.js
إلى main.js.br
.
عند إعادة تحميل التطبيق وإعادة بنائه، يتم الآن إنشاء نسخة مضغوطة من الحزمة الرئيسية. افتح أداة Glitch Console لإلقاء نظرة على محتوى دليل
public/
الأخير الذي يعرضه خادم العقدة.
- انقر على الزرّ أدوات.
- انقر على الزر وحدة التحكّم.
- في وحدة التحكّم، شغِّل الأوامر التالية للتغيير إلى دليل
public
واطّلِع على جميع ملفاته:
cd public
ls -lh
تم الآن حفظ نسخة الحزمة المضغوطة من botli، main.bundle.js.br
،
هنا أيضًا، وهي حجمها أصغر بنسبة% 76 (225 كيلوبايت مقابل 53 كيلوبايت) من
main.bundle.js
.
بعد ذلك، اطلُب من الخادم إرسال هذه الملفات المضغوطة بتنسيق broli كلما تم طلب إصدارات JavaScript الأصلية. يمكن إجراء ذلك من خلال تحديد مسار جديد في 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
الخاص بنقطة نهاية محددة. يتم بعد ذلك استخدام دالة رد اتصال لتحديد كيفية التعامل مع هذا الطلب. يعمل المسار على النحو التالي:
- يعني تحديد
'*.js'
كوسيطة أولى أنّ هذه الطريقة مناسبة لكل نقطة نهاية يتم تنشيطها لجلب ملف JavaScript. - ضمن معاودة الاتصال، يتم إرفاق
.br
بعنوان URL للطلب، ويتم ضبط عنوان الاستجابةContent-Encoding
علىbr
. - تم ضبط عنوان
Content-Type
علىapplication/javascript; charset=UTF-8
لتحديد نوع MIME. - وأخيرًا، تضمن السمة
next()
استمرار التسلسل في أي استدعاء قد يكون بعد ذلك.
ولأنّ بعض المتصفحات قد لا تتيح ضغط broli، عليك التأكّد من أنّ botli
متوافق قبل عرض ملف broli المضغوط، وذلك من خلال التأكُّد من أنّ عنوان الطلب Accept-Encoding
يتضمن br
:
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'));
بعد إعادة تحميل التطبيق، ألقِ نظرة على لوحة "الشبكة" مرة أخرى.
اكتمال عملية النقل بنجاح لقد استخدمت ضغط Brotli لضغط مواد العرض بشكل أكبر.
الخلاصة
أوضح هذا الدرس التطبيقي حول الترميز كيف يمكن لـ brotli
تقليل الحجم الكلي لتطبيقك. وتُعدّ brotli
خوارزمية ضغط أكثر فعالية من gzip
، في حال توفّرها.