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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

وفي حين أن هذا سيكون عملاً روتينيًا متكررًا ويستغرق وقتًا طويلاً إذا تم إجراؤه باستخدام برنامج تعديل الصور، فإن مسئولي المهام مثل تم تصميم Gulp لبرمجة هذا النوع من التكرار بشكل مبرمَج. سريع الاستجابة والذي يستخدم 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/'));
}

في حالة المثال أعلاه، كان حجم الصورة الأصلية (monarch.png) أكثر من 3.3 ميغابايت. أكبر ملف تم إنشاؤه بواسطة هذه المهمة (monarch-1000.jpeg) حوالي 150 كيلوبايت. أصغر حجم، monarch-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 وتختار <source>. srcset للعنصر كقائمة مرشحة للصور. المتصفّحات التي لا تتعرّف على image/webp كوسائط صالحة سيتجاهل <source> هذا، وسيستخدم بدلاً من ذلك السمة srcset لعنصر <img> الداخلي.

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

ونظرًا لأن تحجيم الصورة لأسفل يكون سلسًا مرئيًا وأن ترميز 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 التي نقدّمها لك - وهي راحة كبيرة لك، وضمانًا لتقديم أكثر الطلبات الممكنة كفاءةً للمستخدمين. مع ذلك، يُرجى العلم أنّ هذا الأسلوب لا يعني التضحية بموثوقية الترميز المعروض من خلال الخادم والسرعة. التحسينات المدمجة في المتصفحات، ولن يكون لبدء هذه الطلبات سوى بعد عرض الصفحة حجماً كبيرًا تأثير سلبي في نتيجة سرعة عرض أكبر محتوى مرئي

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