"ابن آوى": الضغط على الواجهة الأمامية

تحية! أنا فانيا ، قائد فريق المنصات في Tinkoff Business.

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




لماذا


الآن التطبيقات الأمامية تزن الكثير. يمكن أن تزن القطع الأثرية المجمعة 2-3 ميغابايت ، أو أكثر. ومع ذلك ، تأتي خوارزميات الضغط لمساعدة المستخدمين.

حتى وقت قريب ، استخدمنا Gzip فقط ، والذي تم تقديمه للعالم في عام 1992. ربما تكون هذه هي خوارزمية الضغط الأكثر شيوعًا على الويب ، فهي مدعومة من قبل جميع المتصفحات فوق IE 6.

واسمحوا لي أن أذكرك أن مستوى ضغط Gzip يختلف في النطاق من 1 إلى 9 (أكثر فعالية) ، ويمكنك ضغطه إما سريعًا أو ثابتًا.

  • "على الطاير" (بشكل حيوي) - يتم تخزين القطع الأثرية في النموذج الذي تم استلامه بعد التجميع ، ويحدث ضغطها أثناء التسليم إلى العميل. في حالتنا ، على مستوى nginx.
  • يتم ضغط القطع الأثرية الثابتة بعد التجميع ، ويرسلها خادم HTTP إلى العميل "كما هي".

من الواضح أن الخيار الأول يتطلب المزيد من موارد الخادم لكل طلب. والثاني هو في مرحلة التجميع وإعداد الطلب.

تم ضغط الواجهة الأمامية الخاصة بنا بشكل ديناميكي من المستوى الرابع. سأبين الفرق بين قطعة أثرية مضغوطة والأصلية:
مستوى الضغط
قطعة أثرية الوزن ، كيلو بايت
وقت الضغط ، مللي
0
2522
-
1
732
42
2
702
44
3
683
48
4
636
55
5
612
65
6
604
77
7
604
80
8
603
104
9
601
102

قد تلاحظ أنه حتى المستوى الرابع يقلل من حجم القطع الأثرية بنسبة 4 مرات! والفرق بين المستوى الرابع والتاسع هو 35 كيلو بايت ، أي 1.3٪ من الأصل ، لكن وقت الضغط أطول مرتين.

ومؤخراً ، فكرنا: لماذا لا نتحول إلى بروتلي؟ نعم ، وعلى أقوى مستوى من الضغط!

بالمناسبة ، تم تقديم هذه الخوارزمية بواسطة Google في عام 2015 ولديها 11 مستوى ضغط. في الوقت نفسه ، المستوى الرابع من Brotli أكثر فعالية من المستوى التاسع في Gzip. حصلت على الحافز ورميت بسرعة لضغط المصنوعات اليدوية باستخدام خوارزمية Brotli. النتائج معروضة أدناه:
مستوى الضغط
قطعة أثرية الوزن ، كيلو بايت
وقت الضغط ، مللي
0
2522
-
1
662
128
2
612
155
3
601
156
4
574
202
5
526
227
6
512
249
7
501
303
8
496
359
9
492
420
10
452
3708
11
446
8257

ومع ذلك ، يوضح الجدول أنه حتى مستوى ضغط 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. دعنا نذهب على البرامج النصية.

ضاغط القاعدة - برنامج نصي يقوم بتنفيذ منطق الضغط الأساسي.

وسيطات الإدخال:

  1. وظيفة الضغط - أي وظيفة جافا سكريبت ، يمكنك تنفيذ خوارزمية الضغط الخاصة بك.
  2. معلمات الضغط - كائن ذو معلمات ضرورية للوظيفة المنقولة.
  3. تمديد - التوسع في ضغط التحف. يجب أن يكون محددًا بدءًا من حرف الفترة.

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:


Source: https://habr.com/ru/post/ar474632/


All Articles