Get it on Google Play تحميل تطبيق نبأ للآندرويد مجانا اقرأ على الموقع الرسمي

استخدام صور WebP لتسريع مواقع الويب

وادي التقنية

استخدام صور WebP لتسريع مواقع الويب

استخدام صور WebP لتسريع مواقع الويب

تمهيد

صيغة WebP هي صيغة صور حديثة مفتوحة المصدر ومطوَّرة من Google في عام 2010 بناءً على صيغة الفيديو VP8. منذ ذاك الحين، ازداد عدد مواقع الويب (وتطبيقات الهاتف) التي تستخدم صيغة WebP ازديادًا كبيرًا. يدعم متصفحا Google Chrome و Opera صيغة WebP دون إضافات، وهذان المتصفحات مسؤولان عن عرض 74% تقريبًا من صفحات الويب، مما يضمن أنَّ عددًا كبيرًا من المستخدمين يمكنهم تصفح المواقع بشكل أسرع فيما لو استعملت تلك المواقع صورًا بصيغة WebP؛ يجدر بالذكر أنَّ هنالك خططٌ لإضافة دعم لصيغة WebP في متصفح Firefox.

تدعم صيغة WebP ضغط الصور الفقود (lossy) وغير الفقود (lossless)، وتدعم أيضًا الرسومات المتحركة، لذا يمكنها أن تستبدل صيغة GIF. ميزتها الرئيسية التي تتفوق فيها على صيغة الصور الأخرى هي أنَّ الحجم التخزيني للصورة أقل بكثير، مما يعني أنَّ سرعة تحميل الصور ستكون أكبر، وسيقل تراسل البيانات في الخادم وعند زائر الموقع. ولمّا كانت الصور بصيغة WebP أقل حجمًا بنسبةٍ كبيرة مقارنةً مع صور PNG و JPEG، فإنَّها ستسرِّع تحميل الصفحات بنسبةٍ كبيرة. إذا كان تطبيق الويب أو الموقع الخاص بك يعاني من مشاكل في الأداء أو كان حجم التراسل الشبكي كبيرًا، فتحويل صورك إلى صيغة WebP سيساعدك كثيرًا في تحسين أداء الصفحات.

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

المتطلبات المسبقة

أغلبية الخطوات والأوامر في هذه المقالة تنطبق على جميع توزيعات لينكس، والاختلافات تكون في طريقة تثبيت البرامج وحسب؛ لذا سنعتمد على ذكر طريقة تثبيت الأدوات اللازمة على توزيعة أوبنتو 16.04 و CentOS 7. ما يلزم هو خادم قد ثبتنا عليها إحدى التوزيعتين السابقتين، ومضبوطٌ فيه خادم أباتشي، مع وحدة mod_rewrite، لاحظ أنَّ حزمة أباتشي في توزيعة CentOS 7 تأتي مع دعم mod_rewrite مسبقًا، أما أوبنتو فهي تحتاج إلى تفعيل.

لاحظ أنَّ الغالبية العظمى من الأوامر في هذا الدرس ستعمل على التوزيعات الأخرى دون تعديل.

بعد حصولك على وصول إلى الخادم، وتثبيت أباتشي وتفعيل وحدة mod_rewrite، فيمكنك المتابعة مع هذه المقالة.

الخطوة الأولى: تثبيت cwebp وتهيئة مجلد الصور

سنثبِّت في هذا القسم البرمجات التي سنستخدمها لتحويل الصور، وسنُنشِئ أيضًا مجلدًا وننزِّل فيه صورًا لنختبر الأوامر عليها.

لتثبيت cwebp، البرمجية التي تضغط الصور وتحوِّلها إلى صيغة ‎.webp، فسنستخدم الأمر الآتي:

sudo apt-get install webp 

أما إذا كنتَ تستعمل CentOS 7، فيمكنك استخدام الأمر الآتي بدلًا من الأمر السابق:

sudo yum install libwebp-tools

سنُنشِئ مجلدًا جديدًا في المجلد الجذر لخادم أباتشي (والموجود في المسار ‎/var/www/html) باسم webp:

sudo mkdir /var/www/html/webp

سنغيّر ملكية هذا المجلد إلى المستخدم سامي (sammy، بفرض أنَّ لدينا في النظام مستخدمٌ بذاك الاسم، وإن لم يكن متاحًا فيمكنك إنشاؤه إن أردت، فهو أفضل من ترك الملفات بملكية الجذر [المستخدم root]) وذلك باستخدام الأمر الآتي:

sudo chown sammy: /var/www/html/webp

سنحتاج إلى بعض الصور لتجربة الأوامر عليها، لذا سنُنزِّل صورًا حرةً باستخدام الأمر wget. لاحظ أنَّ هذه الأداة مثبتة افتراضيًا في أوبنتو 16.04، لكن تثبيتها سهلٌ جدًا في CentOS 7:

sudo yum install wget

ملاحظة: لتسهيل متابعة الأوامر الموجودة في هذه المقالة، سنُنزِّل ثلاث صور حرة من الإنترنت، أوّل صورتان منها (Junonia orithya و Mycalesis junonia) مرخصتان برخصة CC BY-SA 4.0 لصاحبها Jee & Rani Nature Photography؛ أما الصورة الأخيرة (Dental Care) فهي مرخصة برخصة CC0.

wget -c "https://upload.wikimedia.org/wikipedia/commons/2/24/Junonia_orithya-Thekkady-2016-12-03-001.jpg?download" -O /var/www/html/webp/image1.jpg
wget -c "https://upload.wikimedia.org/wikipedia/commons/5/54/Mycalesis_junonia-Thekkady.jpg" -O /var/www/html/webp/image2.jpg
wget -c "https://cdn.pixabay.com/photo/2017/07/18/15/39/dental-care-2516133_640.png" -O /var/www/html/webp/logo.png

معظم عملنا سيكون داخل المجلد ‎/var/www/html/webp، لذا سنغيّر مجلد العمل الحالي إليه بكتابة الأمر:

cd /var/www/html/webp

بعد أن ثبتنا خادم أباتشي، وفعّلنا إضافة mod_rewrite، وثبتنا cwebp وبعد أن ضبطنا مجلد التجارب، يمكننا الآن أن نتابع مع الخطوات القادمة.

الخطوة الثانية: ضغط الصور باستخدام cwebp

قبل أن نناقش كيفية تخديم صور ‎.webp إلى زوار موقعنا، علينا أن نُنشِئ نسخًا بهذه الصيغة من الصور الموجودة لدينا حاليًا. يمكننا استخدام الأداة cwebp لتحويل صور JPEG أو PNG أو TIFF إلى صياغة ‎.webp. الصيغة العامة لهذا الأمر تبدو كما يلي:

cwebp image.jpg -o image.webp

يمكن تحديد مسار ملف المخرجات (بصيغة ‎.webp) بعد الخيار ‎-o، لاحظ أنَّ صور WebP تنتهي عادةً باللاحقة ‎.webp.

يمكننا ضبط جودة الصورة ‎-q إلى أيّ قيمة بين 0 و 100؛ وستكون القيمة الافتراضية، إن لم نضبطها، مساويةً إلى 75.

إذا نزّلتَ الصور التي ذكرناها في الخطوة الأولى، فيمكنك تنفيذ الأوامر الآتية لتحويل الصورة image1.jpg إلى image1.webp و image2.jpg إلى image2.webp. تذكّر أن تغيّر مجلد العمل الحالي إلى ‎/var/www/html/webp، ثم نفِّذ الأمر cwebp لتحويل الصور بجودة 100%:

cd /var/www/html/webp
cwebp -q 100 image1.jpg -o image1.webp
cwebp -q 100 image2.jpg -o image2.webp

لنلقِ نظرةً على الحجم التخزيني لملفات JPEG و WebP باستخدام الأمر ls. سنستخدم الخيار ‎-l لعرض الصيغة التفصيلية التي تتضمن حجم الملف التخزيني، والخيار ‎-h الذي يطلب من الأمر ls أن يعرض الحجم بصيغةٍ سهلة القراءة:

ls -lh image1.jpg image1.webp image2.jpg image2.webp

سيُنتِج الأمر السابق الناتج الآتي:

-rw-r--r-- 1 sammy sammy 7.4M Oct 28 23:36 image1.jpg
-rw-r--r-- 1 sammy sammy 3.9M Feb 18 16:46 image1.webp
-rw-r--r-- 1 sammy sammy  16M Dec 18  2016 image2.jpg
-rw-r--r-- 1 sammy sammy 7.0M Feb 18 16:59 image2.webp

يُظهِر ناتج الأمر ls أنَّ حجم الملف image1.jpg هو 7.4 ميغابايت، بينما حجم الملف image1.webp هو 3.9 ميغابايت؛ والمثل ينطبق على ملف image2.jpg (16 ميغابايت) و image2.webp (7.0 ميغابايت). لاحظ أنَّ حجم الملفات قد أصبح نصف ما كان عليه!

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

cwebp -lossless logo.png -o logo.webp

الأمر الآتي يُظهِر أنَّ الحجم التخزيني لصورة WebP هو 60 كيلوبايت، وهو حوالي نصف الحجم التخزيني لصورة PNG (حوالي 116 كيلوبايت).

ls -lh logo.png logo.webp

ناتج الأمر السابق:

-rw-r--r-- 1 sammy sammy 116K Jul 18  2017 logo.png
-rw-r--r-- 1 sammy sammy  60K Feb 18 16:42 logo.webp

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

الخطوة الثالثة: تحويل جميع صور JPEG و PNG في أحد المجلدات

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

أوّل عنصر في السكربت الذي سنكتبه هو الأمر find. يمكنك تعلّم المزيد من المعلومات حول الأمر find من الفصل السابع عشر «البحث عن الملفات» من كتاب «سطر أوامر لينكس». سيبحث الأمر find عن الملفات في المجلد المُحدَّد، وسنستخدم معه بعض الخيارات لمطابقة أسماء تلك الملفات.

لنُنشِئ السكربت باستخدام المحرر النصي المُفضَّل لدينا. سنستخدم هاهنا المحرر nano لكنك تستطيع أن تستعمل أيّ محرر ترتاح معه. سنُنشِئ الملف webp-convert.sh في مجلد ‎/var/www/html/webp:

nano ~/webp-convert.sh

سيبدو أوّل سطر من الملف كما يلي:

find $1 -type f -and \( -iname "*.jpg" -o -iname "*.jpeg" \)

للحصول على مسار المجلد الذي يحتوي على الصور التي نريد تحويلها، فسنستخدم المعامل الموضعي ‎$1. لاحظ أنَّنا سنُمرِّر مسار مجلّد الصور التي نريد تحويلها إلى السكربت من سطر الأوامر، وهنا سيأتي دور المعامل الموضعي السابق. الغرض من استخدامه هو القدرة على تحديد مسار مجلد الصور بغض النظر عن مكان تخزين السكربت.

باستخدامنا للخيار ‎-type f أخبرنا الأمر find أن يبحث عن الملفات العادية فقط (أي أننا لا نريد أن نحصل على مسارات المجلدات في نواتجه). نريد أيضًا أن نُطابِق اسم الملف مع نمطٍ معيّن باستخدام الاختبار ‎-iname. لاحظ أنَّنا استخدمنا اختبارًا غيرَ حساسٍ لحالة الأحرف (وذلك باستخدامنا للاختبار ‎-iname بدلًا من ‎-name)، وهذا الاختبار سيبحث عن أيّة ملفات تنتهي باللاحقة ‎.jpg ‏(‎*.jpg) أو ‎.jpeg ‏(‎*.jpeg). رمز النجمة * هو محرفٌ خاصٌ يُطابِق محرفًا عاديًا صفر مرة أو أكثر. لاحظ أيضًا أنَّنا استخدمنا المعامل المنطقي ‎-o (الذي يعني «أو») لنطلب من الأمر find أن يعرض الملفات التي تُطابِق الاختبار الأول ‎-iname (أي ‎-iname "*.jpg"‎) أو الاختبار الثاني (‎-iname "*.jpeg"‎). وضعنا كلا الاختبارين بين قوسين لنحرص على أنَّ الاختبار الأول (أي ‎-type f) سيُنفَّذ دومًا باستخدام المعامل المنطقي ‎-and.

بعد العثور على الملفات المطلوبة، علينا أن نتخذ إجراءً لتحويلها إلى صيغة WebP. سنفعل ذلك باستخدام المعامل ‎-exec في السطر الثاني من السكربت الذي نعمل عليه (لاحظ أنَّنا استخدمنا الشرطة المائلة الخلفية \ للسماح بامتداد الأمر find على أكثر من سطر). البنية العامة لهذا المعامل هي ‎-exec command {} \;‎. السلسلة النصية {} ستُستبدل بمسار كل ملف يعثر عليه الأمر find (أي أنَّ الأمر المُحدَّد بهذا المعامل سيُنفَّذ على جميع الملفات، كلًا على حدة). استخدمنا ; لنخبر الأمر find أين ينتهي الأمر (لاحظ أنَّنا هربنا [escape] المحرف ; لأنَّ له معنى خاص في الصدفة [shell] ‏bash، وهو الإشارة إلى نهاية الأوامر).

علينا أن نتحقق أولًا من عدم وجود نسخة ‎.webp من الصور وذلك لكل صورة يُعثر الأمر find عليها، وإن لم تكن موجودةً فسنحوِّلها باستخدام الأمر cwebp كما ناقشنا في الخطوة السابقة. السؤال الآن هو ما هو الأمر الذي علينا تنفيذه مع المعامل ‎-exec؟ صراحةً، سنحتاج إلى تنفيذ أكثر من أمر واحد لتحويل الصور إلى ‎.webp. ولهذا السبب، سنستخدم الأمر bash لتنفيذ سكربت صغير الذي سيُنشِئ نسخة ‎.webp من الملف إن لم تكن موجودةً. ولفعل ذلك سنُمرِّر هذا السكربت الصغير كسلسلة نصية (محاطة بعلامتي اقتباس) باستخدام الخيار ‎-c. إلى هذه المرحلة، لقد تضمّن الأمر find المعامل ‎-exec، الذي يُنفِّذ الأمر bash الذي سنُمرِّر إليه سكربتًا صغيرًا (يُمثَّل فيما يلي بالمحتوى النائب `'commands') الذي سيُنفَّذ مجموعة أوامر على ملفات JPEG. يجب أن يبدو الملف الذي نعمل عليه كما يلي في هذه المرحلة:

find $1 -type f -and \( -iname "*.jpg" -o -iname "*.jpeg" \) \
-exec bash -c 'commands' {} \;

أما داخل 'commands' (أي السكربت الموجود بين علامتي اقتباس بعد الخيار ‎-c التابع للأمر bash)، فسنبدأ بتهيئة متغير جديد باسم webp_path للاحتفاظ بمسار ملف WebP الجديد، الذي سنولِّده بتبديل لاحقة الملف المُطابَق من الأمر find (أي ‎.jpg أو ‎.jpeg) باللاحقة ‎.webp. سنستخدم الأمر sed هنا لتبديل الملف لاحقة الملف الأصلي (أي جميع المحارف التي تأتي بعد آخر نقطة . في اسم الملف) باللاحقة ‎.webp. رجاءً ارجع إلى قسم الأمر sed في الفصل العشرين «معالجة النصوص» في كتاب سطر أوامر لينكس لمزيدٍ من المعلومات حوله. المعامل الموضعي ‎$0 سيحمل مسار الملف المُطابَق هنا، وذلك لأنَّنا مررنا مسار كل ملف إلى الأمر bash بوضع السلسلة النصية {} كمعامل له (تذكّر أنَّ الشكل العامل للأمر كان bash -c 'commands' {} \;‎). مرّرنا اسم الملف الناتج إلى مجرى الدخل القياسي للأمر sed باستخدام here string وهي العلامة ‎<<<‎ (راجع الصفحة 411 من كتاب سطر أوامر لينكس للتفاصيل):

webp_path=$(sed 's/\.[^.]*$/.webp/' <<< "$0");

للحفاظ على طاقة المعالجة في الخادم، فسنختبر إن كان هنالك ملفٌ محوّلٌ مسبقًا إلى صيغة WebP، وذلك باستخدام الأمر if. سنختبر ‎[‎ إن لم يكن ! هنالك ملفٌ ‎-f باسم ‎"$webp_path"‎ موجودًا مسبقًا. لاحظ وجود علامتي اقتباس حول اسم الملف لتفادي حدوث مشاكل فيما لو احتوى على فراغات:

if [ ! -f "$webp_path" ]; then 
  # conversion command
fi;

في النهاية، إذا لم يكن الملف موجودًا، فسنستخدم الأمر cwebp لإنشائه، كما فعلنا عند تحويل الصور في مجلد webp في الخطوة السابقة:

cwebp -quiet -q 90 "$0" -o "$webp_path";

ملاحظة: ربما لاحظتَ أنَّ الأمر cwebp يُظهِر الكثير من المخرجات، وقد لا نرغب بها في حال استخدمناه ضمن سكربتات، لذا يمكننا الاستفادة من الخيار ‎-quiet لإخبار الأمر cwebp ألّا يعرض أيّ شيء.

يجب أن يبدو السكربت المستخدم لتحويل صور JPEG كما يلي عند هذه المرحلة:

# converting JPEG images
find $1 -type f -and \( -iname "*.jpg" -o -iname "*.jpeg" \) \
-exec bash -c '
webp_path=$(sed 's/\.[^.]*$/.webp/' <<< "$0");
if [ ! -f "$webp_path" ]; then 
  cwebp -quiet -q 90 "$0" -o "$webp_path";
fi;' {} \;

أما لتحويل صور PNG، فسنستعمل شيئًا شبيهًا جدًا بما فعلناه مع صور JPEG، باستثناء أمرين اثنين: أولهما هو تغيير النمط المستعمل في الأمر find إلى ‎"*.png"‎، وثانيهما هو استعمال الخيار ‎-lossless في الأمر cwebp لتحويل صور PNG بطريقة غير فقودة (كما ناقشنا في الخطوة الثانية).

سيبدو الملف كله كما يلي:

#!/bin/bash

# converting JPEG images
find $1 -type f -and \( -iname "*.jpg" -o -iname "*.jpeg" \) \
-exec bash -c '
webp_path=$(sed 's/\.[^.]*$/.webp/' <<< "$0");
if [ ! -f "$webp_path" ]; then 
  cwebp -quiet -q 90 "$0" -o "$webp_path";
fi;' {} \;

# converting PNG images
find $1 -type f -and -iname "*.png" \
-exec bash -c '
webp_path=$(sed 's/\.[^.]*$/.webp/' <<< "$0");
if [ ! -f "$webp_path" ]; then 
  cwebp -quiet -lossless "$0" -o "$webp_path";
fi;' {} \;

لنختبر الآن السكربت webp-convert.sh، سنستخدم الملفات التي أنشأناها في الخطوة السابقة لتجربته. لكن احرص أولًا على جعل ملف السكربت قابلًا التنفيذ:

chmod a+x ~/webp-convert.sh

لنشغِّل السكربت على المجلد ‎/var/www/html/webp:

./webp-convert.sh /var/www/html/webp

لم يحدث شيء! ذلك لأنَّ السكربت بحث عن وجود نسخة ‎.webp من الصور في المجلد ‎/var/www/html/wepb، لكننا حولناها كلها في الخطوة الثانية من هذا الدرس. علينا إذًا أن نحصل على صورٍ جديدةٍ أو نحذف نسخة ‎.webp. الأمر الآتي سيحذف جميع ملفات ‎.webp الموجودة في المجلد ‎/var/www/html/webp:

rm /var/www/html/webp/*.webp

بعد حذف جميع صور ‎.webp، يمكننا تشغيل السكربت مرةً أخرى للتحقق أنَّه يعمل:

./webp-convert.sh /var/www/html/webp

سيؤكد الأمر ls أنَّ السكربت قد حوّل الصور بنجاح:

ls -lh /var/www/html/webp

الناتج:

-rw-r--r-- 1 sammy sammy 7.4M Oct 28 23:36 image1.jpg
-rw-r--r-- 1 sammy sammy 3.9M Feb 18 16:46 image1.webp
-rw-r--r-- 1 sammy sammy  16M Dec 18  2016 image2.jpg
-rw-r--r-- 1 sammy sammy 7.0M Feb 18 16:59 image2.webp
-rw-r--r-- 1 sammy sammy 116K Jul 18  2017 logo.png
-rw-r--r-- 1 sammy sammy  60K Feb 18 16:42 logo.webp

هذه الخطوة هي أساس استخدام صور WebP في موقعنا، لأننا نحتاج إلى وجود نسخة WebP من جميع الصورة في موقعنا. سننظر في الخطوات القادمة كيف يمكننا الاستفادة من تلك الصور لتسريع مواقع الويب!

الخطوة الرابعة: مراقبة ملفات الصور في أحد المجلدات

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

إحدى المشاكل في سكربت webp-convert.sh هي أننا لا نستطيع أن نعرف أنَّ صورةً ما قد أُعيدَت تسميتها أو حُذِفَت. فمثلًا، لو أنشأنا صورةً باسم foo.jpg وشغّلنا سكربت webp-convert.sh، ثم أعدنا تسمية تلك الصورة إلى bar.jpg وشغّلنا السكربت webp-convert.sh مجددًا، فسينتهي بنا المطاف بوجود ملفي ‎.webp متطابقين (وهما foo.webp و bar.webp). لهل هذه المشكلة، ولتفادي تشغيل السكربت يدويًا، فسنُضيف مراقبات (watchers) التي تراقب ملفاتٍ أو مجلداتٍ معيّنة للتغييرات، وتُشغِّل أوامر ردًا على تلك التغييرات.

يمكننا ضبط تلك المراقبات باستخدام الأمر inotifywait، الذي هو جزءٌ من الحزمة inotify-tools، وهي مجموعةٌ من الأوامر السطرية التي توفِّر واجهةً بسيطةً لنظام inotify في نواة نظام لينكس. يمكننا تثبيت هذه الحزمة في نظام أوبنتو بالأمر الآتي:

sudo apt-get install inotify-tools

أما لتوزيعة CentOS 7، فالحزمة inotify-tools متوافرة في مستودع EPEL. يمكننا تثبيت مستودع EPEL وتثبيت الحزمة inotify-tools باستخدام الأمرين الآتيين:

sudo yum install epel-release
sudo yum install inotify-tools

الأمر inotifywait ينتظر حدوث تغييرات في مجلدٍ معيّن. الخيار ‎-q سيخبر الأمر inotifywait ألّا يخرج الكثير من المخرجات. نرغب أيضًا أن يعمل الأمر inotifywait دون أجلٍ مسمى (‎-m) كيلا ينتهي تنفيذه بعد الحصول على أوّل حدث وقع في المجلد. إضافةً إلى ذلك، نرغب بضبط المراقبات في المجلد المُحدَّد وجميع المجلدات الفرعية التابعة له تعاوديًا باستخدام الخيار ‎-r.

الصيغة التي نريد الحصول عليها عند وقوع تغييرٍ في المجلد هي «اسم الحدث» متبوعًا بمسار الملف، ويمكننا تغيير الصيغة باستخدام الخيار ‎--format. الأحداث التي نريد مراقبتها هي close_write (الذي سيُطلَق عند إنشاء ملف وانتهاء عملية كتابته إلى القرص)، و moved_from و moved_to (التي ستُطلَق عند نقل ملف)، والحدث delete (الذي سيُطلَق عند حذف ملف).

يمكننا إنشاء السكربت بمحررنا النصي المُفضَّل كما فعلنا في الخطوة السابقة مع السكربت webp-convert.sh. الأمر الآتي سيُنشِئ الملف webp-watchers.sh في المجلد ‎/var/www/html/webp:

nano ~/webp-convert.sh

سيبدو أوّل سطرٍ في السكربت كما يلي:

inotifywait -q -m -r --format '%e %w%f' -e close_write -e moved_from -e moved_to -e delete $1

لتفحص ما هي المخرجات التي سيُظهرها هذا الأمر، فنحاول تشغيله في المجلد ‎/var/www/html/webp، مع تشغيله في الخلفية بإضافة الرمز & في نهاية الأمر. سننتقل الآن من تعديل السكربت إلى سطر الأوامر لاختبار سلوك الأمر inotifywait (احرص على حفظ الملف والخروج من المحرِّر):

inotifywait -q -m -r --format '%e %w%f' -e close_write -e moved_from -e moved_to -e delete /var/www/html/webp &

لمعرفة المخرجات التي يُنتِجها الأمر inotifywait، فسنُنشِئ عدِّة ملفات ونجري عمليات عليها. سنُنِشئ أولًا ملفًا جديدًا فارغًا باسم new_file باستخدام الأمر touch. أدخِل الأمر الآتي في سطر الأوامر:

touch /var/www/html/webp/new_file

ثم سنُعيد تسمية الملف (أي ننقله) إلى moved_file باستخدام الأمر mv:

mv /var/www/html/webp/new_file /var/www/html/webp/moved_file

وفي النهاية سنحذف الملف moved_file باستخدام الأمر rm:

rm /var/www/html/webp/moved_file

سنشاهد ناتجًا شبيهًا بالناتج الآتي في الطرفية:

CLOSE_WRITE,CLOSE /var/www/html/webp/new_file
MOVED_FROM /var/www/html/webp/new_file
MOVED_TO /var/www/html/webp/moved_file
DELETE /var/www/html/webp/moved_file

سيظهر أوّل سطر بعد إنشاء الملف الجديد، وسيظهر السطران الثاني والثالث بعد نقل الملف (ويشيران إلى مسار المصدر والوجهة). في النهاية، آخر سطر يُظهِر أنَّ الملف قد حُذِف.

بالعودة إلى أوّل سطر في سكربت webp-watchers.sh، سنستخدم الأمر grep لمعرفة إن كانت الملفات التي أطلقت أحد الأحداث السابقة هي ملفات بصيغة JPEG أو PNG؛ ولمّا كان الأمر inotifywait لا يوفِّر الخيار ‎--include لمراقبة الملفات التي تُطابِق تعبيرًا نمطيًا محدَّدًا، فنحن مجبرون لاستخدام الأمر grep لحلّ التفافي لهذا القصور. أمر grep الآتي سيؤدي إلى مطابقة صور JPEG أو PNG فقط. وسنستخدم فيه الخيار ‎-i لتجاهل حالة الأحرف، والخيار ‎-E لاستخدام التعابير النمطية الموسّعة (extended regular expressions). سنضيف أيضًا الخيار ‎--line-buffered إلى أمر grep لتمرير الأسطر التي جرت مطابقتها إلى حلقة التكرار (التي سنُناقشها بعد قليل):

| grep -i -E '\.(jpe?g|png)$' --line-buffered

أي أنَّ ناتج الأمر inotifywait سيُمرِّر مسار الملفات التي تغيّرت في المجلد المُحدَّد عبر أنبوب (pipe، أي الرمز |) إلى الأمر grep، الذي بدوره سيتحقق إن كان الملف صورةً.

الخطوة الآتية هي بناء حلقة التكرار while. يمكننا الاستفادة من حلقة التكرار while مع الأمر read في حالات مثل حالتنا؛ مما يسمح لنا بمعالجة كل سطر من الأسطر المُمرَّرة إلى الحلقة فور إخراجها. سيُخزِّن الأمر read الحدث في متغيرٍ باسم ‎$operation وسيخزِّن مسار الملف المُعالَج في متغيرٍ باسم ‎$path:

| while read operation path; do
  # commands
done;

لندمج ذلك مع أمر inotifywait الموجود في أوّل سطر من السكربت:

inotifywait -q -m -r --format '%e %w%f' -e close_write -e moved_from -e moved_to -e delete $1 \
| grep -i -E '\.(jpe?g|png)$' --line-buffered \
| while read operation path; do
  # commands
done;

حلقة while ستتحقق من الحدث المُطلَق من الأمر inotifywait، ومن ثم ستجري الأوامر الموجودة داخل الحلقة الأفعال الآتية:

هنالك ثلاثة أقسام رئيسية في حلقة التكرار. أولها هو تعريف متغيرٍ باسم webp_path الذي هيّأناه ليُخزِّن نسخة ‎.webp من الصورة الهدف (أنشأناه بأسلوب مشابه لما فعلناه في الخطوة الثالثة):

webp_path="$(sed 's/\.[^.]*$/.webp/' <<< "$path")";

الخطوة المنطقية التالية هي اختبار الحدث الذي وقع:

if [ $operation = "MOVED_FROM" ] || [ $operation = "DELETE" ]; then
  # commands to be executed if the file is moved or deleted
elif [ $operation = "CLOSE_WRITE,CLOSE" ] || [ $operation = "MOVED_TO" ]; then
  # commands to be executed if a new file is created
fi;

إذا نقلنا أو حذفنا الملف، فسنتحقق من وجود نسخة ‎.webp منه، فإذا كانت موجودةً فسنحذفها باستخدام الأمر rm:

if [ -f "$webp_path" ]; then
  $(rm -f "$webp_path");
fi;

أما بالنسبة إلى الملفات المُنشَأة حديثًا، فسنختبر إن كان الملف بصيغة PNG (باستخدام if و grep كما فعلنا في الخطوة الثالثة). فعلنا لذا سيسمح لنا باستخدام التحويل غير الفقود (عبر الخيار ‎-lossless). إذا لم يكن الملف المُطابَق بصيغة PNG فسنجري تحويلًا فقودًا باستخدام نفس الأمر المذكور في الخطوة الثانية (أي بتحديد جودة الصورة عبر المعامل ‎-q):

if [ $(grep -i '\.png$' <<< "$path") ]; then
  $(cwebp -quiet -lossless "$path" -o "$webp_path");
else
  $(cwebp -quiet -q 90 "$path" -o "$webp_path");
fi;

قد تتساءل لماذا لم ننقل ملف ‎.webp عند نقل الملف الأصلي المرتبط به، ذلك لأننا اتبعنا المنهجية الأسهل: حذف ملف WebP ثم إعادة إنشاءه من الصفر؛ ذلك لأننا لا نريد تعقيد السكربت في حال أضفنا الجزء المسؤول عن نقل نسخة ‎.webp المرتبطة بالملفات الأصلية.

يجب أن يكون كامل ملف webp-watchers.sh كما يلي:

#!/bin/bash
echo "Setting up watches.";

# watch for any created, moved, or deleted image files
inotifywait -q -m -r --format '%e %w%f' -e close_write -e moved_from -e moved_to -e delete $1 \
| grep -i -E '\.(jpe?g|png)$' --line-buffered \
| while read operation path; do
  webp_path="$(sed 's/\.[^.]*$/.webp/' <<< "$path")";
  if [ $operation = "MOVED_FROM" ] || [ $operation = "DELETE" ]; then # if the file is moved or deleted
    if [ -f "$webp_path" ]; then
      $(rm -f "$webp_path");
    fi;
  elif [ $operation = "CLOSE_WRITE,CLOSE" ] || [ $operation = "MOVED_TO" ]; then  # if new file is created
     if [ $(grep -i '\.png$' <<< "$path") ]; then
       $(cwebp -quiet -lossless "$path" -o "$webp_path");
     else
       $(cwebp -quiet -q 90 "$path" -o "$webp_path");
     fi;
  fi;
done;

لا تنسَ أن تجعل السكربت قابلًا للتنفيذ:

chmod a+x ~/webp-convert.sh

يمكننا الآن تشغيل السكربت على المجلد ‎/var/www/html/webp لمراقبته (وجميع المجلدات الفرعية فيه) للتغيرات. ربما ترغب بتشغيل الأمر في الخلفية بإضافة الرمز & في نهاية الأمر:

./webp-watchers.sh /var/www/html/webp

في هذه المرحلة، حوّلنا جميع الصور الموجودة في المجلد ‎/var/www/html/webp إلى صيغة WebP، وضبطنا المراقبات باستعمال سكربت webp-watchers.sh. حان الوقت الآن لاستكشاف خياراتنا بخصوص طريقة تخديم صور WebP إلى زوار مواقعنا.

الخطوة الخامسة: تخديم ملفات WebP إلى الزوار

إذا اتبعتَ التعليمات الموجودة في الخطوات السابقة، فيجب أن تصبح عندك نسخة ‎.webp لكل صورة JPEG أو PNG موجودة في مجلد ‎/var/www/html/webp. يمكننا الآن التفكير بطريقة تخديم تلك الصور إلى المتصفحات الداعمة لها.

سنفعل ذلك بمنهجيتين اثنتين: استخدام عناصر HTML5 (العنصر [](http://wiki.hsoub.com/HTML/picture) تحديدًا)، ووحدة mod_rewrite في خادم الويب أباتشي. سنناقش طريقة استخدام العنصر في هذه الخطوة، وسنُرجئ شرح الوحدة mod_rewrite إلى الخطوة القادمة.

إذا كنتَ مطوِّر (أو صائن) موقعك، فيمكنك استخدام العنصر لتضمين الصور في صفحات الويب في موقعك. يسمح هذا العنصر بتعريف أكثر من مصدر (source) للصورة. وإذا كان المتصفح يدعم صيغة WebP فسيُنزِّل نسخة ‎.webp بدلًا من الصورة الأصلية، مما يُسرِّع تخديم الصفحة. يجدر بالذكر أنَّ العنصر مدعومٌ دعمًا جيدًا في المتصفحات الحديثة التي تدعم صيغة WebP.

العنصر هو حاوية التي تحتوي على عناصر [](http://wiki.hsoub.com/HTML/source) لتحديد «مصدر» مختلف للصورة المُحدَّدة في العنصر [](http://wiki.hsoub.com/HTML/img) المحتوى فيها. إذا استخدمنا العنصر للإشارة إلى صورة ‎.webp، فسينظر المتصفح إن كان قادرًا على تفسير تلك الصفحة، وإن لم يكن قادرًا فسيستعمل الصورة المُحدَّدة في الخاصية src في العنصر .

لنقل أنَّ لدينا صورة PNG باسم logo.png وحولنا إلى logo.webp باستخدام السكربتات السابقة، فيمكننا استخدام شيفرة HTML الآتية لعرض الصورة logo.webp لأي متصفح يدعم صيغة WebP، والصورة logo.png للمتصفحات الأخرى التي لا تدعم صيغة WebP أو لا تدعم العنصر . لنفتح محررنا النصي المُفضَّل ونُنشِئ ملف HTML في المسار ‎/var/www/html/webp/picture.html:

nano /var/www/html/webp/picture.html

سنختصر الصفحة الاختبارية إلى البنية الآتية:


  
  

يمكن استخدام العنصر لتوفير أكثر من نسخة من الصورة، مما يسمح للمتصفح باختيار أكثر صورة ملائمة بينها لعرضها. هذا أبسط خيارٍ متاحٍ أمامنا لتخديم صور ‎.webp.

بعد أن شرحنا كيفية تخديم صور ‎.webp مباشرةً من شيفرة HTML، سننتقل الآن إلى شرح طريقة أتمتة هذه العملية باستخدام وحدة mod_rewrite التابعة لخادم أباتشي.

الخطوة السادسة: تخديم صور WebP باستخدام وحدة mod_rewrite

إذا أردنا تحسين سرعة موقعنا، لكنه يحتوي على عددٍ كبيرٍ من الصفحات أو لدينا وقتٌ وموارد قليلة لتعديل شيفرة HTML، فستساعدنا وحدة mod_rewrite في أتمتة عملية تخديم صور ‎.webp إلى المتصفحات الداعمة لها.

أولًا، علينا اختبار إذا كانت وحدة mod_rewrite متوافرةً، وذلك في ملف ‎.htaccess باستخدام التعليمة ifModule؛ وإذا كانت الوحدة متاحةً فسنُفعِّلها باستخدام التعليمة RewriteEngine On. يمكن إنشاء ملف ‎.htaccess في مجلد ‎/var/www/html/webp باستخدام الأمر الآتي:

nano /var/www/html/webp/.htaccess

الصيغة الأوليّة لملف ‎.htaccess ستكون كما يلي:


  RewriteEngine On 
  # further directives

لكي نعرف متى علينا تخديم صور ‎.webp إلى المستخدم، فيجب أن يجري خادم الويب عدِّة اختبارات. فعندما يجري المتصفح طلبيةً، فسيُضمِّن فيها ترويسةً تُخبِر الخادم ماذا يستطيع المتصفح تشغيله. وفي حالة صور WebP، سيُرسِل الخادم ترويسة Accept التي تحتوي على image/webp. سنتحقق إذا كان المتصفح قد أرسل هذا الترويسة باستخدام التعليمة RewriteCond. التعليمة RewriteCond تُحدِّد المعايير أو الشروط التي يجب أن تُطابَق حتى يُنفَّذ ما في التعليمة RewriteRule. راجع توثيق وحدة mod_rewrite الرسمي لمزيدٍ من المعلومات:

RewriteCond %{HTTP_ACCEPT} image/webp

علينا ترشيح كل الملفات ما عدا صور JPEG و PNG، وذلك باستخدام تعبيرٍ نمطيٍ شبيهٍ بالتعبير المستخدم في الأقسام السابقة، وذلك لمطابقة عنوان URI المطلوب من المتصفح. لاحظ أننا استخدمنا ‎(?i) لجعل عملية المطابقة غير حساسة لحالة الأحرف:

RewriteCond %{REQUEST_URI}  (?i)(.*)(\.jpe?g|\.png)$ 

لتتحقق أنَّ نسخة ‎.webp من الملف موجودة (من البدهي أننا لا نريد تخديم صورة غير موجودة إلى المستخدم)، فيمكننا استخدام تعليمة RewriteCond كما يلي:

RewriteCond %{DOCUMENT_ROOT}%1.webp -f

في النهاية، إذا تحققت كل الشروط السابقة، فسنُعيد توجيه صورة JPEG أو PNG المطلوبة إلى ملف WebP المرتبط بها. لاحظ أننا «نعيد توجيه الملف» (redirect، أي سيُطلَب من المتصفح أن يجري طلبية جديدة لرابط URI جديد يُشير إلى ملف ‎.webp) باستخدام الراية R، ولا «نعيد كتابة رابط URI» ‏(rewrite). الفرق بين إعادة التوجيه وإعادة كتابة رابط URI هي أنَّ المتصفح سيُخدِّم رابط URI الجديد دون إخبار المتصفح بذلك، مما يعني أنَّ الملف المنقول إلى المتصفح هو ‎.webp لكنّه سيبقى مخدّمًا بنفس رابط URI الأصلي. بعبارةٍ أخرى، سيظهر أنَّ رابط URI يُشير إلى ملف ‎.png (على سبيل المثال)، لكنه في الحقيقة ملف ‎.webp:

RewriteRule (?i)(.*)(\.jpe?g|\.png)$ %1\.webp [L,T=image/webp,R] 

عند هذه المرحلة، أنهينا قسم mod_rewrite في ملف ‎.htaccess، لكن ماذا سيحدث لو كان هنالك خادم تخزين مؤقت بين خادمنا وجهاز المستخدم؟ قد يؤدي ذلك إلى تخديم النسخة الخطأ من الملف إلى الزائر، ولهذا السبب علينا أن نتحقق إذا كانت الوحدة mod_headers مفعّلةً، وذلك لإرسال ترويسة Vary: Accept. الترويسة Vary تُخبر الخوادم الوسيطة (proxy servers) أنَّ نوع المحتوى للمستند (أي MIME type. بعبارةٍ أخرى: صيغة الملف المُخدَّم) تختلف (Vary) اعتمادًا على قدرات المتصفح الذي طلب الملف. إضافةً إلى ذلك، إنَّ المحتوى المُخدَّم إلى الزائر قد وُلِّد اعتمادًا على ترويسة Accept الموجودة في الطلبية. فطلبيةٌ أخرى لها ترويسة Accept مختلفة قد تحصل على ناتج آخر. لاحظ أنَّ إرسال هذه الترويسة هو أمرٌ ضروري لمنع الخوادم الوسيطة من تخديم صور WebP إلى المتصفحات غير الداعمة لها:


  Header append Vary Accept env=REDIRECT_accept

في نهاية ملف ‎.htaccess، سنضبط نوع MIME لملفات ‎.webp إلى image/webp باستخدام التعليمة AddType. فعلنا ذلك لتخديم الصور باستخدام نوع MIME الصحيح:

AddType image/webp .webp

هذه هي النسخة النهائية من ملف ‎.htaccess:


  RewriteEngine On 
  RewriteCond %{HTTP_ACCEPT} image/webp
  RewriteCond %{REQUEST_URI}  (?i)(.*)(\.jpe?g|\.png)$ 
  RewriteCond %{DOCUMENT_ROOT}%1.webp -f
  RewriteRule (?i)(.*)(\.jpe?g|\.png)$ %1\.webp [L,T=image/webp,R] 



  Header append Vary Accept env=REDIRECT_accept


AddType image/webp .webp

ملاحظة: لاحظ أنَّك تستطيع دمج ملف ‎.htaccess السابقة مع الملف الموجود مسبقًا عندك. فلو كنتَ تستخدم ووردبريس مثلًا، فيمكنك نسخ ملف ‎.htaccess السابق ولصقه في بداية الملف الموجود عندك.

لنجرِّب ما فعلناه في هذه الخطوة. لو اتبعنا الخطوات السابقة، فيجب أن يكون لدينا ملف باسم logo.png و logo.webp في مجلد ‎/var/www/html/webp. لنجرِّب استخدام عنصر بسيط لتضمين صورة الشعار logo.png في صفحة الويب. يمكننا إنشاء ملف HTML تجريبي مثلما فعلنا في الخطوة السابقة:

nano /var/www/html/webp/img.html

أدخِل شيفرة HTML في ملف ‎/var/www/html/webp/img.html:


عندما تزو صفحة الويب السابقة باستخدام متصفح Chrome بزيارة الرابط http://example.com/webp/img.html فستلاحظ أنَّ الصورة المُخدَّمة هي نسخة ‎.webp من الشعار (جرِّب مثلًا فتح الصورة في لسانٍ جديد)؛ أما إذا كنتَ تستخدم Firefox فستحصل على نسخة ‎.png تلقائيًا.

الخلاصة

تعلمنا في هذه المقالة عن كيفية استخدام صيغة صور WebP لجعل تحميل صفحات الويب أسرع، وشرحنا كيفية استخدام الأداة cwebp لتحويل الملفات. أوّل طريقة استعملناها لتخديم الملفات هي عبر عنصر ، أما الخطوة الثانية فكانت باستعمال وحدة mod_rewrite في أباتشي.

ما شرحناه في هذا الدرس كافٍ لتحقيق هدف تسريع الموقع باستخدام صور WebP، لكن يمكنك تخصيص السكربتات لتناسب احتياجاتك. ننصحك بأخذ وقتك لتصفح المراجع الآتية:

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

مصدر هذه المقالة هو مقالة How To Create and Serve WebP Images to Speed Up Your Website المنشورة في DitgitalOcean والتي كتبها عبد اللطيف ايمش.

admin السبت, 2018/04/14 - 2:40م
disqus

April 14th 2018, 7:16 am
اقرأ على الموقع الرسمي

0 comments
Write a comment
Get it on Google Play تحميل تطبيق نبأ للآندرويد مجانا