إطار Next.js

تحسين الصور في Next.js

18 دقيقة الدرس 13 من 40

مقدمة إلى تحسين الصور

غالبًا ما تمثل الصور الجزء الأكبر من حجم صفحة الويب ويمكن أن تؤثر بشكل كبير على أداء التحميل. يوفر Next.js مكون Image قوي يقوم تلقائيًا بتحسين الصور عند الطلب، مما يقلل من أحجام الملفات ويحسن درجات Core Web Vitals. يتعامل مكون next/image مع التحميل الكسول والصور المتجاوبة والتنسيقات الحديثة والمزيد.

ملاحظة: يتطلب مكون Image في Next.js إما Sharp (لوقت تشغيل Node.js) أو تحسين الصور المدمج (لوقت تشغيل Edge). يتم تثبيت Sharp تلقائيًا عند تشغيل npm install، ولكن قد تحتاج إلى تثبيته يدويًا في بعض البيئات.

الاستخدام الأساسي لمكون الصورة

استورد واستخدم مكون Image من next/image:

// app/page.tsx import Image from 'next/image'; export default function Page() { return ( <div> <h1>صورتي</h1> <Image src="/images/hero.jpg" alt="صورة البطل" width={800} height={600} /> </div> ); }

يتطلب مكون Image ثلاث خصائص أساسية: src و alt وإما width/height أو fill. هذه تساعد Next.js على تحسين وعرض الصورة بشكل صحيح.

الصور المحلية

للصور المحلية في دليل public أو المستوردة مباشرة:

// خيار 1: دليل public <Image src="/images/profile.jpg" alt="صورة الملف الشخصي" width={400} height={400} /> // خيار 2: الاستيراد (يحصل تلقائيًا على العرض/الارتفاع) import profilePic from './profile.jpg'; <Image src={profilePic} alt="صورة الملف الشخصي" // يتم توفير العرض والارتفاع تلقائيًا />

الصور البعيدة

للصور المستضافة على نطاقات خارجية، قم بتكوين النطاقات المسموح بها في next.config.js:

// next.config.js module.exports = { images: { remotePatterns: [ { protocol: 'https', hostname: 'images.unsplash.com', port: '', pathname: '/photo-**', }, { protocol: 'https', hostname: 'cdn.example.com', }, ], }, };
// app/page.tsx <Image src="https://images.unsplash.com/photo-1234567890" alt="صورة Unsplash" width={800} height={600} />
تحذير: قم دائمًا بتكوين remotePatterns للصور الخارجية لمنع النطاقات غير المصرح بها من استخدام خدمة تحسين الصور الخاصة بك. هذا يحمي موارد الخادم الخاص بك ويمنع إساءة الاستخدام المحتملة.

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

يدعم مكون Image في Next.js استراتيجيات تحجيم مختلفة:

حجم ثابت (width و height)

<Image src="/images/logo.png" alt="الشعار" width={200} height={100} />

حجم متجاوب (خاصية sizes)

استخدم خاصية sizes لتحديد مقدار المساحة التي تشغلها الصورة في عروض إطارات عرض مختلفة:

<Image src="/images/hero.jpg" alt="صورة البطل" width={1200} height={800} sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw" />

هذا يخبر المتصفح:

  • على الشاشات حتى 768 بكسل: الصورة 100٪ من عرض إطار العرض
  • على الشاشات من 769 بكسل إلى 1200 بكسل: الصورة 50٪ من عرض إطار العرض
  • على الشاشات الأوسع من 1200 بكسل: الصورة 33٪ من عرض إطار العرض

ملء الحاوية (خاصية fill)

استخدم fill عندما لا تعرف أبعاد الصورة أو تريد أن تملأ الصورة حاويتها:

// CSS .image-container { position: relative; width: 100%; height: 400px; } // المكون <div className="image-container"> <Image src="/images/banner.jpg" alt="البانر" fill style={{ objectFit: 'cover' }} /> </div>
نصيحة: عند استخدام fill، يجب أن يحتوي العنصر الأصلي على position: relative أو position: fixed أو position: absolute. سيملأ مكون Image تلقائيًا الحاوية الأصلية بأكملها.

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

التحكم في متى وكيف يتم تحميل الصور:

التحميل الكسول (افتراضي)

يتم تحميل الصور عندما تقترب من إطار العرض:

<Image src="/images/product.jpg" alt="منتج" width={600} height={400} loading="lazy" // السلوك الافتراضي />

التحميل الفوري

قم بتحميل الصور على الفور (استخدم للمحتوى فوق الطية):

<Image src="/images/hero.jpg" alt="البطل" width={1200} height={600} loading="eager" priority // يعادل loading="eager" />

الصور ذات الأولوية

ضع علامة على الصور الحرجة (مثل صور البطل) كأولوية لتحميلها مسبقًا:

<Image src="/images/hero.jpg" alt="البطل" width={1200} height={600} priority />
ملاحظة: استخدم الأولوية بحذر وفقط للصور المرئية فوق الطية. عدد كبير جدًا من الصور ذات الأولوية يمكن أن يضر فعليًا بالأداء من خلال التنافس على النطاق الترددي.

استراتيجيات العنصر النائب

اعرض عناصر نائبة أثناء تحميل الصور:

العنصر النائب الضبابي (تلقائي)

للصور المستوردة، ينشئ Next.js تلقائيًا عناصر نائبة ضبابية:

import heroImage from './hero.jpg'; <Image src={heroImage} alt="البطل" placeholder="blur" // يتم إنشاء blurDataURL تلقائيًا />

عنصر نائب ضبابي مخصص

قدم عنصرًا نائبًا مشفرًا بـ base64 خاصًا بك:

<Image src="/images/photo.jpg" alt="صورة" width={800} height={600} placeholder="blur" blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD..." />

عنصر نائب فارغ

<Image src="/images/photo.jpg" alt="صورة" width={800} height={600} placeholder="empty" />

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

التحكم في جودة الصورة وتحسين التنسيق:

إعداد الجودة

<Image src="/images/photo.jpg" alt="صورة" width={800} height={600} quality={75} // الافتراضي هو 75، النطاق من 1-100 /> // جودة عالية للصور المهمة <Image src="/images/product.jpg" alt="تفاصيل المنتج" width={1000} height={1000} quality={90} />

تحسين التنسيق

يقدم Next.js تلقائيًا التنسيقات الحديثة (WebP، AVIF) عندما يدعمها المتصفح. قم بالتكوين في next.config.js:

// next.config.js module.exports = { images: { formats: ['image/avif', 'image/webp'], // افتراضي }, };

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

أنشئ صورًا متجاوبة تتكيف مع أحجام شاشات مختلفة:

مثال متجاوب كامل

<Image src="/images/hero.jpg" alt="صورة البطل" width={1200} height={675} sizes="(max-width: 640px) 100vw, (max-width: 1024px) 80vw, (max-width: 1280px) 70vw, 60vw" style={{ width: '100%', height: 'auto', }} priority />

متجاوب مع Fill

// وحدة CSS .heroContainer { position: relative; width: 100%; height: 60vh; min-height: 400px; } @media (max-width: 768px) { .heroContainer { height: 40vh; min-height: 300px; } } // المكون <div className={styles.heroContainer}> <Image src="/images/hero.jpg" alt="البطل" fill sizes="100vw" style={{ objectFit: 'cover' }} priority /> </div>

مرجع خصائص مكون الصورة

قائمة كاملة بخصائص مكون Image المهمة:

<Image // الخصائص المطلوبة src="/images/photo.jpg" // سلسلة أو StaticImageData alt="الوصف" // سلسلة (مهم لإمكانية الوصول) // خصائص الحجم (اختر نهجًا واحدًا) width={800} // رقم - العرض الصريح height={600} // رقم - الارتفاع الصريح fill // منطقي - ملء الحاوية الأصلية // خصائص التحميل loading="lazy" // "lazy" | "eager" priority // منطقي - تحميل الصورة مسبقًا // خصائص العنصر النائب placeholder="blur" // "blur" | "empty" blurDataURL="data:..." // سلسلة - صورة مشفرة بـ base64 // الجودة والتحسين quality={75} // رقم (1-100) sizes="100vw" // سلسلة - أحجام متجاوبة // التنسيق style={{ objectFit: 'cover' }} className="image-class" // معالجات الأحداث onLoad={(e) => console.log('تم تحميل الصورة')} onError={(e) => console.log('خطأ في الصورة')} // خصائص أخرى unoptimized={false} // منطقي - تعطيل التحسين />

التكوين المتقدم

قم بتكوين تحسين الصور في next.config.js:

// next.config.js module.exports = { images: { // أحجام الأجهزة للصور المتجاوبة deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840], // أحجام الصور (العرض) لـ srcset imageSizes: [16, 32, 48, 64, 96, 128, 256, 384], // التنسيقات المستخدمة formats: ['image/avif', 'image/webp'], // الأنماط البعيدة (تحل محل النطاقات) remotePatterns: [ { protocol: 'https', hostname: '**.example.com', port: '', pathname: '/images/**', }, ], // الحد الأدنى لوقت التخزين المؤقت بالثواني minimumCacheTTL: 60, // تعطيل تحسين الاستيراد الثابت disableStaticImages: false, // السماح الخطير بـ SVG dangerouslyAllowSVG: true, contentDispositionType: 'attachment', contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;", }, };

مثال معرض الصور

أنشئ معرض صور محسّن:

// app/gallery/page.tsx import Image from 'next/image'; const images = [ { src: '/gallery/1.jpg', alt: 'صورة 1' }, { src: '/gallery/2.jpg', alt: 'صورة 2' }, { src: '/gallery/3.jpg', alt: 'صورة 3' }, { src: '/gallery/4.jpg', alt: 'صورة 4' }, ]; export default function Gallery() { return ( <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4"> {images.map((image, index) => ( <div key={index} className="relative aspect-square"> <Image src={image.src} alt={image.alt} fill sizes="(max-width: 768px) 50vw, (max-width: 1200px) 33vw, 25vw" style={{ objectFit: 'cover' }} className="rounded-lg" /> </div> ))} </div> ); }

أفضل ممارسات الأداء

اتبع هذه الإرشادات للحصول على أداء أمثل للصور:

1. استخدم التنسيقات المناسبة

  • JPEG للصور الفوتوغرافية والصور المعقدة
  • PNG للصور التي تتطلب شفافية
  • SVG للأيقونات والشعارات (مضمّن لـ SVG الصغير)
  • دع Next.js يحول تلقائيًا إلى WebP/AVIF

2. تحسين أبعاد الصورة

// سيء: تقديم صورة 3000x2000 لعرض 300x200 <Image src="/huge-image.jpg" width={300} height={200} /> // جيد: قدم صورة بحجم مناسب <Image src="/optimized-image.jpg" width={300} height={200} />

3. استخدم الأولوية بحكمة

// جيد: الأولوية لبطل فوق الطية <Image src="/hero.jpg" priority /> // سيء: الأولوية للعديد من الصور {products.map(p => ( <Image src={p.image} priority /> // لا تفعل هذا! ))}

4. حدد الأحجام بدقة

// يطابق حجم العرض الفعلي في نقاط التوقف المختلفة <Image src="/responsive.jpg" sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 800px" />

5. استخدم العناصر النائبة الضبابية

import heroImage from './hero.jpg'; <Image src={heroImage} placeholder="blur" // يمنع تحول التخطيط />
تمرين: أنشئ صفحة عرض منتج متجاوبة مع:
  • صورة بطل مع عنصر نائب ضبابي وتحميل ذو أولوية
  • شبكة من 12 صورة منتج مع تحميل كسول
  • تحجيم متجاوب باستخدام خاصية sizes
  • نص بديل مناسب لإمكانية الوصول
  • وظيفة النقر للتكبير (إضافية)
تأكد من التكوين الصحيح للصور البعيدة إذا كنت تستخدم مصادر CDN خارجية.

المزالق الشائعة والحلول

مشكلة: الصور لا تُحسَّن في الإنتاج

الحل: تأكد من تثبيت Sharp وأنك تستخدم منصة استضافة مدعومة:

npm install sharp

مشكلة: الصور البعيدة لا تُحمَّل

الحل: أضف النطاق إلى remotePatterns في next.config.js

مشكلة: تحول التخطيط عند تحميل الصور

الحل: حدد دائمًا width/height أو استخدم fill مع حاوية مناسبة

مشكلة: صور منخفضة الجودة

الحل: زيادة خاصية الجودة (الافتراضي 75، الحد الأقصى 100)

الملخص

يوفر مكون Image في Next.js ميزات تحسين تلقائية قوية. النقاط الرئيسية:

  • استخدم next/image للتحسين التلقائي والتحميل الكسول والصور المتجاوبة
  • حدد width/height أو استخدم fill للتخطيط المناسب
  • قم بتكوين remotePatterns للصور الخارجية
  • استخدم خاصية الأولوية للصور فوق الطية
  • استفد من العناصر النائبة الضبابية لمنع تحول التخطيط
  • استخدم خاصية sizes للصور المتجاوبة
  • قم بتكوين الجودة بناءً على حالة الاستخدام (75-90 لمعظم الحالات)
  • يتم تقديم التنسيقات الحديثة (WebP، AVIF) تلقائيًا عندما تكون مدعومة