table of contents - topidesta.files.wordpress.com · first, the page takes longer to become visible...
TRANSCRIPT
![Page 1: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/1.jpg)
![Page 2: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/2.jpg)
TableofContentsIntroduction
IntroductiontoNext.js
ThemainfeaturesprovidedbyNext.js
Next.jsvsGatsbyvscreate-react-app
HowtoinstallNext.js?
ViewsourcetoconfirmSSRisworking
Theappbundles
What'sthaticononthebottomright?
InstalltheReactDeveloperTools
Otherdebuggingtechniquesyoucanuse
Addingasecondpagetothesite
Linkingthetwopages
Dynamiccontentwiththerouter
Prefetching
Usingtheroutertodetecttheactivelink
Usingnext/router
FeeddatatothecomponentsusinggetInitialProps
CSS
Populatingtheheadtagwithcustomtags
Addingawrappercomponent
APIRoutes
Runcodeonlyontheserversideorclientside
2
![Page 3: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/3.jpg)
Deployingtheproductionversion
DeployingonNow
Analyzingtheappbundles
Lazyloadingmodules
Wheretogofromhere
3
![Page 4: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/4.jpg)
Introduction
Welcome!IwrotethisbooktohelpyouquicklylearnNext.jsandgetfamiliarwithhowitworks.
TheidealreaderofthebookhaszeroknowledgeofNext.js,hasusedReactinthepast,andislookingforwarddivingmoreintotheReactecosystem,inparticularserver-siderendering.
IfindNext.jsanawesometooltocreateWebApplications,andattheendofthebookIhopeyou'llbeasexcitedaboutitasIam.
Thankyouforgettingthisebook.IhopeitwillhelpyoulearnNext.js!
Flavio
[email protected],onTwitter@flaviocopes.
Mywebsiteisflaviocopes.com.
Introduction
4
![Page 5: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/5.jpg)
IntroductiontoNext.jsWorkingonamodernJavaScriptapplicationpoweredbyReactisawesomeuntilyourealizethatthereareacoupleproblemsrelatedtorenderingallthecontentontheclient-side.
First,thepagetakeslongertobecomevisibletotheuser,becausebeforethecontentloads,alltheJavaScriptmustload,andyourapplicationneedstoruntodeterminewhattoshowonthepage.
Second,ifyouarebuildingapubliclyavailablewebsite,youhaveacontentSEOissue.SearchenginesaregettingbetteratrunningandindexingJavaScriptapps,butit'smuchbetterifwecansendthemcontentinsteadoflettingthemfigureitout.
Thesolutiontobothofthoseproblemsisserverrendering,alsocalledstaticpre-rendering.
Next.jsisoneReactframeworktodoallofthisinaverysimpleway,butit'snotlimitedtothis.It'sadvertisedbyitscreatorsasazero-configuration,single-commandtoolchainforReactapps.
ItprovidesacommonstructurethatallowsyoutoeasilybuildafrontendReactapplication,andtransparentlyhandlesserver-siderenderingforyou.
IntroductiontoNext.js
5
![Page 6: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/6.jpg)
ThemainfeaturesprovidedbyNext.jsHereisanon-exhaustivelistofthemainNext.jsfeatures:
HotCodeReloading
Next.jsreloadsthepagewhenitdetectsanychangesavedtodisk.
AutomaticRouting
AnyURLismappedtothefilesystem,tofilesputinthe pagesfolder,andyoudon'tneedanyconfiguration(youhavecustomizationoptionsofcourse).
SingleFileComponents
Using styled-jsx,completelyintegratedasbuiltbythesameteam,it'strivialtoaddstylesscopedtothecomponent.
ServerRendering
YoucanrenderReactcomponentsontheserverside,beforesendingtheHTMLtotheclient.
EcosystemCompatibility
Next.jsplayswellwiththerestoftheJavaScript,Node,andReactecosystem.
ThemainfeaturesprovidedbyNext.js
6
![Page 7: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/7.jpg)
AutomaticCodeSplitting
PagesarerenderedwithjustthelibrariesandJavaScriptthattheyneed,nomore.InsteadofgeneratingonesingleJavaScriptfilecontainingalltheappcode,theappisbrokenupautomaticallybyNext.jsinseveraldifferentresources.
LoadingapageonlyloadstheJavaScriptnecessaryforthatparticularpage.
Next.jsdoesthatbyanalyzingtheresourcesimported.
IfonlyoneofyourpagesimportstheAxioslibrary,forexample,thatspecificpagewillincludethelibraryinitsbundle.
Thisensuresyourfirstpageloadisasfastasitcanbe,andonlyfuturepageloads(iftheywilleverbetriggered)willsendtheJavaScriptneededtotheclient.
Thereisonenotableexception.FrequentlyusedimportsaremovedintothemainJavaScriptbundleiftheyareusedinatleasthalfofthesitepages.
Prefetching
The Linkcomponent,usedtolinktogetherdifferentpages,supportsa prefetchpropwhichautomaticallyprefetchespageresources(includingcodemissingduetocodesplitting)inthebackground.
DynamicComponents
YoucanimportJavaScriptmodulesandReactComponentsdynamically.
ThemainfeaturesprovidedbyNext.js
7
![Page 8: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/8.jpg)
StaticExports
Usingthe nextexportcommand,Next.jsallowsyoutoexportafullystaticsitefromyourapp.
TypeScriptSupport
Next.jsiswritteninTypeScriptandassuchcomeswithanexcellentTypeScriptsupport.
ThemainfeaturesprovidedbyNext.js
8
![Page 9: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/9.jpg)
Next.jsvsGatsbyvscreate-react-appNext.js,Gatsby,and create-react-appareamazingtoolswecanusetopowerourapplications.
Let'sfirstsaywhattheyhaveincommon.TheyallhaveReactunderthehood,poweringtheentiredevelopmentexperience.Theyalsoabstractwebpackandallthoselowlevelthingsthatweusedtoconfiguremanuallyinthegoodolddays.
create-react-appdoesnothelpyougenerateaserver-side-renderedappeasily.Anythingthatcomeswithit(SEO,speed...)isonlyprovidedbytoolslikeNext.jsandGatsby.
WhenisNext.jsbetterthanGatsby?
Theycanbothhelpwithserver-siderendering,butin2differentways.
TheendresultusingGatsbyisastaticsitegenerator,withoutaserver.Youbuildthesite,andthenyoudeploytheresultofthebuildprocessstaticallyonNetlifyoranotherstatichostingsite.
Next.jsprovidesabackendthatcanserversiderenderaresponsetorequest,allowingyoutocreateadynamicwebsite,whichmeansyouwilldeployitonaplatformthatcanrunNode.js.
Next.jscangenerateastaticsitetoo,butIwouldnotsayit'sitsmainusecase.
Next.jsvsGatsbyvscreate-react-app
9
![Page 10: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/10.jpg)
Ifmygoalwastobuildastaticsite,I'dhaveahardtimechoosingandperhapsGatsbyhasabetterecosystemofplugins,includingmanyforblogginginparticular.
GatsbyisalsoheavilybasedonGraphQL,somethingyoumightreallylikeordislikedependingonyouropinionsandneeds.
Next.jsvsGatsbyvscreate-react-app
10
![Page 11: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/11.jpg)
HowtoinstallNext.js?ToinstallNext.js,youneedtohaveNode.jsinstalled.
MakesurethatyouhavethelatestversionofNode.Checkwithrunning node-vinyourterminal,andcompareittothelatestLTSversionlistedonhttps://nodejs.org/.
AfteryouinstallNode.js,youwillhavethe npmcommandavailableintoyourcommandline.
Ifyouhaveanytroubleatthisstage,IrecommendthefollowingtutorialsIwroteforyou:
HowtoinstallNode.jsHowtoupdateNode.jsAnintroductiontothenpmpackagemanagerUnixShellsTutorialHowtousethemacOSterminalTheBashShell
NowthatyouhaveNode,updatedtothelatestversion,and npm,we'reset!
Wecanchoose2routesnow:using create-next-apportheclassicapproachwhichinvolvesinstallingandsettingupaNextappmanually.
Usingcreate-next-app
Ifyou'refamiliarwith create-react-app, create-next-appisthesamething-exceptitcreatesaNextappinsteadofaReactapp,asthenameimplies.
HowtoinstallNext.js?
11
![Page 12: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/12.jpg)
IassumeyouhavealreadyinstalledNode.js,which,fromversion5.2(2+yearsagoatthetimeofwriting),comeswiththe npxcommandbundled.ThishandytoolletsusdownloadandexecuteaJavaScriptcommand,andwe'lluseitlikethis:
npxcreate-next-app
Thecommandaskstheapplicationname(andcreatesanewfolderforyouwiththatname),thendownloadsallthepackagesitneeds( react, react-dom, next),setsthe package.jsonto:
andyoucanimmediatelyrunthesampleappbyrunning npmrundev:
HowtoinstallNext.js?
12
![Page 14: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/14.jpg)
ThisistherecommendedwaytostartaNext.jsapplication,asitgivesyoustructureandsamplecodetoplaywith.There'smorethanjustthatdefaultsampleapplication;youcanuseanyoftheexamplesstoredathttps://github.com/zeit/next.js/tree/canary/examplesusingthe --exampleoption.Forexampletry:
npxcreate-next-app--exampleblog-starter
Whichgivesyouanimmediatelyusablebloginstancewithsyntaxhighlightingtoo:
HowtoinstallNext.js?
14
![Page 15: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/15.jpg)
ManuallycreateaNext.jsapp
Youcanavoid create-next-appifyoufeellikecreatingaNextappfromscratch.Here'show:createanemptyfolderanywhereyoulike,forexampleinyourhomefolder,andgointoit:
mkdirnextjs
cdnextjs
andcreateyourfirstNextprojectdirectory:
mkdirfirstproject
cdfirstproject
HowtoinstallNext.js?
15
![Page 16: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/16.jpg)
Nowusethe npmcommandtoinitializeitasaNodeproject:
npminit-y
The -yoptiontells npmtousethedefaultsettingsforaproject,populatingasample package.jsonfile.
NowinstallNextandReact:
npminstallnextreactreact-dom
Yourprojectfoldershouldnowhave2files:
package.json(seemytutorialonit)package-lock.json(seemytutorialonpackage-lock)
andthe node_modulesfolder.
HowtoinstallNext.js?
16
![Page 17: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/17.jpg)
Opentheprojectfolderusingyourfavoriteeditor.MyfavoriteeditorisVSCode.Ifyouhavethatinstalled,youcanrun code.inyourterminaltoopenthecurrentfolderintheeditor(ifthecommanddoesnotworkforyou,seethis)
Open package.json,whichnowhasthiscontent:
{
"name":"firstproject",
"version":"1.0.0",
"description":"",
"main":"index.js",
"scripts":{
"test":"echo\"Error:notestspecified\"&&exit1"
},
"keywords":[],
"author":"",
"license":"ISC",
"dependencies":{
"next":"^9.1.2",
"react":"^16.11.0",
"react-dom":"^16.11.0"
}
}
andreplacethe scriptssectionwith:
"scripts":{
"dev":"next",
"build":"nextbuild",
"start":"nextstart"
}
toaddtheNext.jsbuildcommands,whichwe'regoingtousesoon.
HowtoinstallNext.js?
17
![Page 18: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/18.jpg)
Tip:use "dev":"next-p3001",tochangetheportandrun,inthisexample,onport3001.
Nowcreatea pagesfolder,andaddan index.jsfile.
Inthisfile,let'screateourfirstReactcomponent.
We'regoingtouseitasthedefaultexport:
constIndex=()=>(
<div>
<h1>Homepage</h1>
</div>
)
exportdefaultIndex
Nowusingtheterminal,run npmrundevtostarttheNextdevelopmentserver.
HowtoinstallNext.js?
18
![Page 19: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/19.jpg)
Thiswillmaketheappavailableonport3000,onlocalhost.
Openhttp://localhost:3000inyourbrowsertoseeit.
HowtoinstallNext.js?
19
![Page 20: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/20.jpg)
HowtoinstallNext.js?
20
![Page 21: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/21.jpg)
ViewsourcetoconfirmSSRisworkingLet'snowchecktheapplicationisworkingasweexpectittowork.It'saNext.jsapp,soitshouldbeserversiderendered.
It'soneofthemainsellingpointsofNext.js:ifwecreateasiteusingNext.js,thesitepagesarerenderedontheserver,whichdeliversHTMLtothebrowser.
Thishas3majorbenefits:
TheclientdoesnotneedtoinstantiateReacttorender,whichmakesthesitefastertoyourusers.Searchengineswillindexthepageswithoutneedingtoruntheclient-sideJavaScript.SomethingGooglestarteddoing,butopenlyadmittedtobeaslowerprocess(andyoushouldhelpGoogleasmuchaspossible,ifyouwanttorankwell).Youcanhavesocialmediametatags,usefultoaddpreviewimages,customizetitleanddescriptionforanyofyourpagessharedonFacebook,Twitterandsoon.
Let'sviewthesourceoftheapp.UsingChromeyoucanright-clickanywhereinthepage,andpressViewPageSource.
ViewsourcetoconfirmSSRisworking
21
![Page 22: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/22.jpg)
Ifyouviewthesourceofthepage,you'llseethe <div><h1>Homepage</h1></div>snippetintheHTML body,alongwithabunchofJavaScriptfiles-theappbundles.
Wedon'tneedtosetupanything,SSR(server-siderendering)isalreadyworkingforus.
TheReactappwillbelaunchedontheclient,andwillbetheonepoweringinteractionslikeclickingalink,usingclient-siderendering.Butreloadingapagewillre-loaditfromtheserver.AndusingNext.jsthereshouldbenodifferenceintheresultinsidethebrowser-aserver-renderedpageshouldlookexactlylikeaclient-renderedpage.
ViewsourcetoconfirmSSRisworking
22
![Page 23: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/23.jpg)
TheappbundlesWhenweviewedthepagesource,wesawabunchofJavaScriptfilesbeingloaded:
Let'sstartbyputtingthecodeinanHTMLformattertogetitformattedbetter,sowehumanscangetabetterchanceatunderstandingit:
<!DOCTYPEhtml>
<html>
<head>
<metacharSet="utf-8"/>
<metaname="viewport"content="width=device-width,minimum-sca
le=1,initial-scale=1"/>
<metaname="next-head-count"content="2"/>
Theappbundles
23
![Page 24: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/24.jpg)
<linkrel="preload"href="/_next/static/development/pages/ind
ex.js?ts=1572863116051"as="script"/>
<linkrel="preload"href="/_next/static/development/pages/_ap
p.js?ts=1572863116051"as="script"/>
<linkrel="preload"href="/_next/static/runtime/webpack.js?ts
=1572863116051"as="script"/>
<linkrel="preload"href="/_next/static/runtime/main.js?ts=15
72863116051"as="script"/>
</head>
<body>
<divid="__next">
<div>
<h1>Homepage</h1></div>
</div>
<scriptsrc="/_next/static/development/dll/dll_01ec57fc9b90d4
3b98a8.js?ts=1572863116051"></script>
<scriptid="__NEXT_DATA__"type="application/json">{"dataMana
ger":"[]","props":{"pageProps":{}},"page":"/","query":{},"buildId"
:"development","nextExport":true,"autoExport":true}</script>
<scriptasync=""data-next-page="/"src="/_next/static/develo
pment/pages/index.js?ts=1572863116051"></script>
<scriptasync=""data-next-page="/_app"src="/_next/static/de
velopment/pages/_app.js?ts=1572863116051"></script>
<scriptsrc="/_next/static/runtime/webpack.js?ts=157286311605
1"async=""></script>
<scriptsrc="/_next/static/runtime/main.js?ts=1572863116051"
async=""></script>
</body>
</html>
Wehave4JavaScriptfilesbeingdeclaredtobepreloadedinthehead,using rel="preload"as="script":
/_next/static/development/pages/index.js(96LOC)/_next/static/development/pages/_app.js(5900LOC)
Theappbundles
24
![Page 25: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/25.jpg)
/_next/static/runtime/webpack.js(939LOC)/_next/static/runtime/main.js(12kLOC)
Thistellsthebrowsertostartloadingthosefilesassoonaspossible,beforethenormalrenderingflowstarts.Withoutthose,scriptswouldbeloadedwithanadditionaldelay,andthisimprovesthepageloadingperformance.
Thenthose4filesareloadedattheendofthe body,alongwith/_next/static/development/dll/dll_01ec57fc9b90d43b98a8.js(31kLOC),andaJSONsnippetthatsetssomedefaultsforthepagedata:
<scriptid="__NEXT_DATA__"type="application/json">
{
"dataManager":"[]",
"props":{
"pageProps":{}
},
"page":"/",
"query":{},
"buildId":"development",
"nextExport":true,
"autoExport":true
}
</script>
The4bundlefilesloadedarealreadyimplementingonefeaturecalledcodesplitting.The index.jsfileprovidesthecodeneededfortheindexcomponent,whichservesthe /route,andifwehadmorepageswe'dhavemorebundlesforeachpage,whichwillthenonlybeloadedifneeded-toprovideamoreperformantloadtimeforthepage.
Theappbundles
25
![Page 26: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/26.jpg)
Theappbundles
26
![Page 27: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/27.jpg)
What'sthaticononthebottomright?Didyouseethatlittleiconatthebottomrightofthepage,whichlookslikealightning?
Ifyouhoverit,it'sgoingtosay"PrerenderedPage":
What'sthaticononthebottomright?
27
![Page 28: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/28.jpg)
Thisicon,whichisonlyvisibleindevelopmentmodeofcourse,tellsyouthepagequalifiesforautomaticstaticoptimization,whichbasicallymeansthatitdoesnotdependondatathatneedstobefetchedatinvokationtime,anditcanbeprerenderedandbuiltasastaticHTMLfileatbuildtime(whenwerun npmrunbuild).
Nextcandeterminethisbytheabsenceofthe getInitialProps()methodattachedtothepagecomponent.
Whenthisisthecase,ourpagecanbeevenfasterbecauseitwillbeservedstaticallyasanHTMLfileratherthangoingthroughtheNode.jsserverthatgeneratestheHTMLoutput.
Anotherusefuliconthatmightappearnexttoit,orinsteadofitonnon-prerenderedpages,isalittleanimatedtriangle:
What'sthaticononthebottomright?
28
![Page 29: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/29.jpg)
Thisisacompilationindicator,andappearswhenyousaveapageandNext.jsiscompilingtheapplicationbeforehotcodereloadingkicksintoreloadthecodeintheapplicationautomatically.
It'sareallynicewaytoimmediatelydetermineiftheapphasalreadybeencompiledandyoucantestapartofityou'reworkingon.
What'sthaticononthebottomright?
29
![Page 30: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/30.jpg)
InstalltheReactDeveloperToolsNext.jsisbasedonReact,sooneveryusefultoolweabsolutelyneedtoinstall(ifyouhaven'talready)istheReactDeveloperTools.
AvailableforbothChromeandFirefox,theReactDeveloperToolsareanessentialinstrumentyoucanusetoinspectaReactapplication.
Now,theReactDeveloperToolsarenotspecifictoNext.jsbutIwanttointroducethembecauseyoumightnotbe100%familiarwithallthetoolsReactprovides.It'sbesttogoalittleintodebuggingtoolingthanassumingyoualreadyknowthem.
TheyprovideaninspectorthatrevealstheReactcomponentstreethatbuildsyourpage,andforeachcomponentyoucangoandchecktheprops,thestate,hooks,andlotsmore.
OnceyouhaveinstalledtheReactDeveloperTools,youcanopentheregularbrowserdevtools(inChrome,it'sright-clickinthepage,thenclick Inspect)andyou'llfind2newpanels:ComponentsandProfiler.
InstalltheReactDeveloperTools
30
![Page 31: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/31.jpg)
Ifyoumovethemouseoverthecomponents,you'llseethatinthepage,thebrowserwillselectthepartsthatarerenderedbythatcomponent.
Ifyouselectanycomponentinthetree,therightpanelwillshowyouareferencetotheparentcomponent,andthepropspassedtoit:
InstalltheReactDeveloperTools
31
![Page 32: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/32.jpg)
Youcaneasilynavigatebyclickingaroundthecomponentnames.
YoucanclicktheeyeiconintheDeveloperToolstoolbartoinspecttheDOMelement,andalsoifyouusethefirsticon,theonewiththemouseicon(whichconvenientlysitsunderthesimilarregularDevToolsicon),youcanhoveranelementinthebrowserUItodirectlyselecttheReactcomponentthatrendersit.
Youcanusethe bugicontologacomponentdatatotheconsole.
InstalltheReactDeveloperTools
32
![Page 33: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/33.jpg)
Thisisprettyawesomebecauseonceyouhavethedataprintedthere,youcanright-clickanyelementandpress"Storeasaglobalvariable".ForexamplehereIdiditwiththe urlprop,andIwasabletoinspectitintheconsoleusingthetemporaryvariableassignedtoit, temp1:
InstalltheReactDeveloperTools
33
![Page 34: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/34.jpg)
UsingSourceMaps,whichareloadedbyNext.jsautomaticallyindevelopmentmode,fromtheComponentspanelwecanclickthe <>codeandtheDevToolswillswitchtotheSourcepanel,showingusthecomponentsourcecode:
InstalltheReactDeveloperTools
34
![Page 35: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/35.jpg)
TheProfilertabisevenmoreawesome,ifpossible.Itallowsustorecordaninteractionintheapp,andseewhathappens.Icannotshowanexampleyet,becauseitneedsatleast2componentstocreateaninteraction,andwehavejustonenow.I'lltalkaboutthislater.
InstalltheReactDeveloperTools
35
![Page 36: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/36.jpg)
IshowedallscreenshotsusingChrome,buttheReactDeveloperToolsworksinthesamewayinFirefox:
InstalltheReactDeveloperTools
36
![Page 37: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/37.jpg)
InstalltheReactDeveloperTools
37
![Page 38: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/38.jpg)
OtherdebuggingtechniquesyoucanuseInadditiontotheReactDeveloperTools,whichareessentialtobuildingaNext.jsapplication,Iwanttoemphasize2waystodebugNext.jsapps.
Thefirstisobviously console.log()andalltheotherConsoleAPItools.ThewayNextappsworkwillmakealogstatementworkinthebrowserconsoleORintheterminalwhereyoustartedNextusing npmrundev.
Inparticular,ifthepageloadsfromtheserver,whenyoupointtheURLtoit,oryouhittherefreshbutton/cmd/ctrl-R,anyconsolelogginghappensintheterminal.
Subsequentpagetransitionsthathappenbyclickingthemousewillmakeallconsolelogginghappeninsidethebrowser.
Justrememberifyouaresurprisedbymissinglogging.
Anothertoolthatisessentialisthe debuggerstatement.Addingthisstatementtoacomponentwillpausethebrowserrenderingthepage:
Otherdebuggingtechniquesyoucanuse
38
![Page 39: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/39.jpg)
Reallyawesomebecausenowyoucanusethebrowserdebuggertoinspectvaluesandrunyourapponelineatatime.
Otherdebuggingtechniquesyoucanuse
39
![Page 40: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/40.jpg)
YoucanalsousetheVSCodedebuggertodebugserver-sidecode.Imentionthistechniqueandthistutorialtosetthisup.
Otherdebuggingtechniquesyoucanuse
40
![Page 41: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/41.jpg)
AddingasecondpagetothesiteNowthatwehaveagoodgraspofthetoolswecanusetohelpusdevelopNext.jsapps,let'scontinuefromwhereweleftourfirstapp:
Iwanttoaddasecondpagetothiswebsite,ablog.It'sgoingtobeservedinto /blog,andforthetimebeingitwilljustcontainasimplestaticpage,justlikeourfirst index.jscomponent:
Addingasecondpagetothesite
41
![Page 42: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/42.jpg)
Aftersavingthenewfile,the npmrundevprocessalreadyrunningisalreadycapableofrenderingthepage,withouttheneedtorestartit.
WhenwehittheURLhttp://localhost:3000/blogwehavethenewpage:
Addingasecondpagetothesite
42
![Page 43: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/43.jpg)
andhere'swhattheterminaltoldus:
Addingasecondpagetothesite
43
![Page 44: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/44.jpg)
NowthefactthattheURLis /blogdependsonjustthefilename,anditspositionunderthe pagesfolder.
Youcancreatea pages/hey/hopage,andthatpagewillshowupontheURLhttp://localhost:3000/hey/ho.
Whatdoesnotmatter,fortheURLpurposes,isthecomponentnameinsidethefile.
Trygoingandviewingthesourceofthepage,whenloadedfromtheserveritwilllist /_next/static/development/pages/blog.jsasoneofthebundlesloaded,andnot/_next/static/development/pages/index.jslikeinthehomepage.Thisisbecausethankstoautomaticcodesplittingwedon'tneedthebundlethatservesthehomepage.Justthebundlethatservestheblogpage.
Wecanalsojustexportananonymousfunctionfrom blog.js:
exportdefault()=>(
<div>
<h1>Blog</h1>
Addingasecondpagetothesite
44
![Page 45: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/45.jpg)
</div>
)
orifyoupreferthenon-arrowfunctionsyntax:
exportdefaultfunction(){
return(
<div>
<h1>Blog</h1>
</div>
)
}
Addingasecondpagetothesite
45
![Page 46: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/46.jpg)
LinkingthetwopagesNowthatwehave2pages,definedby index.jsand blog.js,wecanintroducelinks.
NormalHTMLlinkswithinpagesaredoneusingthe atag:
<ahref="/blog">Blog</a>
Wecan'tdodothatinNext.js.
Why?Wetechnicallycan,ofcourse,becausethisistheWebandontheWebthingsneverbreak(that'swhywecanstillusethe <marquee>tag.ButoneofthemainbenefitsofusingNextisthatonceapageisloaded,transitionstootherpageareveryfastthankstoclient-siderendering.
Ifyouuseaplain alink:
constIndex=()=>(
<div>
<h1>Homepage</h1>
<ahref='/blog'>Blog</a>
</div>
)
exportdefaultIndex
NowopentheDevTools,andtheNetworkpanelinparticular.Thefirsttimeweload http://localhost:3000/wegetallthepagebundlesloaded:
Linkingthetwopages
46
![Page 47: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/47.jpg)
Nowifyouclickthe"Preservelog"button(toavoidclearingtheNetworkpanel),andclickthe"Blog"link,thisiswhathappens:
Linkingthetwopages
47
![Page 48: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/48.jpg)
WegotallthatJavaScriptfromtheserver,again!But..wedon'tneedallthatJavaScriptifwealreadygotit.We'djustneedthe blog.jspagebundle,theonlyonethat'snewtothepage.
Tofixthisproblem,weuseacomponentprovidedbyNext,calledLink.
Weimportit:
importLinkfrom'next/link'
andthenweuseittowrapourlink,likethis:
importLinkfrom'next/link'
Linkingthetwopages
48
![Page 49: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/49.jpg)
constIndex=()=>(
<div>
<h1>Homepage</h1>
<Linkhref='/blog'>
<a>Blog</a>
</Link>
</div>
)
exportdefaultIndex
Nowifyouretrythethingwedidpreviously,you'llbeabletoseethatonlythe blog.jsbundleisloadedwhenwemovetotheblogpage:
Linkingthetwopages
49
![Page 50: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/50.jpg)
andthepageloadedsofasterthanbefore,thebrowserusualspinneronthetabdidn'tevenappear.YettheURLchanged,asyoucansee.ThisisworkingseamlesslywiththebrowserHistoryAPI.
Thisisclient-siderenderinginaction.
Whatifyounowpressthebackbutton?Nothingisbeingloaded,becausethebrowserstillhastheold index.jsbundleinplace,readytoloadthe /indexroute.It'sallautomatic!
Linkingthetwopages
50
![Page 51: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/51.jpg)
DynamiccontentwiththerouterInthepreviouschapterwesawhowtolinkthehometotheblogpage.
AblogisagreatusecaseforNext.js,onewe'llcontinuetoexploreinthischapterbyaddingblogposts.
BlogpostshaveadynamicURL.Forexampleaposttitled"HelloWorld"mighthavetheURL /blog/hello-world.Aposttitled"Mysecondpost"mighthavetheURL /blog/my-second-post.
Thiscontentisdynamic,andmightbetakenfromadatabase,markdownfilesormore.
Next.jscanservedynamiccontentbasedonadynamicURL.
WecreateadynamicURLbycreatingadynamicpagewiththe []syntax.
How?Weadda pages/blog/[id].jsfile.ThisfilewillhandleallthedynamicURLsunderthe /blog/route,liketheoneswementionedabove: /blog/hello-world, /blog/my-second-postandmore.
Inthefilename, [id]insidethesquarebracketsmeansthatanythingthat'sdynamicwillbeputinsidethe idparameterofthequerypropertyoftherouter.
Ok,that'sabittoomanythingsatonce.
What'stherouter?
TherouterisalibraryprovidedbyNext.js.
Weimportitfrom next/router:
Dynamiccontentwiththerouter
51
![Page 52: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/52.jpg)
import{useRouter}from'next/router'
andoncewehave useRouter,weinstantiatetherouterobjectusing:
constrouter=useRouter()
Oncewehavethisrouterobject,wecanextractinformationfromit.
InparticularwecangetthedynamicpartoftheURLinthe [id].jsfilebyaccessing router.query.id.
ThedynamicpartcanalsojustbeaportionoftheURL,like post-[id].js.
Solet'sgoonandapplyallthosethingsinpractice.
Createthefile pages/blog/[id].js:
import{useRouter}from'next/router'
exportdefault()=>{
constrouter=useRouter()
return(
<>
<h1>Blogpost</h1>
<p>Postid:{router.query.id}</p>
</>
)
}
Nowifyougotothe http://localhost:3000/blog/testrouter,youshouldseethis:
Dynamiccontentwiththerouter
52
![Page 53: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/53.jpg)
Wecanusethis idparametertogatherthepostfromalistofposts.Fromadatabase,forexample.Tokeepthingssimplewe'lladdaposts.jsonfileintheprojectrootfolder:
{
"test":{
"title":"testpost",
"content":"Heysomepostcontent"
},
"second":{
"title":"secondpost",
"content":"Heythisisthesecondpostcontent"
}
}
Nowwecanimportitandlookupthepostfromthe idkey:
Dynamiccontentwiththerouter
53
![Page 54: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/54.jpg)
import{useRouter}from'next/router'
importpostsfrom'../../posts.json'
exportdefault()=>{
constrouter=useRouter()
constpost=posts[router.query.id]
return(
<>
<h1>{post.title}</h1>
<p>{post.content}</p>
</>
)
}
Reloadingthepageshouldshowusthisresult:
Dynamiccontentwiththerouter
54
![Page 55: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/55.jpg)
Butit'snot!Instead,wegetanerrorintheconsole,andanerrorinthebrowser,too:
Why?Because..duringrendering,whenthecomponentisinitialized,thedataisnotthereyet.We'llseehowtoprovidethedatatothecomponentwithgetInitialPropsinthenextlesson.
Fornow,addalittle if(!post)return<p></p>checkbeforereturningtheJSX:
import{useRouter}from'next/router'
importpostsfrom'../../posts.json'
exportdefault()=>{
constrouter=useRouter()
constpost=posts[router.query.id]
if(!post)return<p></p>
Dynamiccontentwiththerouter
55
![Page 56: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/56.jpg)
return(
<>
<h1>{post.title}</h1>
<p>{post.content}</p>
</>
)
}
Nowthingsshouldwork.Initiallythecomponentisrenderedwithoutthedynamic router.query.idinformation.Afterrendering,Next.jstriggersanupdatewiththequeryvalueandthepagedisplaysthecorrectinformation.
Andifyouviewsource,thereisthatempty <p>tagintheHTML:
Dynamiccontentwiththerouter
56
![Page 57: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/57.jpg)
We'llsoonfixthisissuethatfailstoimplementSSRandthisharmsbothloadingtimesforourusers,SEOandsocialsharingaswealreadydiscussed.
Wecancompletetheblogexamplebylistingthosepostsinpages/blog.js:
importpostsfrom'../posts.json'
constBlog=()=>(
<div>
<h1>Blog</h1>
<ul>
{Object.entries(posts).map((value,index)=>{
return<likey={index}>{value[1].title}</li>
})}
</ul>
</div>
)
exportdefaultBlog
Andwecanlinkthemtotheindividualpostpages,byimporting Linkfrom next/linkandusingitinsidethepostsloop:
importLinkfrom'next/link'
importpostsfrom'../posts.json'
constBlog=()=>(
<div>
<h1>Blog</h1>
<ul>
{Object.entries(posts).map((value,index)=>{
return(
<likey={index}>
Dynamiccontentwiththerouter
57
![Page 58: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/58.jpg)
<Linkhref='/blog/[id]'as={'/blog/'+value[0]}>
<a>{value[1].title}</a>
</Link>
</li>
)
})}
</ul>
</div>
)
exportdefaultBlog
Dynamiccontentwiththerouter
58
![Page 59: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/59.jpg)
PrefetchingImentionedpreviouslyhowthe LinkNext.jscomponentcanbeusedtocreatelinksbetween2pages,andwhenyouuseit,Next.jstransparentlyhandlesfrontendroutingforus,sowhenauserclicksalink,frontendtakescareofshowingthenewpagewithouttriggeringanewclient/serverrequestandresponsecycle,asitnormallyhappenswithwebpages.
There'sanotherthingthatNext.jsdoesforyouwhenyouuse Link.
Assoonasanelementwrappedwithin <Link>appearsintheviewport(whichmeansit'svisibletothewebsiteuser),Next.jsprefetchestheURLitpointsto,aslongasit'salocallink(onyourwebsite),makingtheapplicationsuperfasttotheviewer.
Thisbehaviorisonlybeingtriggeredinproductionmode(we'lltalkaboutthisin-depthlater),whichmeansyouhavetostoptheapplicationifyouarerunningitwith npmrundev,compileyourproductionbundlewith npmrunbuildandrunitwith npmrunstartinstead.
UsingtheNetworkinspectorintheDevToolsyou'llnoticethatanylinksabovethefold,atpageload,starttheprefetchingassoonastheloadeventhasbeenfiredonyourpage(triggeredwhenthepageisfullyloaded,andhappensafterthe DOMContentLoadedevent).
Anyother Linktagnotintheviewportwillbeprefetchedwhentheuserscrollsandit
Prefetchingisautomaticonhighspeedconnections(Wifiand3g+connections,unlessthebrowsersendsthe Save-DataHTTPHeader.
Prefetching
59
![Page 60: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/60.jpg)
Youcanoptoutfromprefetchingindividual Linkinstancesbysettingthe prefetchpropto false:
<Linkhref="/a-link"prefetch={false}>
<a>Alink</a>
</Link>
Prefetching
60
![Page 61: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/61.jpg)
UsingtheroutertodetecttheactivelinkOneveryimportantfeaturewhenworkingwithlinksisdeterminingwhatisthecurrentURL,andinparticularassigningaclasstotheactivelink,sowecanstyleitdifferentlyfromtheotherones.
Thisisespeciallyusefulinyoursiteheader,forexample.
TheNext.jsdefault Linkcomponentofferedin next/linkdoesnotdothisautomaticallyforus.
WecancreateaLinkcomponentourselves,andwestoreitinafileLink.jsintheComponentsfolder,andimportthatinsteadofthedefault next/link.
Inthiscomponent,we'llfirstimportReactfrom react,Linkfromnext/linkandthe useRouterhookfrom next/router.
Insidethecomponentwedetermineifthecurrentpathnamematchesthe hrefpropofthecomponent,andifsoweappendthe selectedclasstothechildren.
Wefinallyreturnthischildrenwiththeupdatedclass,usingReact.cloneElement():
importReactfrom'react'
importLinkfrom'next/link'
import{useRouter}from'next/router'
exportdefault({href,children})=>{
constrouter=useRouter()
Usingtheroutertodetecttheactivelink
61
![Page 62: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/62.jpg)
letclassName=children.props.className||''
if(router.pathname===href){
className=`${className}selected`
}
return<Linkhref={href}>{React.cloneElement(children,{classN
ame})}</Link>
}
Usingtheroutertodetecttheactivelink
62
![Page 63: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/63.jpg)
Usingnext/routerWealreadysawhowtousetheLinkcomponenttodeclarativelyhandleroutinginNext.jsapps.
It'sreallyhandytomanageroutinginJSX,butsometimesyouneedtotriggeraroutingchangeprogrammatically.
Inthiscase,youcanaccesstheNext.jsRouterdirectly,providedinthenext/routerpackage,andcallits push()method.
Here'sanexampleofaccessingtherouter:
import{useRouter}from'next/router'
exportdefault()=>{
constrouter=useRouter()
//...
}
Oncewegettherouterobjectbyinvoking useRouter(),wecanuseitsmethods.
Thisistheclientsiderouter,somethodsshouldonlybeusedinfrontendfacingcode.Theeasiestwaytoensurethisistowrapcallsinthe useEffect()Reacthook,orinsidecomponentDidMount()inReactstatefulcomponents.
Theonesyou'lllikelyusethemostare push()and prefetch().
push()allowsustoprogrammaticallytriggeraURLchange,inthefrontend:
Usingnext/router
63
![Page 64: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/64.jpg)
router.push('/login')
prefetch()allowsustoprogrammaticallyprefetchaURL,usefulwhenwedon'thavea Linktagwhichautomaticallyhandlesprefetchingforus:
router.prefetch('/login')
Fullexample:
import{useRouter}from'next/router'
exportdefault()=>{
constrouter=useRouter()
useEffect(()=>{
router.prefetch('/login')
})
}
Youcanalsousetheroutertolistenforroutechangeevents.
Usingnext/router
64
![Page 65: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/65.jpg)
FeeddatatothecomponentsusinggetInitialPropsInthepreviouschapterwehadanissuewithdynamicallygeneratingthepostpage,becausethecomponentrequiredsomedataupfront,andwhenwetriedtogetthedatafromtheJSONfile:
import{useRouter}from'next/router'
importpostsfrom'../../posts.json'
exportdefault()=>{
constrouter=useRouter()
constpost=posts[router.query.id]
return(
<>
<h1>{post.title}</h1>
<p>{post.content}</p>
</>
)
}
wegotthiserror:
FeeddatatothecomponentsusinggetInitialProps
65
![Page 66: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/66.jpg)
Howdowesolvethis?AndhowdowemakeSSRworkfordynamicroutes?
Wemustprovidethecomponentwithprops,usingaspecialfunctioncalled getInitialProps()whichisattachedtothecomponent.
Todoso,firstwenamethecomponent:
constPost=()=>{
//...
}
exportdefaultPost
thenweaddthefunctiontoit:
constPost=()=>{
FeeddatatothecomponentsusinggetInitialProps
66
![Page 67: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/67.jpg)
//...
}
Post.getInitialProps=()=>{
//...
}
exportdefaultPost
Thisfunctiongetsanobjectasitsargument,whichcontainsseveralproperties.Inparticular,thethingweareinterestedintonowisthatwegetthe queryobject,theoneweusedpreviouslytogetthepostid.
Sowecangetitusingtheobjectdestructuringsyntax:
Post.getInitialProps=({query})=>{
//...
}
Nowwecanreturnthepostfromthisfunction:
Post.getInitialProps=({query})=>{
return{
post:posts[query.id]
}
}
Andwecanalsoremovetheimportof useRouter,andwegetthepostfromthe propspropertypassedtothe Postcomponent:
importpostsfrom'../../posts.json'
constPost=props=>{
return(
<div>
FeeddatatothecomponentsusinggetInitialProps
67
![Page 68: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/68.jpg)
<h1>{props.post.title}</h1>
<p>{props.post.content}</p>
</div>
)
}
Post.getInitialProps=({query})=>{
return{
post:posts[query.id]
}
}
exportdefaultPost
Nowtherewillbenoerror,andSSRwillbeworkingasexpected,asyoucanseecheckingviewsource:
FeeddatatothecomponentsusinggetInitialProps
68
![Page 69: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/69.jpg)
The getInitialPropsfunctionwillbeexecutedontheserverside,butalsoontheclientside,whenwenavigatetoanewpageusingtheLinkcomponentaswedid.
It'simportanttonotethat getInitialPropsgets,inthecontextobjectitreceives,inadditiontothe queryobjecttheseotherproperties:
pathname:the pathsectionofURLasPath-Stringoftheactualpath(includingthequery)showsinthebrowser
whichinthecaseofcalling http://localhost:3000/blog/testwillrespectivelyresultto:
/blog/[id]
/blog/test
Andinthecaseofserversiderendering,itwillalsoreceive:
req:theHTTPrequestobjectres:theHTTPresponseobjecterr:anerrorobject
reqand reswillbefamiliartoyouifyou'vedoneanyNode.jscoding.
FeeddatatothecomponentsusinggetInitialProps
69
![Page 70: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/70.jpg)
CSSHowdowestyleReactcomponentsinNext.js?
Wehavealotoffreedom,becausewecanusewhateverlibraryweprefer.
ButNext.jscomeswith styled-jsxbuilt-in,becausethat'salibrarybuiltbythesamepeopleworkingonNext.js.
Andit'saprettycoollibrarythatprovidesusscopedCSS,whichisgreatformaintainabilitybecausetheCSSisonlyaffectingthecomponentit'sappliedto.
IthinkthisisagreatapproachatwritingCSS,withouttheneedtoapplyadditionallibrariesorpreprocessorsthataddcomplexity.
ToaddCSStoaReactcomponentinNext.jsweinsertitinsideasnippetintheJSX,whichstartwith
<stylejsx>{`
andendswith
`}</style>
InsidethisweirdblockswewriteplainCSS,aswe'ddoina .cssfile:
<stylejsx>{`
h1{
font-size:3rem;
}
CSS
70
![Page 71: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/71.jpg)
`}</style>
YouwriteitinsidetheJSX,likethis:
constIndex=()=>(
<div>
<h1>Homepage</h1>
<stylejsx>{`
h1{
font-size:3rem;
}
`}</style>
</div>
)
exportdefaultIndex
Insidetheblockwecanuseinterpolationtodynamicallychangethevalues.Forexamplehereweassumea sizepropisbeingpassedbytheparentcomponent,andweuseitinthe styled-jsxblock:
constIndex=props=>(
<div>
<h1>Homepage</h1>
<stylejsx>{`
h1{
font-size:${props.size}rem;
}
`}</style>
</div>
)
CSS
71
![Page 72: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/72.jpg)
IfyouwanttoapplysomeCSSglobally,notscopedtoacomponent,youaddthe globalkeywordtothe styletag:
<stylejsxglobal>{`
body{
margin:0;
}
`}</style>
IfyouwanttoimportanexternalCSSfileinaNext.jscomponent,youhavetofirstinstall @zeit/next-css:
npminstall@zeit/next-css
andthencreateaconfigurationfileintherootoftheproject,callednext.config.js,withthiscontent:
constwithCSS=require('@zeit/next-css')
module.exports=withCSS()
AfterrestartingtheNextapp,youcannowimportCSSlikeyounormallydowithJavaScriptlibrariesorcomponents:
import'../style.css'
YoucanalsoimportaSASSfiledirectly,usingthe @zeit/next-sasslibraryinstead.
CSS
72
![Page 73: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/73.jpg)
PopulatingtheheadtagwithcustomtagsFromanyNext.jspagecomponent,youcanaddinformationtothepageheader.
Thisishandywhen:
youwanttocustomizethepagetitleyouwanttochangeametatag
Howcanyoudoso?
Insideeverycomponentyoucanimportthe Headcomponentfromnext/headandincludeitinyourcomponentJSXoutput:
importHeadfrom'next/head'
constHouse=props=>(
<div>
<Head>
<title>Thepagetitle</title>
</Head>
{/*therestoftheJSX*/}
</div>
)
exportdefaultHouse
YoucanaddanyHTMLtagyou'dliketoappearinthe <head>sectionofthepage.
Populatingtheheadtagwithcustomtags
73
![Page 74: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/74.jpg)
Whenmountingthecomponent,Next.jswillmakesurethetagsinsideHeadareaddedtotheheadingofthepage.Samewhenunmountingthecomponent,Next.jswilltakecareofremovingthosetags.
Populatingtheheadtagwithcustomtags
74
![Page 75: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/75.jpg)
AddingawrappercomponentAllthepagesonyoursitelookmoreorlessthesame.There'sachromewindow,acommonbaselayer,andyoujustwanttochangewhat'sinside.
There'sanavbar,asidebar,andthentheactualcontent.
HowdoyoubuildsuchsysteminNext.js?
Thereare2ways.OneisusingaHigherOrderComponent,bycreatinga components/Layout.jscomponent:
exportdefaultPage=>{
return()=>(
<div>
<nav>
<ul>....</ul>
</hav>
<main>
<Page/>
</main>
</div>
)
}
Intherewecanimportseparatecomponentsforheadingand/orsidebar,andwecanalsoaddalltheCSSweneed.
Andyouuseitineverypagelikethis:
importwithLayoutfrom'../components/Layout.js'
constPage=()=><p>Here'sapage!</p>
Addingawrappercomponent
75
![Page 76: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/76.jpg)
exportdefaultwithLayout(Page)
ButIfoundthisworksonlyforsimplecases,whereyoudon'tneedtocall getInitialProps()onapage.
Why?
Because getInitialProps()getsonlycalledonthepagecomponent.ButifweexporttheHigherOrderComponentwithLayout()fromapage, Page.getInitialProps()isnotcalled.withLayout.getInitialProps()would.
Toavoidunnecessarilycomplicatingourcodebase,thealternativeapproachistouseprops:
exportdefaultprops=>(
<div>
<nav>
<ul>....</ul>
</hav>
<main>
{props.content}
</main>
</div>
)
andinourpagesnowweuseitlikethis:
importLayoutfrom'../components/Layout.js'
constPage=()=>(
<Layoutcontent={(
<p>Here'sapage!</p>
)}/>
Addingawrappercomponent
76
![Page 77: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/77.jpg)
)
Thisapproachletsususe getInitialProps()fromwithinourpagecomponent,withtheonlydownsideofhavingtowritethecomponentJSXinsidethe contentprop:
importLayoutfrom'../components/Layout.js'
constPage=()=>(
<Layoutcontent={(
<p>Here'sapage!</p>
)}/>
)
Page.getInitialProps=({query})=>{
//...
}
Addingawrappercomponent
77
![Page 78: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/78.jpg)
APIRoutesInadditiontocreatingpageroutes,whichmeanspagesareservedtothebrowserasWebpages,Next.jscancreateAPIroutes.
ThisisaveryinterestingfeaturebecauseitmeansthatNext.jscanbeusedtocreateafrontendfordatathatisstoredandretrievedbyNext.jsitself,transferringJSONviafetchrequests.
APIroutesliveunderthe /pages/api/folderandaremappedtothe/apiendpoint.
Thisfeatureisveryusefulwhencreatingapplications.
Inthoseroutes,wewriteNode.jscode(ratherthanReactcode).It'saparadigmshift,youmovefromthefrontendtothebackend,butveryseamlessly.
Sayyouhavea /pages/api/comments.jsfile,whosegoalistoreturnthecommentsofablogpostasJSON.
Sayyouhavealistofcommentsstoredina comments.jsonfile:
[
{
"comment":"First"
},
{
"comment":"Nicepost"
}
]
Here'sasamplecode,whichreturnstotheclientthelistofcomments:
APIRoutes
78
![Page 79: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/79.jpg)
importcommentsfrom'./comments.json'
exportdefault(req,res)=>{
res.status(200).json(comments)
}
Itwilllistenonthe /api/commentsURLforGETrequests,andyoucantrycallingitusingyourbrowser:
APIroutescanalsousedynamicroutinglikepages,usethe []syntaxtocreateadynamicAPIroute,like/pages/api/comments/[id].jswhichwillretrievethecommentsspecifictoapostid.
APIRoutes
79
![Page 80: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/80.jpg)
Insidethe [id].jsyoucanretrievethe idvaluebylookingitupinsidethe req.queryobject:
importcommentsfrom'../comments.json'
exportdefault(req,res)=>{
res.status(200).json({post:req.query.id,comments})
}
Heresyoucanseetheabovecodeinaction:
Indynamicpages,you'dneedtoimport useRouterfrom next/router,thengettherouterobjectusing constrouter=useRouter(),andthenwe'dbeabletogetthe idvalueusing router.query.id.
Intheserver-sideit'salleasier,asthequeryisattachedtotherequestobject.
IfyoudoaPOSTrequest,allworksinthesameway-itallgoesthroughthatdefaultexport.
ToseparatePOSTfromGETandotherHTTPmethods(PUT,DELETE),lookupthe req.methodvalue:
APIRoutes
80
![Page 81: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/81.jpg)
exportdefault(req,res)=>{
switch(req.method){
case'GET':
//...
break
case'POST':
//...
break
default:
res.status(405).end()//MethodNotAllowed
break
}
}
Inadditionto req.queryand req.methodwealreadysaw,wehaveaccesstocookiesbyreferencing req.cookies,therequestbodyinreq.body.
Underthehoods,thisisallpoweredbyMicro,alibrarythatpowersasynchronousHTTPmicroservices,madebythesameteamthatbuiltNext.js.
YoucanmakeuseofanyMicromiddlewareinourAPIroutestoaddmorefunctionality.
APIRoutes
81
![Page 82: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/82.jpg)
RuncodeonlyontheserversideorclientsideInyourpagecomponents,youcanexecutecodeonlyintheserver-sideorontheclient-side,bycheckingthe windowproperty.
Thispropertyisonlyexistinginsidethebrowser,soyoucancheck
if(typeofwindow==='undefined'){
}
andaddtheserver-sidecodeinthatblock.
Similarly,youcanexecuteclient-sidecodeonlybychecking
if(typeofwindow!=='undefined'){
}
JSTip:Weusethe typeofoperatorherebecausewecan'tdetectavaluetobeundefinedinotherways.Wecan'tdo if(window===undefined)becausewe'dgeta"windowisnotdefined"runtimeerror
Next.js,asabuild-timeoptimization,alsoremovesthecodethatusesthosechecksfrombundles.Aclient-sidebundlewillnotincludethecontentwrappedintoa if(typeofwindow==='undefined'){}block.
Runcodeonlyontheserversideorclientside
82
![Page 83: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/83.jpg)
Runcodeonlyontheserversideorclientside
83
![Page 84: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/84.jpg)
DeployingtheproductionversionDeployinganappisalwaysleftlastintutorials.
HereIwanttointroduceitearly,justbecauseit'ssoeasytodeployaNext.jsappthatwecandiveintoitnow,andthenmoveontoothermorecomplextopicslateron.
Rememberinthe"HowtoinstallNext.js"chapterItoldyoutoaddthose3linestothe package.json scriptsection:
"scripts":{
"dev":"next",
"build":"nextbuild",
"start":"nextstart"
}
Weused npmrundevuptonow,tocallthe nextcommandinstalledlocallyin node_modules/next/dist/bin/next.Thisstartedthedevelopmentserver,whichprovidedussourcemapsandhotcodereloading,twoveryusefulfeatureswhiledebugging.
Thesamecommandcanbeinvokedtobuildthewebsitepassingthebuildflag,byrunning npmrunbuild.Then,thesamecommandcanbeusedtostarttheproductionapppassingthe startflag,byrunning npmrunstart.
Those2commandsaretheoneswemustinvoketosuccessfullydeploytheproductionversionofoursitelocally.Theproductionversionishighlyoptimizedanddoesnotcomewithsourcemapsand
Deployingtheproductionversion
84
![Page 85: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/85.jpg)
otherthingslikehotcodereloadingthatwouldnotbebeneficialtoourendusers.
So,let'screateaproductiondeployofourapp.Builditusing:
npmrunbuild
Theoutputofthecommandtellsusthatsomeroutes( /and /blogarenowprerenderedasstaticHTML,while /blog/[id]willbeservedbytheNode.jsbackend.
Thenyoucanrun npmrunstarttostarttheproductionserverlocally:
npmrunstart
Deployingtheproductionversion
85
![Page 86: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/86.jpg)
Visitinghttp://localhost:3000willshowustheproductionversionoftheapp,locally.
Deployingtheproductionversion
86
![Page 87: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/87.jpg)
DeployingonNowInthepreviouschapterwedeployedtheNext.jsapplicationlocally.
Howdowedeployittoarealwebserver,sootherpeoplecanaccessit?
OneofthemostsimplewaystodeployaNextapplicationisthroughtheNowplatformcreatedbyZeit,thesamecompanythatcreatedtheOpenSourceprojectNext.js.YoucanuseNowtodeployNode.jsapps,StaticWebsites,andmuchmore.
Nowmakesthedeploymentanddistributionstepofanappvery,verysimpleandfast,andinadditiontoNode.jsapps,theyalsosupportdeployingGo,PHP,Pythonandotherlanguages.
Youcanthinkofitasthe"cloud",asyoudon'treallyknowwhereyourappwillbedeployed,butyouknowthatyouwillhaveaURLwhereyoucanreachit.
Nowisfreetostartusing,withgenerousfreeplanthatcurrentlyincludes100GBofhosting,1000serverlessfunctionsinvocationsperday,1000buildspermonth,100GBofbandwidthpermonth,andoneCDNlocation.Thepricingpagehelpsgetanideaofthecostsifyouneedmore.
ThebestwaytostartusingNowisbyusingtheofficialNowCLI:
npminstall-gnow
Oncethecommandisavailable,run
DeployingonNow
87
![Page 88: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/88.jpg)
nowlogin
andtheappwillaskyouforyouremail.
Ifyouhaven'tregisteredalready,createanaccountonhttps://zeit.co/signupbeforecontinuing,thenaddyouremailtotheCLIclient.
Oncethisisdone,fromtheNext.jsprojectrootfolderrun
now
andtheappwillbeinstantlydeployedtotheNowcloud,andyou'llbegiventheuniqueappURL:
Onceyourunthe nowprogram,theappisdeployedtoarandomURLunderthe now.shdomain.
Wecansee3differentURLsintheoutputgivenintheimage:
https://firstproject-2pv7khwwr.now.shhttps://firstproject-sepia-ten.now.shhttps://firstproject.flaviocopes.now.sh
DeployingonNow
88
![Page 89: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/89.jpg)
Whysomany?
ThefirstistheURLidentifyingthedeploy.Everytimewedeploytheapp,thisURLwillchange.
Youcantestimmediatelybychangingsomethingintheprojectcode,andrunning nowagain:
Theother2URLswillnotchange.Thefirstisarandomone,thesecondisyourprojectname(whichdefaultstothecurrentprojectfolder,youraccountnameandthen now.sh.
IfyouvisittheURL,youwillseetheappdeployedtoproduction.
DeployingonNow
89
![Page 90: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/90.jpg)
YoucanconfigureNowtoservethesitetoyourowncustomdomainorsubdomain,butIwillnotdiveintothatrightnow.
The now.shsubdomainisenoughforourtestingpurposes.
DeployingonNow
90
![Page 91: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/91.jpg)
AnalyzingtheappbundlesNextprovidesusawaytoanalyzethecodebundlesthataregenerated.
Openthepackage.jsonfileoftheappandinthescriptssectionaddthose3newcommands:
"analyze":"cross-envANALYZE=truenextbuild",
"analyze:server":"cross-envBUNDLE_ANALYZE=servernextbuild",
"analyze:browser":"cross-envBUNDLE_ANALYZE=browsernextbuild"
Likethis:
{
"name":"firstproject",
"version":"1.0.0",
"description":"",
"main":"index.js",
"scripts":{
"dev":"next",
"build":"nextbuild",
"start":"nextstart",
"analyze":"cross-envANALYZE=truenextbuild",
"analyze:server":"cross-envBUNDLE_ANALYZE=servernextbuild"
,
"analyze:browser":"cross-envBUNDLE_ANALYZE=browsernextbui
ld"
},
"keywords":[],
"author":"",
"license":"ISC",
"dependencies":{
"next":"^9.1.2",
"react":"^16.11.0",
Analyzingtheappbundles
91
![Page 92: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/92.jpg)
"react-dom":"^16.11.0"
}
}
theninstallthose2packages:
npminstall--devcross-env@next/bundle-analyzer
Createa next.config.jsfileintheprojectroot,withthiscontent:
constwithBundleAnalyzer=require('@next/bundle-analyzer')({
enabled:process.env.ANALYZE==='true'
})
module.exports=withBundleAnalyzer({})
Nowrunthecommand
npmrunanalyze
Analyzingtheappbundles
92
![Page 93: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/93.jpg)
Thisshouldopen2pagesinthebrowser.Onefortheclientbundles,andonefortheserverbundles:
Analyzingtheappbundles
93
![Page 94: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/94.jpg)
Analyzingtheappbundles
94
![Page 95: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/95.jpg)
Thisisincrediblyuseful.Youcaninspectwhat'stakingthemostspaceinthebundles,andyoucanalsousethesidebartoexcludebundles,foraneasiervisualizationofthesmallerones:
Analyzingtheappbundles
95
![Page 96: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/96.jpg)
Analyzingtheappbundles
96
![Page 97: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/97.jpg)
LazyloadingmodulesBeingabletovisuallyanalyzeabundleisgreatbecausewecanoptimizeourapplicationveryeasily.
SayweneedtoloadtheMomentlibraryinourblogposts.Run:
npminstallmoment
toincludeitintheproject.
Nowlet'ssimulatethefactweneeditontwodifferentroutes: /blogand /blog/[id].
Weimportitin pages/blog/[id].js:
importmomentfrom'moment'
...
constPost=props=>{
return(
<div>
<h1>{props.post.title}</h1>
<p>Publishedon{moment().format('ddddDMMMMYYYY')}</p>
<p>{props.post.content}</p>
</div>
)
}
I'mjustaddingtoday'sdate,asanexample.
ThiswillincludeMoment.jsintheblogpostpagebundle,asyoucanseebyrunning npmrunanalyze:
Lazyloadingmodules
97
![Page 98: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/98.jpg)
Seethatwenowhavearedentryin /blog/[id],theroutethatweaddedMoment.jsto!
Itwentfrom~1kBto350kB,quiteabigdeal.AndthisisbecausetheMoment.jslibraryitselfis349kB.
Theclientbundlesvisualizationnowshowsusthatthebiggerbundleisthepageone,whichbeforewasverylittle.And99%ofitscodeisMoment.js.
Lazyloadingmodules
98
![Page 99: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/99.jpg)
Everytimeweloadablogpostwearegoingtohaveallthiscodetransferredtotheclient.Whichisnotideal.
Onefixwouldbetolookforalibrarywithasmallersize,asMoment.jsisnotknownforbeinglightweight(especiallyoutoftheboxwithallthelocalesincluded),butlet'sassumeforthesakeoftheexamplethatwemustuseit.
Lazyloadingmodules
99
![Page 100: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/100.jpg)
WhatwecandoinsteadisseparatingalltheMomentcodeinaseparatebundle.
How?InsteadofimportingMomentatthecomponentlevel,weperformanasyncimportinside getInitialProps,andwecalculatethevaluetosendtothecomponent.Rememberthatwecan'treturncomplexobjectsinsidethe getInitialProps()returnedobject,sowecalculatethedateinsideit:
importpostsfrom'../../posts.json'
constPost=props=>{
return(
<div>
<h1>{props.post.title}</h1>
<p>Publishedon{props.date}</p>
<p>{props.post.content}</p>
</div>
)
}
Post.getInitialProps=async({query})=>{
constmoment=(awaitimport('moment')).default()
return{
date:moment.format('ddddDMMMMYYYY'),
post:posts[query.id]
}
}
exportdefaultPost
Seethatspecialcallto .default()after awaitimport?It'sneededtoreferencethedefaultexportinadynamicimport(seehttps://v8.dev/features/dynamic-import)
Nowifwerun npmrunanalyzeagain,wecanseethis:
Lazyloadingmodules
100
![Page 101: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/101.jpg)
Our /blog/[id]bundleisagainverysmall,asMomenthasbeenmovedtoitsownbundlefile,loadedseparatelybythebrowser.
Lazyloadingmodules
101
![Page 102: Table of Contents - topidesta.files.wordpress.com · First, the page takes longer to become visible to the user, because before the content loads, all the JavaScript must load, and](https://reader033.vdocument.in/reader033/viewer/2022060301/5f086bf27e708231d421ee34/html5/thumbnails/102.jpg)
WheretogofromhereThereisalotmoretoknowaboutNext.js.Ididn'ttalkaboutmanagingusersessionswithlogin,serverless,managingdatabases,andsoon.
ThegoalofthisHandbookisnottoteachyoueverything,butinsteaditaimstointroduceyou,gradually,toallthepowerofNext.js.
ThenextstepIrecommendistotakeagoodreadattheNext.jsofficialdocumentationtofindoutmoreaboutallthefeaturesandfunctionalityIdidn'ttalkabout,andtakealookatalltheadditionalfunctionalitiesintroducedbyNext.jsplugins,someofwhichareprettyamazing.
Wheretogofromhere
102