الأمان والأداء

تحسين الصور والوسائط

20 دقيقة الدرس 18 من 35

تحسين الصور والوسائط

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

تنسيقات الصور الحديثة

توفر تنسيقات الجيل التالي ضغطًا فائقًا:

<!-- التحسين التدريجي مع الاحتياطيات -->
<picture>
<source srcset="image.avif" type="image/avif">
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" alt="الوصف" loading="lazy">
</picture>

<!-- مقارنة التنسيقات (نفس الجودة) -->
JPEG: 100 كيلوبايت
PNG: 150 كيلوبايت
WebP: 40 كيلوبايت (أصغر بنسبة 60٪ من JPEG)
AVIF: 25 كيلوبايت (أصغر بنسبة 75٪ من JPEG)
ملاحظة: WebP لديه دعم 96٪ للمتصفحات (2024). AVIF لديه دعم 85٪ ويوفر ضغطًا أفضل. قدم دائمًا احتياطيات JPEG/PNG للمتصفحات القديمة.

فوائد WebP و AVIF

/* مزايا WebP */
- أصغر بنسبة 25-35٪ من JPEG بنفس الجودة
- يدعم الشفافية (مثل PNG)
- يدعم الرسوم المتحركة (مثل GIF)
- ضغط فاقد وغير فاقد

/* مزايا AVIF */
- أصغر بنسبة 50٪ من JPEG بنفس الجودة
- خوارزمية ضغط فائقة (AV1)
- دقة ألوان أفضل
- دعم HDR

/* الكشف عن دعم المتصفح */
function supportsWebP() {
const canvas = document.createElement('canvas');
if (canvas.getContext && canvas.getContext('2d')) {
return canvas.toDataURL('image/webp').indexOf('data:image/webp') === 0;
}
return false;
}

// الكشف من جانب الخادم (Accept header)
Accept: image/avif,image/webp,image/apng,image/*,*/*;q=0.8

الصور المتجاوبة

قدّم صورًا بحجم مناسب لأجهزة مختلفة:

<!-- تبديل الدقة مع srcset -->
<img
src="image-800.jpg"
srcset="image-400.jpg 400w,
image-800.jpg 800w,
image-1200.jpg 1200w,
image-1600.jpg 1600w"
sizes="(max-width: 600px) 100vw,
(max-width: 1200px) 50vw,
33vw"
alt="صورة متجاوبة"
loading="lazy">

<!-- توجيه فني مع picture -->
<picture>
<source media="(min-width: 1200px)" srcset="hero-desktop.jpg">
<source media="(min-width: 768px)" srcset="hero-tablet.jpg">
<img src="hero-mobile.jpg" alt="صورة البطل">
</picture>

<!-- استهداف نسبة بكسل الجهاز -->
<img
src="image.jpg"
srcset="image.jpg 1x,
image@2x.jpg 2x,
image@3x.jpg 3x"
alt="صورة DPI عالية">
نصيحة: استخدم سمة `sizes` لإخبار المتصفح بحجم عرض الصورة. يسمح له هذا باختيار الصورة الأمثل من `srcset` قبل تحليل CSS، مما يحسن الأداء.

التحميل الكسول للصور

أجّل تحميل الصور خارج الشاشة:

<!-- التحميل الكسول الأصلي (موصى به) -->
<img src="image.jpg" loading="lazy" alt="صورة محملة بشكل كسول">

<!-- التحميل السريع للصور أعلى الصفحة -->
<img src="hero.jpg" loading="eager" alt="صورة البطل">

<!-- احتياطي JavaScript Intersection Observer -->
<img data-src="image.jpg" class="lazy" alt="صورة">

<script>
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.remove('lazy');
observer.unobserve(img);
}
});
});

document.querySelectorAll('img.lazy').forEach(img => {
imageObserver.observe(img);
});
</script>

<!-- عنصر نائب صورة منخفضة الجودة (LQIP) -->
<img
src="tiny-placeholder.jpg"
data-src="full-image.jpg"
class="lazy blur"
alt="صورة مع عنصر نائب">
تحذير: لا تحمّل الصور أعلى الصفحة أو مرشحي LCP (أكبر رسم محتوى) بشكل كسول. يضر هذا بمقاييس Core Web Vitals ويؤخر رؤية المحتوى الحرج.

تقنيات ضغط الصور

/* استراتيجيات الضغط */

1. الضغط الفاقد (JPEG، WebP فاقد)
- يقلل حجم الملف عن طريق إزالة البيانات المرئية
- الجودة 80-85 هي الأمثل (العين البشرية لا تستطيع تمييز الفرق)
- الأدوات: ImageOptim، Squoosh، TinyPNG

2. الضغط غير الفاقد (PNG، WebP غير فاقد)
- يقلل حجم الملف دون فقدان الجودة
- الأفضل للرسومات والشعارات والأيقونات
- الأدوات: OptiPNG، PNGQuant، ImageOptim

3. الضغط المتجاوب
- ضغط أعلى للهاتف المحمول
- ضغط أقل لسطح المكتب/الريتينا

/* التحسين من سطر الأوامر */
// تحسين JPEG
jpegoptim --max=85 --strip-all --all-progressive image.jpg

// تحسين PNG
optipng -o7 image.png
pngquant --quality=65-80 image.png

// تحويل WebP
cwebp -q 80 input.jpg -o output.webp

// تحويل AVIF
avifenc --min 20 --max 25 input.jpg output.avif

تحسين الصور الآلي

// مكون صورة Next.js (التحسين التلقائي)
import Image from 'next/image';

export default function Gallery() {
return (
<Image
src="/photo.jpg"
width={800}
height={600}
alt="صورة"
loading="lazy"
placeholder="blur"
blurDataURL="data:image/jpeg;base64,..."
/>
);
}
// يخدم تلقائيًا WebP/AVIF، يغير الحجم، يحمل بشكل كسول

// تحسين صورة Webpack
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
plugins: [
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminGenerate,
options: {
plugins: [
['imagemin-webp', { quality: 80 }],
['imagemin-mozjpeg', { quality: 85 }],
],
},
},
}),
],
};
ملاحظة: يجب أن يحدث تحسين الصورة في وقت البناء، وليس في وقت التشغيل. استخدم أدوات البناء أو CDN للصور (Cloudinary، Imgix، ImageKit) للتحسين والتسليم التلقائي.

تحسين الفيديو

حسّن تسليم الفيديو للأداء:

<!-- تنسيقات متعددة مع احتياطي -->
<video controls preload="metadata" poster="thumbnail.jpg">
<source src="video.webm" type="video/webm">
<source src="video.mp4" type="video/mp4">
متصفحك لا يدعم الفيديو.
</video>

<!-- التحميل الكسول للفيديو -->
<video preload="none" poster="poster.jpg">
<source data-src="video.mp4" type="video/mp4">
</video>

<script>
const videoObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const video = entry.target;
const source = video.querySelector('source');
source.src = source.dataset.src;
video.load();
videoObserver.unobserve(video);
}
});
});

document.querySelectorAll('video').forEach(video => {
videoObserver.observe(video);
});
</script>

<!-- استبدال GIF بالفيديو -->
<!-- قبل: animated.gif (2 ميجابايت) -->
<img src="animated.gif" alt="رسوم متحركة">

<!-- بعد: video (200 كيلوبايت، أصغر بنسبة 90٪) -->
<video autoplay loop muted playsinline>
<source src="animated.webm" type="video/webm">
<source src="animated.mp4" type="video/mp4">
</video>

أفضل ممارسات ضغط الفيديو

/* استراتيجيات تحسين الفيديو */

1. اختر الترميز المناسب
- H.264 (MP4): أفضل توافق
- VP9 (WebM): ضغط أفضل، دعم 94٪
- AV1: ترميز المستقبل، دعم 72٪، أصغر بنسبة 50٪

2. البث التكيفي لمعدل البت
- تقديم جودات مختلفة بناءً على النطاق الترددي
- استخدام بروتوكولات HLS أو DASH

3. إعدادات الضغط
- CRF (عامل معدل ثابت): 23-28 للويب
- الترميز ذو الممرين للجودة الأفضل
- إزالة الصوت إذا لم يكن مطلوبًا

/* أوامر ضغط FFmpeg */
// التحويل إلى WebM (VP9)
ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 30 -b:v 0 output.webm

// التحويل إلى MP4 (H.264)
ffmpeg -i input.mp4 -c:v libx264 -crf 23 -preset slow output.mp4

// إزالة الصوت
ffmpeg -i input.mp4 -c:v copy -an output.mp4

// تغيير حجم الفيديو
ffmpeg -i input.mp4 -vf scale=1280:-1 output.mp4
نصيحة: استخدم خدمات البث مثل YouTube أو Vimeo أو Cloudflare Stream لمقاطع الفيديو الكبيرة. يتعاملون مع التحسين ومعدل البت التكيفي وتسليم CDN العالمي تلقائيًا.

CDN وخدمات الصور

/* معاملات URL لـ CDN الصور */

// تحويلات Cloudinary
https://res.cloudinary.com/demo/image/upload/
w_800,h_600,c_fill,q_auto,f_auto/sample.jpg
// تنسيق تلقائي، جودة، وتغيير حجم

// معاملات Imgix
https://demo.imgix.net/photo.jpg?
w=800&h=600&fit=crop&auto=format,compress

// تحويلات ImageKit
https://ik.imagekit.io/demo/photo.jpg?
tr=w-800,h-600,fo-auto,q-80

/* فوائد CDN للصور */
- الكشف والتحويل التلقائي للتنسيق
- تغيير الحجم والاقتصاص فوريًا
- الضغط الذكي بناءً على الجهاز
- تسليم CDN العالمي
- تحسين التخزين المؤقت
- تحليلات الصور

مقاييس الأداء

// قياس أداء تحميل الصور
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.initiatorType === 'img') {
console.log('الصورة:', entry.name);
console.log('الحجم:', entry.transferSize, 'بايت');
console.log('المدة:', entry.duration, 'ملي ثانية');
}
}
});
observer.observe({ entryTypes: ['resource'] });

// حساب LCP للصور
const lcpObserver = new PerformanceObserver((list) => {
const entries = list.getEntries();
const lastEntry = entries[entries.length - 1];
console.log('LCP:', lastEntry.renderTime || lastEntry.loadTime);
});
lcpObserver.observe({ entryTypes: ['largest-contentful-paint'] });
تمرين: راجع صور موقعك باستخدام علامة التبويب Network في Chrome DevTools. احسب إجمالي وزن الصور وحدد أكبر الملفات. حوّل 5 صور على الأقل إلى تنسيق WebP/AVIF ونفّذ ترميز الصور المتجاوبة مع srcset. أضف التحميل الكسول الأصلي للصور أسفل الصفحة. استبدل أي ملفات GIF متحركة بعناصر فيديو. قِس التأثير على وزن الصفحة ووقت التحميل باستخدام Lighthouse و WebPageTest.