كل عملية تحسين وراء الحصول على درجة Lighthouse مثالية
أقوم بتشغيل Lighthouse على موقعي باستمرار. تظل الدرجة 100 في كل مرة أقوم فيها بالتشغيل محلياً، و100 في درجة تجربة المستخدم الحقيقية (Real Experience Score) في Vercel.
هذه الدرجات لا تأتي من قائمة مهام عامة. أنا أحققها من خلال نقل العمل من المتصفح إلى مرحلة البناء (build stage).
إليكم بالضبط كيف أفعل ذلك.
نقل العمل إلى وقت البناء
معظم الأدلة تنصحك باستخدام التحميل المتأخر (lazy-load) لكل شيء. أنا أفضل المعالجة المسبقة (prerender). أستخدم TanStack Start مع تفعيل خاصية الـ prerendering.
هذا يحول الموقع بالكامل إلى HTML ثابت أثناء عملية البناء. لا يضطر المتصفح لتنفيذ JavaScript ثقيل لمجرد عرض الصفحة الأولى. يكون الـ HTML موجوداً بالفعل عندما يضغط المستخدم على Enter.
الحساب المسبق للمنطق المعقد
تحتوي الصفحة الرئيسية لموقعي على خريطة عالم بها 5,000 نقطة. عادةً، تقوم إحدى المكتبات بتحليل GeoJSON وإجراء عمليات حسابية على الخيط الرئيسي (main thread). هذا يؤدي إلى حظر الصفحة لمدة 1,000 مللي ثانية.
حللت هذه المشكلة بنقل العمليات الحسابية إلى نص برمجي للبناء (build script).
- أقوم بإنشاء سلسلة نصية واحدة لـ SVG path لجميع النقاط الـ 5,000.
- مسار واحد أسرع بكثير للمتصفح في عملية الرندرة (render) من 5,000 دائرة منفصلة.
- أقوم بحساب جداول البحث عن الإحداثيات مسبقاً بحيث لا يقوم المتصفح بأي عمليات حسابية أثناء وقت التشغيل (runtime).
التأخير البالغ 1,000 مللي ثانية يتحول إلى عملية رسم (paint) واحدة وفورية.
تحسين تحميل الخطوط
أستخدم rel="preload" لخطوطي الأساسية.
من الأخطاء الشائعة نسيان سمة crossOrigin. إذا تجاهلتها، سيقوم المتصفح بجلب الخط مرتين. هذا يفسد مقياس Largest Contentful Paint (LCP). أنا أقوم بعمل preload للخطوط الثلاثة المستخدمة في الجزء العلوي من الصفحة (above the fold) فقط.
استخدام الأدوات الصحيحة للرسوم المتحركة
أستخدم SMIL لرسوم النبض (pulse) البسيطة على علامات الخريطة. إنها أقل تكلفة من استخدام حالة React (React state) لتشغيل حلقة رسوم متحركة. فهي تتيح للمتصفح التعامل مع العمل على خيط المجمع (compositor thread).
بالنسبة للمسارات المعقدة، أستخدم motion. أحافظ على بساطتها. أقوم بالتحريك مرة واحدة عند التحميل (on mount) وأتجنب الاستماع إلى مواضع التمرير (scroll positions).
الالتزام بالمتجهات و WebP
إذا كان شعاراً أو شكلاً، استخدم SVG. إذا كانت صورة، استخدم WebP. هذا يحافظ على صغر حجم الملف ويمنع تغيرات التخطيط (layout shifts).
تجنب الإفراط في الهندسة (over-engineering)
لا أستخدم CDN للصور. لا أستخدم تقسيم الكود (code-splitting) المعقد. موقعي صغير، لذا فإن التقسيم على مستوى المسار (route-level splitting) كافٍ.
يمكن أن تكون الدرجة المثالية مجرد مقياس للمظاهر (vanity metric). الهدف الحقيقي هو قياس أدائك ونقل أكبر قدر ممكن من العمل بعيداً عن جهاز المستخدم.
معرض أعمالي: brodin.dev
الكود المصدري: github.com/NathanBrodin/Portfolio
المعالجة المسبقة لـ TanStack Start: tanstack.com/start
Paper Shaders: shaders.paper.design
المقال الكامل: https://dev.to/nathan-brodin/every-optimization-behind-a-perfect-lighthouse-score-283n
