ഒരു മികച്ച Lighthouse സ്കോറിന് പിന്നിലെ ഓരോ ഒപ്റ്റിമൈസേഷനും
ഞാൻ എന്റെ സൈറ്റിൽ നിരന്തരം Lighthouse റൺ ചെയ്യാറുണ്ട്. ഓരോ ലോക്കൽ റണ്ണിലും ഇത് 100 ആയി നിൽക്കുന്നു, കൂടാതെ Vercel-ന്റെ Real Experience Score-ലും 100 ആണ്.
ഈ സ്കോറുകൾ വെറുമൊരു ചെക്ക്ലിസ്റ്റ് നോക്കിയുള്ളതല്ല. ബ്രൗസറിൽ ചെയ്യേണ്ട ജോലികൾ ബിൽഡ് സ്റ്റേജിലേക്ക് (build stage) മാറ്റുന്നതിലൂടെയാണ് ഞാൻ ഇത് നേടിയെടുക്കുന്നത്.
ഞാൻ ഇത് കൃത്യമായി എങ്ങനെ ചെയ്യുന്നു എന്ന് താഴെ നൽകുന്നു.
ജോലികൾ ബിൽഡ് സമയത്തേക്ക് മാറ്റുക
മിക്ക ഗൈഡുകളും എല്ലാം lazy-load ചെയ്യാൻ പറയും. എന്നാൽ ഞാൻ prerender ചെയ്യാൻ താല്പര്യപ്പെടുന്നു. ഞാൻ prerendering എനേബിൾ ചെയ്ത TanStack Start ആണ് ഉപയോഗിക്കുന്നത്.
ഇത് ബിൽഡ് സമയത്ത് സൈറ്റിനെ മുഴുവനായി സ്റ്റാറ്റിക് HTML ആക്കി മാറ്റുന്നു. ആദ്യ പേജ് കാണിക്കാൻ വേണ്ടി ബ്രൗസർക്ക് കനത്ത JavaScript പ്രവർത്തിപ്പിക്കേണ്ടി വരുന്നില്ല. ഉപയോക്താവ് എൻ്റർ അടിക്കുമ്പോൾ തന്നെ HTML അവിടെ ലഭ്യമാണ്.
സങ്കീർണ്ണമായ ലോജിക്കുകൾ മുൻകൂട്ടി കണക്കാക്കുക
എന്റെ ഹോംപേജിൽ 5,000 ഡോട്ടുകളുള്ള ഒരു ലോക ഭൂപടമുണ്ട്. സാധാരണയായി, ഒരു ലൈബ്രറി GeoJSON പാഴ്സ് ചെയ്യുകയും മെയിൻ ത്രെഡിൽ (main thread) കണക്കുകൂട്ടലുകൾ നടത്തുകയും ചെയ്യും. ഇത് പേജിനെ 1,000ms നേരത്തേക്ക് ബ്ലോക്ക് ചെയ്യുന്നു.
ഈ കണക്കുകൂട്ടലുകൾ ഒരു ബിൽഡ് സ്ക്രിപ്റ്റിലേക്ക് മാറ്റിക്കൊണ്ട് ഞാൻ ഇത് പരിഹരിച്ചു.
- 5,000 ഡോട്ടുകൾക്കുമായി ഞാൻ ഒരു സിംഗിൾ SVG path string നിർമ്മിക്കുന്നു.
- 5,000 പ്രത്യേക സർക്കിളുകൾ റെൻഡർ ചെയ്യുന്നതിനേക്കാൾ വേഗത്തിൽ ഒരു പാത്ത് (path) റെൻഡർ ചെയ്യാൻ ബ്രൗസിന് സാധിക്കും.
- കോർഡിനേറ്റ് ലുക്കപ്പ് ടേബിളുകൾ (coordinate lookup tables) ഞാൻ മുൻകൂട്ടി കണക്കാക്കുന്നു, അതിനാൽ റൺടൈമിൽ ബ്രൗസിന് യാതൊരു കണക്കുകൂട്ടലുകളും നടത്തേണ്ടി വരുന്നില്ല.
ആ 1,000ms വൈകൽ ഒരു നിമിഷം കൊണ്ട് സംഭവിക്കുന്ന പെയിന്റായി (instant paint) മാറുന്നു.
ഫോണ്ട് ലോഡിംഗ് ഒപ്റ്റിമൈസ് ചെയ്യുക
എന്റെ പ്രൈമറി ഫോണ്ടുകൾക്കായി ഞാൻ rel="preload" ഉപയോഗിക്കുന്നു.
crossOrigin അറ്റ്രിബ്യൂട്ട് മറന്നുപോകുന്നത് ഒരു സാധാരണ തെറ്റാണ്. നിങ്ങൾ ഇത് ഒഴിവാക്കിയാൽ, ബ്രൗസർ ഫോണ്ട് രണ്ടുതവണ ഫെച്ച് ചെയ്യും. ഇത് നിങ്ങളുടെ Largest Contentful Paint (LCP)-നെ ബാധിക്കും. 'Above the fold' ഭാഗത്ത് ഉപയോഗിക്കുന്ന മൂന്ന് ഫോണ്ടുകൾ മാത്രമാണ് ഞാൻ പ്രീലോഡ് ചെയ്യുന്നത്.
ആനിമേഷനായി ശരിയായ ടൂളുകൾ ഉപയോഗിക്കുക
മാപ്പ് മാർക്കറുകളിലെ ലളിതമായ പൾസ് ആനിമേഷനുകൾക്കായി ഞാൻ SMIL ഉപയോഗിക്കുന്നു. ഒരു ആനിമേഷൻ ലൂപ്പ് പ്രവർത്തിപ്പിക്കാൻ React state ഉപയോഗിക്കുന്നതിനേക്കാൾ ലാഭകരമാണിത്. ഇത് ബ്രൗസിനെ കോമ്പോസിറ്റർ ത്രെഡിൽ (compositor thread) ജോലി ചെയ്യാൻ അനുവദിക്കുന്നു.
സങ്കീർണ്ണമായ പാത്തുകൾക്കായി ഞാൻ motion ഉപയോഗിക്കുന്നു. ഞാൻ ഇത് ലളിതമായി വെക്കുന്നു. മൗണ്ട് ചെയ്യുമ്പോൾ (on mount) ഒരിക്കൽ മാത്രം ആനിമേഷൻ നടത്തുകയും സ്ക്രോൾ പൊസിഷനുകൾ ശ്രദ്ധിക്കുന്നത് ഒഴിവാക്കുകയും ചെയ്യുന്നു.
വെക്റ്ററുകളും 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
