एक परफेक्ट Lighthouse स्कोर के पीछे का हर ऑप्टिमाइज़ेशन
मैं अपनी साइट पर लगातार Lighthouse चलाता हूँ। यह हर लोकल रन पर 100 रहता है और Vercel के Real Experience Score में भी 100 रहता है।
ये स्कोर किसी सामान्य चेकलिस्ट से नहीं आते। मैं काम को ब्राउज़र से हटाकर बिल्ड स्टेज (build stage) पर ले जाकर इन्हें हासिल करता हूँ।
मैं इसे ठीक इसी तरह करता हूँ।
काम को बिल्ड टाइम (build time) पर ले जाएँ
ज़्यादातर गाइड्स आपको सब कुछ lazy-load करने के लिए कहती हैं। मैं prerender करना पसंद करता हूँ। मैं prerendering इनेबल करने के साथ TanStack Start का उपयोग करता हूँ।
यह बिल्ड के दौरान पूरी साइट को static HTML में बदल देता है। ब्राउज़र को सिर्फ पहला पेज दिखाने के लिए भारी JavaScript चलाने की ज़रूरत नहीं पड़ती। जब यूज़र एंटर दबाता है, तो HTML पहले से ही मौजूद होता है।
जटिल लॉजिक को प्रीकंप्यूट (Precompute) करें
मेरे होमपेज पर 5,000 डॉट्स वाला एक वर्ल्ड मैप है। आमतौर पर, एक लाइब्रेरी GeoJSON को पार्स करेगी और मेन थ्रेड (main thread) पर गणितीय गणना (math) करेगी। यह पेज को 1,000ms के लिए ब्लॉक कर देता है।
मैंने इस गणितीय गणना को बिल्ड स्क्रिप्ट में ले जाकर इस समस्या को हल किया।
- मैं सभी 5,000 डॉट्स के लिए एक सिंगल SVG path स्ट्रिंग जनरेट करता हूँ।
- ब्राउज़र के लिए 5,000 अलग-अलग सर्कल्स को रेंडर करने की तुलना में एक सिंगल पाथ को रेंडर करना बहुत तेज़ होता है।
- मैं कोऑर्डिनेट लुकअप टेबल (coordinate lookup tables) को प्री-कैलकुलेट करता हूँ ताकि रनटाइम पर ब्राउज़र को कोई गणित न करना पड़े।
1,000ms का विलंब (delay) एक सिंगल, इंस्टेंट पेंट (instant paint) में बदल जाता है।
फ़ॉन्ट लोडिंग को ऑप्टिमाइज़ करें
मैं अपने प्राइमरी फ़ॉन्ट्स के लिए rel="preload" का उपयोग करता हूँ।
एक आम गलती crossOrigin एट्रिब्यूट को भूल जाना है। यदि आप इसे छोड़ देते हैं, तो ब्राउज़र फ़ॉन्ट को दो बार फेच करता है। यह आपके Largest Contentful Paint (LCP) को खराब कर देता है। मैं केवल उन्हीं तीन फ़ॉन्ट्स को प्रीलोड करता हूँ जिनका उपयोग 'above the fold' (स्क्रीन के ऊपरी हिस्से) में किया जाता है।
एनिमेशन के लिए सही टूल्स का उपयोग करें
मैं अपने मैप मार्कर्स पर सिंपल पल्स एनिमेशन के लिए SMIL का उपयोग करता हूँ। एनिमेशन लूप चलाने के लिए React state का उपयोग करने की तुलना में यह अधिक किफायती (cheaper) है। यह ब्राउज़र को कंपोजिटर थ्रेड (compositor thread) पर काम संभालने की अनुमति देता है।
जटिल पाथ के लिए, मैं motion का उपयोग करता हूँ। मैं इसे सरल रखता हूँ। मैं माउंट (mount) होने पर एक बार एनिमेट करता हूँ और स्क्रॉल पोजीशन को सुनने (listening) से बचता हूँ।
वेक्टर्स और WebP का ही उपयोग करें
यदि यह कोई लोगो या शेप है, तो SVG का उपयोग करें। यदि यह कोई फोटो है, तो WebP का उपयोग करें। इससे फ़ाइल का साइज़ कम रहता है और लेआउट शिफ्ट (layout shifts) से बचाव होता है।
ओवर-इंजीनियरिंग से बचें
मैं इमेज CDN का उपयोग नहीं करता हूँ। मैं जटिल code-splitting का उपयोग नहीं करता हूँ। मेरी साइट छोटी है, इसलिए route-level splitting ही काफी है।
एक परफेक्ट स्कोर केवल एक दिखावटी मीट्रिक (vanity metric) हो सकता है। असली लक्ष्य अपने प्रदर्शन को मापना और जितना संभव हो सके काम को यूज़र के डिवाइस से दूर ले जाना है।
मेरा पोर्टफोलियो: brodin.dev
सोर्स कोड: github.com/NathanBrodin/Portfolio
TanStack Start prerendering: tanstack.com/start
Paper Shaders: shaders.paper.design
पूरा पोस्ट: https://dev.to/nathan-brodin/every-optimization-behind-a-perfect-lighthouse-score-283n
