...
UI/UX
Pillars of Next.js Optimizations
15 min read
Let’sstartwithimageoptimizations.NextjshasitsownImagecomponentthatmanagestheloadingandrenderingoftheimageonitsown.Evenifitisusedinaservercomponent,thisimagecomponentcanbelazilyloadedandrenderedontheclientside.Butthisdoesnotcauseanycumulativelayoutshifts.Ittakescareofthat.Thatlayoutshiftispreventedusingthewidthandheightyouprovideaspropstothiscomponent.Youcanseethatinthisblogaswellifyouthrottlethenetworksettings.Forsrc,ifit'sanimagehostedatanyremotebucketthenyoushoulduseremotePatternsinnextjsconfigfiletoavoidtheexternaldomainerror.Forrelativepaths,youcanuselocalPatterns.Thisisnotanoptimizationbutjustacodepattern.
blurDataUrlexpectsabase64urlstringofanimagethatislessthan10by10pixelsandwhenclubbedwithblurplaceholder,itshowsablurredplaceholderimagewhiletheactualsrcimageisbeingpaintedonthescreen.Ifyouwanttouseacustomcomponentasaloader,youcanevenusethatandspecifytheloaderkeyoftheimageinnextjsconfigfile.Ifwegointothenextjsconfigpropertiesforimage,therearealotofthingsthatwecancontrollikesizeofimagesfordifferentviewports,formatsofimageallowed.
Thencomestheconceptofprefetching.It’sachievedthroughtheLinkcomponent.Thiscomponentisanalternativetohtmlanchortag.Ifyourpagehassomeinapplinks/routes,youcanchoosetoprefetchtheirrespectivejsbeforehand.Ittakesabooleanvalueforprefetchprop.Iftrue,asthepagethatusesitispainted,itwillfetchallthecompiledjsofthepagethatthislinkisreferringto.Youwillseethedifferenceintheloadtimes.
Thesecallsweremadewhilebeingonthelandingpageandnotclickinganyofthoselinks.Youcanonlycheckthisonyourdeployedlink,yourlocaldevserverwon’tbeshowingyouthesecallsevenifyouspecifytrueasitsvalue.Noticehowitsays_rscwhichstandsforreactservercomponent.Sinceallthesepagesarestaticpages,thewholeRSCpayloadofthatrouteisfetched.Inessenceyouarejustdecidingwhetheryoucanaffordtokeepthelatencyaddedbythesecallsintheroutenavigation.
Ifnot,youcanprefetchthem.Butthisisacaseofasimplestaticpage.Whenthereisapagewhichhasserverrenderedcomponentsusingapicallsandsomeclientcomponents,justrelyingonprefetchingdoesnotreducetheresponsiveness.Onereasonbeing,fordynamicroutes,thewholeRSCpayloadisnotprefetched.Anotherreasonbeing,evenifitis,providedyouareusingtheloadingfile,duetothelargenumberofcomponentsandlibrariesimportsusedinit,itsjschunkgetsrelativelybiggerandthereyouhavetomakeuseofcodesplitting.

Whenitcomestocaching,ifit’saclientcomponentwhereyouaremakingformsubmissionapicalls,inthatcaseeverythingishydratedandexecutedinthebrowser.Butifit’sadynamicservercomponentandisconsumingdatathroughanAPI,thenyoucanspecifythecachetypeinthefetchcallandaccordinglynotjusttheAPIcallbutalsothecomponent’srenderingcanbecachedornot.
Thecachingcanbefurthercontrolledbyspecifyingtherevalidationintervalincaseofcaching.Withthis,ifthecacheisfoundtobestale,thenitwillrevalidate.Usingthis,wecanspeeduptherenderingofthepageifsomeofitscomponentscanbecachedforalongerduration.Ifyouwishtoemulatethesecachingscenariosyouwillhavetousethedeployedbuild,thelocaldevserverdoesnotusecachingbecauseit’sfordevelopmentwhereweexpectittoreflectthelatestchangesandcachinggoesagainstthehotreloadmodule.
I’llshowyouthedifferenceinresponsesforthetwoopposingvalues.Oneisno-storeandtheotherisforcecache.
IcanidentifythedifferencesbasedontheresponseheadersandthefetchedAtvaluethatwillbeshownonUI.Takeforexample“force-cache”value.
Theexpectationisthatuponrepeatedre-loads,theresponseheadershouldreflectthisdirectiveandthefetchedAtvalueshouldbethesameforthoseconsecutivereloads.
aspublicwhichwillallowthiscontenttobestoredincacheandsubsequentrequestswillhitthecachestoredbyNextJS.Inessence,thispageisnowbehavinglikeastaticallyrenderedpage.
EachcallhadadifferentorlatestfetchedAttimewhichmeanseachcallwasbeingrevalidatedfromtheremoteserver.Now,thisisadynamicallyrenderedpage.
CachingcantakeplaceeitherontheclientorintheNextJSserver.BydefaultthestaticallyrenderedpagesarecachedentirelyinthefullroutecacheofNextjsserver.Whereaswhenyouenableprefetching,thoseprefetchedroutesusetheroutercacheofthebrowsertostorethemasprobablefutureroutesthatmightbevisitedforquickernavigation.Dynamicservercomponentslikediscussedabovecannotusefullroutecacheinsteadtheyrelyonthedatacacheforthecachingofapicallsusedbythem.
Whatiftherearemultiplecomponentswithmultiplefetchcallsandsomeofthemareusingdifferentcachingmechanisms?Inthatcase,thedistinctionarisesbetweenroutecache,datacacheandrequestmemoization.Ifthisservercomponentsharedabovewasonlyapartoftheentireroute,thenonlytherequestwouldhavebeenacachehitinthedatacacheandbasedontherestofthecomponenttreegettingusedonthispage,theentirepage’scachecontrolwouldhavebeendecidedbyreferringtotheroutecache.Regardlessofwhatcachetypeisspecifiedinthefetchrequest,ifasamecallismadeduringthesamerendercycle,thenthememoizedrequestisusedinsteadofmakingaduplicaterequestagain.
I’vetakenanotherscenariowhereinthesamepage
EachhasitsownfetchcallandafetchedAttime.Onehasalistofimagesandtheotherhasalistoftextitems,bothfetchingthatdatafromtheirrespectiveapis.

Again,thisonlyworksifthe
ofasmallimage.FortheAPIcallsIhavenotyetdefinedanycachetype.Uponloadingthepage,bydefault,nextjsreturnsthecachedpagesuponre-loadingthispage.ThisIcantellbythefetchedAtvalueofeachcomponent.It’sthesameaftereveryrefresh.UponremovingthecacheforimagesAPI,theentirepagebecomesdynamicandeveryloadrequestsanewlyrenderedpage.Evenafterspecifyingforce-cacheforthetextcomponent’sAPI,thewholepagestillbehavesdynamicallyandthecachecontrolofhtmlreturnedinresponseisprivate,no-store,no-cachebecauseitisconsolidatingthecachedirectivesofboththecomponentsbeingusedonthisroute.
AnotherwaytoachievecachinginapprouterisusingthetimebasedISRbyexporting
Whenused,itkeptreturningmethecachedpagebutafterrevalidatingatthisinterval,itwouldreturnthepagewithfreshdata.Thisistheroutelevelrevalidation,soitworksforstaticcomponentbutfordynamiccomponentitwillnotrevalidatetheentirehtmlinsteadIcanspecifyanAPIlevelrevalidationusing
torevalidatethedatabeingfetchedinsidethatdynamiccomponent