تحية! أنا فانيا ، قائد فريق المنصات في Tinkoff Business.
إن هوايتي المفضلة هي فتح علامة تبويب DevTools والتحقق من مقدار تأثيرات موقع الويب. في هذه المقالة ، سوف أخبرك كيف خفضنا وزن التطبيق بنسبة 30٪ باستخدام فريق الواجهة الأمامية للنظام الأساسي في يوم واحد دون تغيير رمز الموقع. لا الحيل والتسجيلات - فقط nginx ، عامل ميناء و node.js (اختياري).

لماذا
الآن التطبيقات الأمامية تزن الكثير. يمكن أن تزن القطع الأثرية المجمعة 2-3 ميغابايت ، أو أكثر. ومع ذلك ، تأتي خوارزميات الضغط لمساعدة المستخدمين.
حتى وقت قريب ، استخدمنا Gzip فقط ، والذي تم تقديمه للعالم في عام 1992. ربما تكون هذه هي خوارزمية الضغط الأكثر شيوعًا على الويب ، فهي مدعومة من قبل
جميع المتصفحات فوق IE 6.واسمحوا لي أن أذكرك أن مستوى ضغط Gzip يختلف في النطاق من 1 إلى 9 (أكثر فعالية) ، ويمكنك ضغطه إما سريعًا أو ثابتًا.
- "على الطاير" (بشكل حيوي) - يتم تخزين القطع الأثرية في النموذج الذي تم استلامه بعد التجميع ، ويحدث ضغطها أثناء التسليم إلى العميل. في حالتنا ، على مستوى nginx.
- يتم ضغط القطع الأثرية الثابتة بعد التجميع ، ويرسلها خادم HTTP إلى العميل "كما هي".
من الواضح أن الخيار الأول يتطلب المزيد من موارد الخادم لكل طلب. والثاني هو في مرحلة التجميع وإعداد الطلب.
تم ضغط الواجهة الأمامية الخاصة بنا بشكل ديناميكي من المستوى الرابع. سأبين الفرق بين قطعة أثرية مضغوطة والأصلية:
قد تلاحظ أنه حتى المستوى الرابع يقلل من حجم القطع الأثرية بنسبة 4 مرات! والفرق بين المستوى الرابع والتاسع هو 35 كيلو بايت ، أي 1.3٪ من الأصل ، لكن وقت الضغط أطول مرتين.
ومؤخراً ، فكرنا: لماذا لا نتحول إلى بروتلي؟ نعم ، وعلى أقوى مستوى من الضغط!
بالمناسبة ، تم تقديم هذه الخوارزمية بواسطة Google في عام 2015 ولديها 11 مستوى ضغط. في الوقت نفسه ، المستوى الرابع من Brotli أكثر فعالية من المستوى التاسع في Gzip. حصلت على الحافز ورميت بسرعة لضغط المصنوعات اليدوية باستخدام خوارزمية Brotli. النتائج معروضة أدناه:
ومع ذلك ، يوضح الجدول أنه حتى مستوى ضغط Brotli الأول يستغرق وقتًا أطول من المستوى التاسع في Gzip. والمستوى الأخير - بقدر 8.3 ثانية! لقد نبهتني.
من ناحية أخرى ، كانت النتيجة مثيرة للإعجاب بشكل واضح. بعد ذلك ، حاولت نقل الضغط إلى nginx -
google الوثائق . كل شيء تبين أنه بسيط للغاية:
brotli on; brotli_comp_level 11; brotli_types text/plain text/css application/javascript;
قام بتجميع صورة عامل ميناء ، أطلق الحاوية وفوجئت بشكل رهيب:

زاد وقت تنزيل ملفي عشرة أضعاف - من 100 مللي ثانية إلى 5 ثوانٍ! أصبح التطبيق مستحيل الاستخدام.
بعد أن درست الوثائق بشكل أعمق ، أدركت أنه يمكنك توزيع البيانات بشكل ثابت. لقد استخدمت نصًا مكتوبًا مسبقًا ، وضغطت نفس المصنوعات ، وأضعته في حاوية ، وأطلقته. تحميل مرات العودة إلى وضعها الطبيعي - النصر! ومع ذلك ، من السابق لأوانه السعادة لأن نسبة المتصفحات التي تدعم هذا النوع من الضغط تبلغ
حوالي 80٪ .
هذا يعني أنه يجب الحفاظ على التوافق مع الإصدارات السابقة ، بينما تريد أيضًا استخدام المستوى الأكثر فاعلية من Gzip. لذلك ظهرت الفكرة لإنشاء أداة ضغط الملفات ، والتي حصلت فيما بعد على اسم "Jackal".

ماذا نحتاج؟
Nginx و Docker و Node.js ، على الرغم من أنه يمكنك أيضًا استخدام bash إذا كنت ترغب في ذلك.
مع Nginx ، كل شيء تقريبًا واضح:
brotli off; brotli_static on; gzip_static on;
ولكن ماذا تفعل مع التطبيقات التي لم تتمكن بعد من تحديث صورة عامل الميناء؟ اليمين ، إضافة التوافق إلى الوراء:
gzip on; gzip_level 4; gzip_types text/plain text/css application/javascript;
سأشرح مبدأ العملية:
عند كل طلب ، يرسل العميل رأس قبول - التشفير ، والذي يسرد خوارزميات الضغط المدعومة ، مفصولة بفواصل. عادة ما يكون فرغ ، gzip ، ر.
إذا كان لدى العميل br في السطر ، فابحث nginx عن الملفات ذات الامتداد .br ، إذا لم يكن هناك مثل هذه الملفات وكان العميل يدعم Gzip ، فسيبحث عن .gz. إذا لم يكن هناك مثل هذه الملفات ، فسوف يهتز "سريعًا" ويعيدها مع المستوى الرابع من الضغط.
إذا كان العميل لا يدعم أي نوع من الضغط ، فسيقوم الخادم بإصدار قطع أثرية في شكلها الأصلي.
ومع ذلك ، نشأت مشكلة: لا تدعم صورة عامل الإرساء nginx وحدة Brotli. كأساس ، أخذت
صورة عامل ميناء الانتهاء .
Dockerfile ل "التعبئة" nginx في المشروع FROM fholzer/nginx-brotli # RUN rm -rf /usr/share/nginx/html/ # COPY app/nginx /etc/nginx/conf.d/ # COPY dist/ /usr/share/nginx/html/ # CMD nginx -c /etc/nginx/conf.d/nginx.conf
لقد اكتشفنا موازنة حركة المرور ، ولكن من أين يمكن الحصول على القطع الأثرية؟ هذا هو المكان الذي يأتي فيه ابن آوى.
ابن آوى
هذه أداة مساعدة لضغط احصائيات التطبيق الخاص بك.
الآن هذه ثلاثة برامج نصية node.js ملفوفة في صورة عامل ميناء مع عقدة: alpine. دعنا نذهب على البرامج النصية.
ضاغط القاعدة - برنامج نصي يقوم بتنفيذ منطق الضغط الأساسي.
وسيطات الإدخال:
- وظيفة الضغط - أي وظيفة جافا سكريبت ، يمكنك تنفيذ خوارزمية الضغط الخاصة بك.
- معلمات الضغط - كائن ذو معلمات ضرورية للوظيفة المنقولة.
- تمديد - التوسع في ضغط التحف. يجب أن يكون محددًا بدءًا من حرف الفترة.
gzip.js - ملف به استدعاء ضاغط أساسي مع وظيفة Gzip تم تمريره من حزمة
zlib والإشارة إلى المستوى التاسع من الضغط.
brotli.js - ملف مع استدعاء الضاغط الأساسي مع وظيفة Brotli التي تم تمريرها من
نفس حزمة npm والإشارة إلى المستوى الحادي عشر من الضغط.
Dockerfile خلق صورة ابن آوى FROM node:8.12.0-alpine # COPY scripts scripts # package.json package-lock.json COPY package*.json scripts/ # WORKDIR scripts # # node_modules/ # , RUN npm ci # CMD node gzip.js | node brotli.js
اكتشفنا كيف يعمل ، يمكنك الآن تشغيل بأمان:
docker run \ -v $(pwd)/dist:/scripts/dist \ -e 'dirs=["dist/"]' \ -i mngame/shakal
- -v $ (pwd) / dist: / scripts / dist - حدد الدليل المحلي الذي يجب مراعاته في الدليل في الحاوية (رابط إلى الحامل). تحديد دليل البرامج النصية مطلوب ، لأنه يعمل داخل الحاوية.
- -e 'dirs = ["dist /"]' - حدد معلمات بيئة dirs - مجموعة من الخطوط التي تصف الأدلة الموجودة داخل البرامج النصية / التي سيتم ضغطها.
- -i mngame / shakal - تحديد صورة مع docker.io.
في الدلائل المحددة ، يضغط البرنامج النصي بشكل متكرر على جميع الملفات بالملحقات المحددة .js و .json و .html و .css ويحفظ الملفات مع الامتدادات .br و .gz بجانبه. في مشروعنا ، تستغرق هذه العملية حوالي دقيقتين مع وزن جميع القطع الأثرية التي تبلغ حوالي 6 ميغابايت.
في هذه المرحلة ، وربما حتى قبل ذلك ، ربما كنت قد فكرت: "ما عامل الميناء؟ أي عقدة؟ لماذا لا تضيف فقط مجموعتين لنفسك في package.json المشروع وتدعو مباشرة إلى postbuild؟ "
شخصيا ، يؤلمني أن أرى متى ، من أجل تشغيل الشحوم في CI ، يقوم المشروع بتثبيت أكثر من 100 حزمة لنفسه ، والتي يحتاج إلى 10 كحد أقصى في مرحلة الفحص ، وهذا هو وقت الوكيل ، وقتك ، بعد كل شيء ، وقت التسويق.
في حالة عامل الإرساء ، نحصل على صورة مجمعة مسبقًا يتم فيها تثبيت كل ما هو ضروري للضغط. إذا كنت لا تحتاج إلى ضغط أي شيء الآن - لا تضغط. تحتاج إلى الوبر - قم بتشغيله فقط ، وتحتاج إلى الاختبارات - قم بتشغيلها فقط. بالإضافة إلى ذلك ، نحصل على إصدار جيد من Jackal: لا نحتاج إلى تحديث تبعياته في كل مشروع - فقط قم بإصدار إصدار جديد ، واستخدم أحدث علامة للمشروع.
النتيجة:
- لقد تغير حجم القطع الأثرية من 636 كيلو بايت إلى 446 كيلو بايت.
- انخفض حجم النسبة بنسبة 30 ٪.
- انخفض وقت التنزيل بنسبة 10-12 ٪.
- وقت تخفيف الضغط ، بناءً على المقال ، لا يزال كما هو.
في المجموع
يمكنك مساعدة المستخدمين في الوقت الحالي مباشرة من خلال العلاقات العامة التالية: إضافة خطوة بعد التجميع - ضغط "Jackal" ، ثم تسليم القطع الأثرية إلى الحاوية الخاصة بك. بعد نصف ساعة ، يشعر المستخدمون بتحسن كبير.
لقد نجحنا في تقليل وزن الواجهة الأمامية بنسبة 30٪ - ستنجح! جميع المواقع السهلة.
ssylochki: