برمجة الضغط والترميز

جعل إنشاء مصادر صور عالية الأداء جزءًا سلسًا من عملية التطوير.

جميع التراكيب في هذه الدورة - من ترميز بيانات الصور إلى الترميز الكثيف المعلومات الذي يدعم الصور سريعة الاستجابة - هي طرق تستخدمها الأجهزة للاتصال بالأجهزة. لقد اكتشفت عددًا من الطرق ليتمكن متصفح العميل من توصيل احتياجاته إلى الخادم، وخادم للاستجابة نوعًا ما. يتمكن ترميز الصور السريع الاستجابة (srcset وsizes، على وجه الخصوص) من وصف كمية صادمة من المعلومات باستخدام عدد قليل نسبيًا من الأحرف. الأسوأ أو الأسوأ من ذلك، أنّ الإيجاز هو التصميم، وقد يكون من الصعب على المتصفح تحليلها إذا كانت صياغة الجملة هذه أقل وضوحًا، وتسهيل تحليلها على المطوّرين. كلما تمت إضافة تعقيد إلى سلسلة ما، زادت احتمالية حدوث أخطاء في المحلل أو اختلافات غير مقصودة في السلوك من متصفح إلى آخر.

نافذة ترميز آلي للصور

مع ذلك، إنّ السمة نفسها التي تجعل هذه المواضيع مخيفة قد توفّر لك حلولاً، فلا شكّ في أنّ البنية التي تقرأها الأجهزة بسهولة أكبر، وذلك من خلال كتابة بنية الجملة بسهولة أكبر. لقد تعرفت بالتأكيد على العديد من الأمثلة حول ترميز وضغط الصور التلقائيين كمستخدم على الويب: أي صورة يتم تحميلها إلى الويب من خلال منصات التواصل الاجتماعي، أو أنظمة إدارة المحتوى (CMS)، وحتى برامج البريد الإلكتروني سوف تمر بلا تغيير تقريبًا عبر نظام يغيّر حجمها وإعادة ترميزها وضغطها.

وبالمثل، سواء من خلال المكوّنات الإضافية أو المكتبات الخارجية أو أدوات عملية الإنشاء المستقلة أو الاستخدام المسؤول للبرمجة النصية من جهة العميل، يمكن لترميز الصور سريع الاستجابة استيعاب التشغيل الآلي بسهولة.

وهذان هما مصدران أساسيان يتعلّقان ببرمجة أداء الصور، وهما إدارة إنشاء الصور، مثل ترميزها وضغطها، والمصادر البديلة التي ستستخدمها لتعبئة السمة srcset، وإنشاء الترميز الذي يتوجّه إلى المستخدم. في هذه الوحدة، ستتعرف على بعض المناهج الشائعة لإدارة الصور كجزء من سير العمل الحديث، سواء كمرحلة آلية في عملية التطوير، أو من خلال إطار العمل أو نظام إدارة المحتوى الذي يدعم موقعك، أو تم استخراجه بالكامل تقريبًا من خلال شبكة مخصصة لعرض المحتوى.

برمجة الضغط والترميز

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

كما تعلّمت عند القراءة عن تنسيقات الصور وأنواع ضغطها المختلفة، سيعتمد دائمًا الترميز الأكثر فعالية للصورة على محتواها، وكما تعلّمت في الصور المتجاوبة مع مختلف الأجهزة، سيتم تحديد الأحجام البديلة التي ستحتاجها لمصادر الصور حسب موضع شغل تلك الصور في تنسيق الصفحة. في سير العمل الحديث، سيتم التعامل مع هذه القرارات بشكلٍ شامل بدلاً من أن يتم بشكلٍ فردي من خلال تحديد مجموعة من الإعدادات التلقائية المعقولة للصور لتناسب السياقات التي من المفترض أن يتم استخدامها فيها.

عند اختيار الترميزات لدليل صور فوتوغرافية، تكون AVIF هي الفائز الواضح من حيث الجودة وحجم النقل، ولكنها لا تزال محدودة، وتوفّر WebP خيارًا احتياطيًا محسَّنًا وحديثًا، فيما يُعدّ JPEG الخيار التلقائي الأكثر موثوقية. تختلف الأحجام البديلة التي نحتاج إلى إنتاجها للصور التي تهدف إلى أن تشغل شريطًا جانبيًا في تخطيط الصفحة إلى حد كبير عن الصور التي تهدف إلى أن تشغل إطار عرض المتصفح بالكامل في أعلى نقاط التوقف لدينا. ستتطلب إعدادات الضغط تركيزًا على عناصر التمويه والنقر على العديد من الملفات الناتجة، مما يترك مساحة أقل لتخصيص كل بايت ممكن من كل صورة مقابل سير عمل أكثر مرونة وموثوقية. باختصار، سوف تتبع نفس عملية اتخاذ القرار التي تفهمها من هذه الدورة بشكل كبير.

في ما يتعلّق بعملية المعالجة نفسها، يتوفّر عدد كبير من مكتبات معالجة الصور مفتوحة المصدر التي توفّر طرقًا لتحويل الصور وتعديلها وتعديلها على دفعات، للتنافس على السرعة والكفاءة والموثوقية. ستسمح لك مكتبات المعالجة هذه بتطبيق إعدادات الترميز والضغط على أدلة الصور الكاملة في آنٍ واحد، بدون الحاجة إلى فتح برنامج لتعديل الصور، وبطريقة تحافظ على مصادر الصور الأصلية إذا احتاجت هذه الإعدادات إلى تعديلها أثناء التنقل. والغرض منها هو العمل في مجموعة من السياقات، من بيئة التطوير المحلية إلى خادم الويب نفسه. على سبيل المثال، يمكن توسيع نطاق ImageMin الذي يركّز على الضغط لـ Node.js لتناسب تطبيقات محددة من خلال مصفوفة من المكوّنات الإضافية، بينما يأتي استخدام ImageMagick وSharp المستنِد إلى أنظمة أساسية متعددة مع عدد كبير من الميزات مباشرةً،

تتيح مكتبات معالجة الصور هذه للمطوّرين إنشاء أدوات مخصّصة لتحسين الصور بسلاسة كجزء من عمليات التطوير العادية، ما يضمن أنّ مشروعك سيشير دائمًا إلى مصادر الصور الجاهزة للإنتاج بأقل قدر ممكن من النفقات العامة.

أدوات التطوير المحلي وسير العمل

يمكن استخدام أدوات إدارة المهام وحزم البرامج مثل Grunt أو Gulp أو Webpack لتحسين مواد عرض الصور إلى جانب المهام الشائعة الأخرى المتعلقة بالأداء، مثل تصغير CSS وJavaScript. للتوضيح، لنأخذ حالة استخدام بسيطة نسبيًا: يحتوي دليل في مشروعك على عشرات الصور الفوتوغرافية، والتي يُقصد استخدامها على موقع ويب مواجهة للجمهور.

أولاً، يجب عليك ضمان ترميز متسق وفعّال لهذه الصور. كما تعلمت في الوحدات السابقة، فإن WebP هو خيار افتراضي فعال للصور الفوتوغرافية من حيث الجودة وحجم الملف. إنّ تنسيق WebP متوافق جيدًا، ولكنه غير متاح عالميًا، لذا عليك أيضًا تضمين عنصر احتياطي في شكل صورة JPEG تدريجية. للاستفادة من السمة srcset للتسليم الفعّال لمواد العرض هذه، يجب إنشاء أحجام بديلة متعددة لكل ترميز.

في حين أن هذا سيكون عملاً روتينيًا متكررًا ويستغرق وقتًا طويلاً إذا تم باستخدام برنامج تعديل الصور، تم تصميم برامج تشغيل المهام مثل Gulp لبرمجة هذا النوع من التكرار بالضبط. المكوّن الإضافي gulp-responsive الذي يستخدم ميزة Sharp هو أحد الخيارات من بين العديد من الملفات التي تتبع نمطًا متشابهًا: جمع كل الملفات في دليل مصدر وإعادة ترميزها وضغطها بناءً على الاختصار "الجودة" نفسه الذي تعلّمته في تنسيقات الصور وضغطها. يتم بعد ذلك إخراج الملفات الناتجة إلى مسار تحدّده، وتكون جاهزة للرجوع إليها في سمات src لعناصر img الموجّهة للمستخدمين مع إبقاء ملفاتك الأصلية سليمة.

const { src, dest } = require('gulp');
const respimg = require('gulp-responsive');

exports.webp = function() {
  return src('./src-img/*')
    .pipe(respimg({
      '*': [{
        quality: 70,
        format: ['webp', 'jpeg'],
        progressive: true
      }]
  }))
  .pipe(dest('./img/'));
}

عند تنفيذ عملية كهذه، لن يحدث أي ضرر لبيئة الإنتاج إذا أضاف شخص ما في المشروع، بدون قصد، صورة تم ترميزها كملف PNG بحجم هائل إلى الدليل الذي يحتوي على مصادر الصور الأصلية، بغض النظر عن ترميز الصورة الأصلية، حيث ستنتج هذه المهمة تنسيق WebP فعالاً احتياطيًا ونسخة JPEG تقدمية موثوقًا بها، وبمستوى ضغط يمكن ضبطه بسهولة بشكل فوري. وبالطبع، تضمن هذه العملية أيضًا الاحتفاظ بملفات الصور الأصلية ضمن بيئة تطوير المشروع، ما يعني أنّه يمكن تعديل هذه الإعدادات في أي وقت مع استبدال الإخراج الآلي فقط.

لإخراج ملفات متعددة، عليك تمرير كائنات إعداد متعددة، كلها متماثلة، باستثناء إضافة مفتاح width وقيمة بالبكسل:

const { src, dest } = require('gulp');
const respimg = require('gulp-responsive');

exports.default = function() {
  return src('./src-img/*')
    .pipe(respimg({
    '*': [{
            width: 1000,
            format: ['jpeg', 'webp'],
            progressive: true,
            rename: { suffix: '-1000' }
            },
            {
            width: 800,
            format: ['jpeg', 'webp'],
            progressive: true,
            rename: { suffix: '-800' }
            },
            {
            width: 400,
            format: ['jpeg', 'webp'],
            progressive: true,
            rename: { suffix: '-400' },
        }]
        })
    )
    .pipe(dest('./img/'));
}

في المثال أعلاه، كان حجم الصورة الأصلية (monach.png) أكبر من 3.3 ميغابايت. يبلغ حجم أكبر ملف تم إنشاؤه من خلال هذه المهمة (monrc-1000.jpeg) ما يقرب من 150 كيلوبايت. وهو أصغر حجمًا، monzar-400.web، يبلغ حجمه 32 كيلوبايت فقط.

[10:30:54] Starting 'default'...
[10:30:54] gulp-responsive: monarch.png -> monarch-400.jpeg
[10:30:54] gulp-responsive: monarch.png -> monarch-800.jpeg
[10:30:54] gulp-responsive: monarch.png -> monarch-1000.jpeg
[10:30:54] gulp-responsive: monarch.png -> monarch-400.webp
[10:30:54] gulp-responsive: monarch.png -> monarch-800.webp
[10:30:54] gulp-responsive: monarch.png -> monarch-1000.webp
[10:30:54] gulp-responsive: Created 6 images (matched 1 of 1 image)
[10:30:54] Finished 'default' after 374 ms

وبالطبع، ننصحك بفحص النتائج بعناية بحثًا عن أدوات ضغط مرئية، أو ربما زيادة الضغط لتوفير مزيد من التوفير. ولأنّ هذه المهمة لا تؤدّي إلى إيقاف الاستخدام، يمكن تغيير هذه الإعدادات بسهولة.

وبالمقابل، مقابل عدد قليل من الكيلوبايت الذي يمكنك الاستفادة منه من خلال التحسين الدقيق اليدوي الدقيق، ستحصل على عملية ليست فعّالة فحسب، بل مرنة أيضًا، وهي أداة تطبّق بسلاسة معرفتك بمواد عرض الصور العالية الأداء على مشروع بأكمله، بدون أي تدخّل يدوي.

الترميز العملي للصور المتجاوبة مع مختلف الأجهزة

عادةً ما تكون تعبئة سمات srcset عملية يدوية مباشرة، لأنّ السمة لا تسجّل سوى معلومات حول الإعدادات التي سبق أن نفّذتها عند إنشاء مصادرك. في المهام أعلاه، أنشأنا أسماء الملفات ومعلومات العرض التي ستتبعها السمة:

srcset="filename-1000.jpg 1000w, filename-800.jpg 800w, filename-400.jpg 400w"

يُرجى العِلم أنّ محتوى السمة srcset وصفي وليس إلزاميًا. ما مِن ضرر في التحميل الزائد لسمة srcset، شرط أن تكون نسبة العرض إلى الارتفاع لكلّ مصدر متسقة. يمكن أن تحتوي السمة srcset على معرّف الموارد المنتظم (URI) وعرض كل عملية قطع بديلة ينشئها الخادم بدون إرسال أي طلبات غير ضرورية، وكلما زاد عدد المصادر المرشحة للصورة المعروضة، تمكّن المتصفح من تخصيص الطلبات بفعالية أكبر.

كما تعلّمت في الصور المتجاوبة مع مختلف الأجهزة، سيكون عليك استخدام العنصر <picture> للتعامل بسلاسة مع النمط الاحتياطي WebP أو JPEG. في هذه الحالة، ستستخدم السمة type بالتنسيق مع السمة srcset.

<picture>
  <source type="image/webp" srcset="filename-1000.webp 1000w, filename-800.webp 800w, filename-400.webp 400w">
  <img srcset="filename-1000.jpg 1000w, filename-800.jpg 800w, filename-400.jpg 400w" sizes="…" alt="…">
</picture>

كما تعلّمت، ستتعرّف المتصفحات التي تتيح تنسيق WebP على محتوى السمة type وتختار السمة srcset في عنصر <source> هذه كقائمة صور مرشحة. المتصفّحات التي لا تتعرّف على image/webp كنوع وسائط صالح ستتجاهل <source> هذا وستستخدم بدلاً من ذلك سمة srcset للعنصر <img> الداخلي.

وهناك اعتبار إضافي بخصوص التوافق مع المتصفّح: ستظل المتصفّحات التي لا تتوافق مع أي ترميز للصور المتجاوبة بحاجة إلى عنصر احتياطي، أو قد نواجه خطر ظهور صورة معطّلة في سياقات التصفّح القديمة على وجه التحديد. بما أنّه يتم تجاهل <picture> و<source> وsrcset في هذه المتصفحات، سنحتاج إلى تحديد مصدر تلقائي في سمة src الخاصة بـ <img> الداخلية.

نظرًا لأن تحجيم الصورة لأسفل يكون سلسًا مرئيًا وترميز JPEG مدعوم عالميًا، فإن تنسيق JPEG الأكبر هو خيار معقول.

<picture>
  <source type="image/webp" srcset="filename-1000.webp 1000w, filename-800.webp 800w, filename-400.webp 400w">
  <img src="filename-1000.jpg" srcset="filename-1000.jpg 1000w, filename-800.jpg 800w, filename-400.jpg 400w" sizes="…" alt="…">
</picture>

قد يكون التعامل مع sizes أكثر صعوبة بعض الشيء. كما تعلّمت، إنّ السمة sizes سياقية بالضرورة، فلا يمكنك ملء السمة بدون معرفة حجم المساحة التي تريد أن تشغلها الصورة في التنسيق المعروض. لتقديم الطلبات الممكنة الأكثر كفاءة، يجب أن تكون سمة sizes دقيقة في ترميزنا في الوقت الذي يقدّم فيه المستخدم النهائي تلك الطلبات، قبل وقت طويل من طلب الأنماط التي تحكم تنسيق الصفحة. ولا يمثّل حذف sizes تمامًا انتهاكًا لمواصفات HTML فحسب، بل ينتج عنه سلوك تلقائي يعادل sizes="100vw"، أي إعلام المتصفّح بأنّ هذه الصورة مقيَّدة بإطار العرض نفسه فقط، ما يؤدي إلى اختيار أكبر عدد ممكن من المصادر المرشحة.

كما هي الحال مع أيّ من مهام تطوير الويب المعقّدة بشكل خاص، تم إنشاء عدد من الأدوات لتقليل عملية كتابة سمات sizes بخط اليد. إنّ respImageLint هي مقتطف رمز أساسي يهدف إلى فحص سمات sizes للتأكّد من دقتها وتقديم اقتراحات لتحسينها. إنّه يعمل كأداة مرجعية، أي أداة يمكنك تشغيلها في متصفحك أثناء الإشارة إلى الصفحة المعروضة بالكامل والتي تحتوي على عناصر صورك. في السياق الذي يكون لدى المتصفح فيه فهم كامل لتخطيط الصفحة، سيكون لديه أيضًا إدراك تام تقريبًا للمساحة التي من المفترض أن تشغلها الصورة في ذلك التخطيط في كل حجم ممكن لإطار العرض.

تقرير صور متجاوب يعرض عدم تطابق في الحجم/العرض

من المؤكد أنّ أداة تركيب سمات sizes مفيدة للغاية، ولكنّها ذات قيمة أكبر كأداة لإنشاء السمات بالجملة. كما هو معروف، تهدف بنية srcset وsizes إلى تحسين طلبات مواد عرض الصور بطريقة سلسة مرئيًا. وعلى الرغم من أنّ هذه القيمة ليست مطلوبة على الإطلاق، إلا أنّ قيمة العنصر النائب التلقائية لـ sizes الخاصة بـ 100vw تكون معقولة تمامًا أثناء العمل على تنسيق الصفحة في بيئة التطوير المحلية. عند إعداد أنماط التنسيق، سيوفر لك تشغيل respImageLint سمات sizes مخصصة يمكنك نسخها ولصقها في الترميز بمستوى من التفاصيل أكبر بكثير من واحد مكتوب يدويًا:

تقرير صور متجاوب مع سمات مقترَحة

على الرغم من أنّ طلبات الصور التي يبدأها الترميز الذي يعرضه الخادم تحدث بسرعة كبيرة جدًا يتعذّر على JavaScript إنشاء سمة sizes من جهة العميل، لا ينطبق المنطق نفسه إذا تم بدء هذه الطلبات من جهة العميل. على سبيل المثال، يتيح لك مشروع Lazysizes تأجيل طلبات الصور بشكل كامل إلى ما بعد إنشاء التنسيق، ما يسمح لJavaScript بإنشاء قيم sizes لنا، ما يوفّر لنا سهولة كبيرة ويضمن الطلبات الممكنة الأكثر كفاءة للمستخدمين. مع ذلك، تذكَّر أنّ هذا الأسلوب يعني التضحية بموثوقية الترميز الذي يعرضه الخادم وتحسينات السرعة المضمَّنة في المتصفّحات، ولن يكون لبدء هذه الطلبات إلّا بعد عرض الصفحة تأثير سلبي كبير على نتيجة سرعة عرض أكبر جزء من المحتوى على الصفحة (LCP).

إذا كنت تعتمد حاليًا على إطار عمل عرض من جهة العميل، مثل React أو Vue، سيكون لديك ديون ستتحمّله، وفي مثل هذه الحالات، يعني استخدام طريقة Lazysizes أنّه يمكن إزالة سمات sizes بالكامل تقريبًا. الأفضل من ذلك: مع حصول sizes="auto" على إجماع عند تحميل الصور الكسولة وعمليات التنفيذ الأصلية، ستصبح Lazysizes رمزًا متعددًا لسلوك المتصفح الموحّد حديثًا.