How NextJS REALLY Works
By Theo - t3․gg
Summary
Topics Covered
- SPAs Deliver Incorrect Initial HTML
- Next.js Embeds Props in HTML
- Opt for Static Generation When Possible
- Server Code Can't Access Client Globals
- Next.js Is Enhanced SPA with Correct HTML
Full Transcript
how does next actually work might sound like a silly question it renders react on the server what is there to know about it well I found a lot of the questions that I get about people building with P3 stack and with the tech
we recommend here come from fundamental misunderstandings of how next itself actually works and differs from old ways of deploying things like create react app or V single page app deployments
what makes next different how should we think about it and how does data actually flow through nextjs to your react application let's talk about
it this big old dump in the HTML here this is the content of what gets serers side props returned oh boy am I happy you're here for this stream and video because the whole point of this is that
SSR is just the first step so nextjs as we know is a server rendered framework for react the tldr
version is you write react code and before it goes to the users it gets run on a server so the user gets a page that actually has the content of the page if
I go to somewhere like do I have a single like a simple V app deployed somewhere we did so this is an app that was built using V normally you put uh
query Pam for the hours minutes and seconds I'm lazy don't feel like doing that the important detail to know here is that the HTML that comes down the server does not have the contents of the
page so so if I Network Tab and actually look at the HTML we got back from the server you'll see that this HTML is like hilariously empty has a div ID root with
nothing in it the reason for this is the content of the page isn't created on a server it's created on the client this page is almost instructions for how to make the website and most of those
instructions are contained within this index whatever. JS file this asset file
index whatever. JS file this asset file is a bunch of JavaScript that we bundle that we built when things were deployed on verell and this JavaScript gets
loaded by the client and then runs to create the page that the user sees so the control flow here if I open up excal
draw quick uh Spa react flow is I'll draw my arrow down the top here is request the bottoms the HTML page I'm
too lazy to draw those in here the step one is user receives HTML with JS tag should specify that this is like empty
so the first steps the user receives empty HTML with a JS tag user loads Js from JS tag Js from or JS runs starts
fetching data and creating page I'm going to have to make a longer arrow for this one eventually data returns JS finishes rendering page and then finally
complete page with correct HTML in order to go go from the user making a request to this generated correct page we have
to load JS here from the HTML so at this point I'll say HTML here but incorrect so at this point the HTML is here but it is incorrect it does not represent what
the pages content should be it represents a static cached asset of just some of the content of the page and until all of these things happen it is not running are is not the correct page
and it takes all the way to here to get that correct page because the client has to go do another server trip to fetch data I could put a a line actually for each point that an additional request or
set of requests has to be made so request one happens at the top here and then they receive the HTML then they request the JS here so this is the request for that JavaScript and then
once the JS comes in and runs it has to request the actual data for the page contents so the first thing you fetch here is the HTML so first fetch HTML
then fetch JS then fetch the data you need for the page and finally then after all of these steps you get a complete page with the correct HTML out so each
of these you request to the server you get HTML you do some stuff you request the server again you get some JavaScript you do some stuff you request the data that comes back again and now you can
actually finish rendering the page but each of those steps it's because the server isn't generating HTML per request on this request the first one the server doesn't know what you want it doesn't know what the user is asking for it's
just handing them an HTML page and from there the HTML page can load the JavaScript and then from that JavaScript figure out what it's actually meant to be doing but all of those steps have to
occur on the client's device before it can render the correct page the goal of nextjs was to prevent this so if I go here and say nextjs data flow what
nextjs does and I'm going to delete all of these line I'm just going to delete all of this because most of the info here is incorrect so user requests page so what happens here when the user
requests the page depends on how you have things set up in nextjs but will assume your server rendering every page for now we'll go into what that means and why you might not want to do that in
a minute but for now we'll say next server we say gets request runs get server side props the get server side
props function is server code that runs when a user requests the page so if I request a page like let's say I'm requesting I'll just change it user requests
sluser Theo so user request user Theo next server gets the request and it runs the get server side props function that is in that page file that get server say
props function probably is taking a user ID from the query Pam in this case the SL Theo it is running that against something like a database to fetch some data and then it returns that as props
for that page specifically so it can render that in to the HTML so your react code is running here on the server so
react runs on server using properties from get server side props this means that the actual page the HTML that has
the information that you want the HTML to have on it is run and generated on the server the server then sends correct
HTML to user based on what this react code rendered and then the user loads HTML then loads JS to catch up to what server rendered this catch-up step is a
very important piece the catching up is how the term for it's hydration because when your client isn't rendering the whole page it's just getting HTML that's
correct initially you still want things to change like in react if I have a hook that renders a count and I want it to go up every time a user clicks but the server rendered it to zero I still want
it to increase when I click it on the user side the way that you do that is you take the the HTML that you got from the server and you hydrate it with the JavaScript in order for the hydration to
work it needs to know exactly what properties were passed to generate that HTML because effectively what it's doing when you hydrate and react is it is regenerating the same HTML in react so
it knows hey that element on the page matches this virtual element in our virtual Dom so it can do updates from that point forward this step this H this
uh hydration step takes roughly as long as the painting step here where you actually are generating and running that code to figure out what you need to fetch and then fetch it and whatnot that
takes just as long to hydrate however the page already exists and the user already sees something and they're probably reading the content of that page as everything else is updating behind the scenes and by the time they
go to click something all of the JS is loaded and hydrated the page properly but what about the serers side props if you have serers side props and these return some data that is used to render
the page how does the the copy of that rendering path that is running on the client know about that data well here's where things get a little hacky uh do I have any pages that have get server side
props that I can quickly demo on think ping does cool so here's the Ping call page for me and if I go in here and I actually go into the HTML I'll find a
script tag somewhere in here might actually be in the head maybe not oh next data here we are this here this big old dump in the HTML here this is the
content of what get server side props returned this is dropped in the HTML because it is necessary for the JavaScript running on the client to know
what was used to render the page so it can properly hydrate and synchronize the client with the server this here is an important arguably Hack That nextjs does
in order to make all of this possible so the the the magic piece here the thing that you might not have known about how nextjs works is that this page can only be rendered on the client after the
server because the data needed to render this page was included on the HTML itself so the main benefit here of next specifically is that the correct data is
on the page when it renders for the user the first time you don't have the blank pop in that then shows the correct content like if I go to Twitch right now see this loading state that loading
state is if I slow on my network you can see it even more D or uh like exaggerated I'll put on Fast 3G you'll see there's a state here with like a loading spinner oh wow it's it's have to
disable cache and knock that to slow you'll see that there's a state there where the JS hasn't loaded yet and it just has that like top nav uh can I
easily disable JavaScript on the page cool if I refresh yeah you'll see the JavaScript is
disabled and because of that we never get additional data if I go to here I go here and I disable the JavaScript it's going to hang on a
loading spinner still but the actual HTML we got back has way more in it including that server data if I was painting a more traditional view here you would get that whole view hell if I
go to the Ping homepage actually and JavaScript is still disabled right now you know that because there's a video that should be playing and it's not so this is the Ping homepage with JavaScript disabled and this works
because the HTML the server sends is correct that correct HTML means your metadata is correct your first paint is correct your general user experience is
more consistent because you don't have a big pile of JavaScript that has to load run parse and paint before content makes it to the user that all said you do not
have to do this on every page in nextjs you can opt in or out in fact on this page you might notice that it still loads really fast that's because we don't want to run this on the server
this page doesn't run on the server when we build our application when we like npm run build or we deploy to verell since the file for this page doesn't have a get server side props function
next is smart enough to generate a unique HTML page for the site at build time and then this route now has static HTML that is fetched when a US loads the
page that static nature of the content that's being output means like robots and Google crawlers can more easily parse this and get meaningful data out of it it means users load the page
significantly faster it means less like powerful devices are necessary to load your page in the first place and it most importantly here means that you don't need to run server code on every request
because you generated that HTML at build time and then sent it up to your CDN to share it from there static assets are incredibly cheap and and if you're able to distribute those and have those be
like fetched by your users that's going to be a significantly better experience for everybody I see people saying but who actually disables JavaScript robots disable
JavaScript uh bunch of embedded devices disable JavaScript a bunch of like crawlers SEO those types of things disable JavaScript most importantly users have JavaScript disabled until the
JavaScript loads every user who goes to your site has JavaScript disabled for the first however many milliseconds maybe even seconds depending on the speed of their Connection in their device every user has JavaScript
disabled for some amount of time on every website they go to until the JavaScript loads and ideally the content of that page will be correct the first time it loads without needing the
JavaScript all to load in behind the scenes somebody's asking is there a scenario where this isn't good it's not that there are situations where this isn't good there are some where it isn't necessary where you might want to say eh Don't Bother we'll just fetch everything
on client we do that a bunch CH ping we have a handful of pages where just like the dashboard for example server rendering the dashboard makes no sense also love that the menu button do work with JavaScript disabled fun stuff if
you have a page that you just you don't care about the HTML being correct like people are exclusively using it on computers in San franisco with really fast internet connections it's not as big a deal or something that we deal
with you have like a bunch of Av devices you want to interface with so when I go to this page I need to use your AV I need to use your camera and your microphone in order to activate this
call if we don't have JavaScript running I can't do any of that this page is actually useless without JavaScript which is why this page has a big old loading spinner in front of it it still server renders and it still puts a bunch
of data into that server render in order to make the metad DAT here correct so when I link this call to somebody the right stuff comes up when I do that so like if I go to one of my favorite sites the Twitter card validator by the way
super pro tip if you're working on metadata one of the easiest ways to know if your is working so when I paste a pin call here unable to render card preview because I must have broken
something kind of recently very good to know theoretically this should load fine surprised it doesn't uh URL metad dat Checker I think Facebook has one a
Facebook link validator sharing debugging cool please work cool this one kind of worked so here's what it would look like I have my
old T3 logo Theo's room come chat and Theo's room this is what the metadata of that page contains if this page was client rendered entirely this would not be able to come through because this
would have to load the HTML then run some JavaScript then create an updated page and this robot's not going to do that they're just going to download the HTML and read it they're going to stop at that first step I think that's what a
lot of people are missing when they see things like this a lot of devices stop here so the HTML here is here but it's
incorrect if your device isn't running JavaScript because it hasn't loaded yet because you're a server and your server doesn't load JavaScript because you're parsing things because you're reading
metadata if you stop here and a lot of things do this does not work you are not getting the data that you need here realistically speaking because of all
that it's important to be considerate of server rendering opportunities when you have them and the HTML contents that your users are getting when you can so yeah be more considerate of how your
servers are actually rendering things what's happening where and to an extent how the HTML that comes out of your server is shaped and how it looks there are gotas here yeah one of the big gotas
is not all code can be run on a server things like calling window directly actually I'll not all code can be run on a server there's a lot of code don't want to make that smaller there's a lot
of code that can't be run on a server things that call Window window can't be run on the server because servers don't have Windows servers run Linux kind of a joke seriously though servers don't have the window primitive so you can't call
that directly and do things to it you can't like check a user AV devices on the server cuz you're not on their device where the AV devices are you can't call local storage so things that
call local storage local storage doesn't exist on the server it exist on the client you don't have access to that on the server if you want things like that you want to put those in the request to the server so the server can include the right things it's again one of those
huge Arguments for having cookies is the cookie will be in the initial request and you can render the right things accordingly other code that can can't run on servers uh anything stateful if you have stateful code you either need
to put that in a database and synchronize it or you can't like like an onclick a uh set State those types of things those aren't going to run on a server basically anything that isn't
there before use effects start running and before actions start running isn't going to be there when you render on the server what else is there that I have run into where I like wanted something and I couldn't use it because I was
server rendering uh I'd say user devices is part of window like the only way access user devices is through window and similar window-based globals uh
media queries oh media queries is a fun one somebody asked Theo what about real-time page updates isn't it better to have client side rendering for this case oh boy am I happy you're here for
this stream and video because the whole point of this is that SSR is just the first step the thing that nextjs is and I want to be very very clear about this cuz I feel like this is what people are missing and I'm pumped you ask the
question because I want to call it out next only does this this is next this is a normal Spa once your HTML has got to the user I should actually move this
here because this is the point where the HTML is correct so this section up here is next and this part here is react once your server code has run you're in a
normal react app the only difference between something like create T3 app or sorry I would like create react app or vit the difference between those and the difference with something like next is
what happens before that HTML comes if I was to horizontally Spectrum this is probably like the most useful part there's if we're very generic like there
is HTML loads let's make three of these HTML loads JS loads and uh JS paints correct content I'll even call this like
JS synced with HTML content these are three steps that both like a create react app or V or other single page app have as well as something like nextjs
the difference between create react app and vs versus something like next is purely here from uh request to complete
Spa load let me move all of this quick this section what the hell why is it doing that I did not find that there at any point why does it think this is here did not do that so this section here
this little bit in this area this is where things are different in next land the only difference between next and another single page app is right here
this is the next remix section when you're using something that's rendering on the server and it's something like next remix whatever else I don't know why this Arrow keeps killing itself whenever it's something like next or
remix and it's Runing running code on the server it runs here before the HTML loads but from this point forwards I should give this background color too
wrong color I move this up God why is excal doing this to me I want to unlink this Arrow I never want this I can I just tell arrows to never connect i' be okay
if my arrows never connected again okay this is the next remix section and this is a normal Spa so given this spectrum here you have the
next remix section and then normal Spa the difference here the thing that makes these two so different cuz right now it looks pretty similar there just like that little section in front the thing that that means God I can't just make all three of these shorter at once okay
better so the thing that is different here is that the HTML that loads here I'll put an arrow here initial initial HTML is correct in next remix Incorrect
and an Spa so the important difference here like the distinction the initial HTML when you use next to remix is correct and it is incorrect if you're using a traditional Spa which means that
what happens from here down is different as well if your HTML is correct then when the JS loads it's not filling the page it's recreating the page in
JavaScript land in order to synchronize that state with the page state so this step is a little different depending on if you're going the next remix route or not but the distinction that really
matters the point I want to drive home the is that the only difference between next or remix and something like V or create react app the only difference in
terms of how Pages load render behave is that your HTML loads different content initi
this first step is correct if you're using a serers side rendered framework and it is incorrect if you're using a single page app based framework and that is fine if the thing you're building
doesn't need correct HTML but it probably does at some point I saw somebody else in chat saying this is why a single page app loads faster no it does not because if I run this code here at build the thing that the server has
cached is the same if I have HTML that next built and you have HTML that create react app built those load just as fast if I want to make different HTML for every request or every user I can do
that and that will be slower for the first paint but it won't be slower overall the HTML that the user gets from a single page app is incorrect and it will always take more time for them to
load the JavaScript fetch the data the JavaScript needs and then paint the correct page but if the page is static I can do that at build time here and now my page and your page my page being a
next app and your page being a create react app have the same time to that first HTML the difference is your html's wrong if I want if I have Dynamic data we want to fetch like let's say we want to fetch my view count on this page you
could load the HTML page with no data in it you could load the JavaScript that JavaScript parses renders the page realizes oh I need that data it that's a third fetch to go get that data bring it back and now you have the
correct content in next in remix if you choose to block the page on that content you make one request the server gets everything it needs puts it in the page and then the thing the client gets back is correct the first time and that
overall takes way less time way less time and if you don't need to do that because the content is static then don't block every request on the server generate a static page from nexto remix
it is very easy to effectively turn nexto remix into create react at plus plus by never using get server side props and never using loaders and actions the server code only runs if you
write it so don't write it if you don't need it and now you've just made a create react app style single page app with better build tools or you can block
things because you have pages that need content and that's fine too but chances are at some point you're going to want correct HTML and at that point you're going to wish you were using next next
JS remix from the start and I found on almost every project I ever worked on I got to the point eventually where I wanted to add an endpoint or I wanted to block on like generating this page or at like I wanted to use incremental static
revalidation or regeneration revalidation whatever to make sure the content of that like metadata is correct on request all of these things quickly get noticed when you have problems that
require you to work around them I yeah I don't know how to put it other than like if you don't think you need some form of serers side rendering generation you're going to regret that
soon you're you're probably close to the point where you realize that somebody asked if you have conditionals on the front end IE like if content does that get run during hydration it depends on where the conditionals are and if the
data those conditionals operate on is on the server or not it's like if you're blocking the page on getting data from Prisma and you only render a certain view if that data has like like let's
say you use the user's token or their cookie to fetch the user profile and you only render this page if they're an admin if you have code that's if user is admin render this else render something else then the HTML the user gets us
correct I think I've covered everything I want to here the main point I want to drive home is that nextjs isn't this crazy alternative framework that does
doesn't do the things that react does it doesn't in any meaningful way change how your react code runs on the client at
all the only thing nextjs does and the only thing remix does is the request before the content is on the user's
device nextjs makes it easier than ever to generate HTML per page for your users so that when they load the page the html's correct and then the JavaScript loads and becomes a normal reactor app
without next or remix you're getting incorrect HTML the client has to fetch everything update it all then and only then will the user get correct content and the benefit of these Frameworks in
the server side stuff is that you have control over what HTML the user gets but don't think that using nextjs means that you can't use all the other react stuff you're used to this is still a single
page app and all the people saying single page app versus next don't actually understand what nextjs is because nextjs isn't a multipage app
framework it is a single page app framework it is a react based framework that runs on the server that happens to let you generate different HTML based on
different routes but you're still building a single page app once that first page loads it's just a normal react app that's it like I I hope this
video covers this well enough that I can start linking to it and no longer answer these annoying questions next gives you the benefits of serers side rendering and single page app style react
applications in one react is a way to make interactive websites and next J is a way to make the HTML correct for those interactive websites as soon as it loads that's it
nextjs isn't an alternative to these things next isn't an alternative to react next isn't an alternative to like single page apps next lets you build a really powerful single page app with
correct HTML from the server on first paint and a much better overall developer experience around it next is a single page application framework that happens to be backend ready happens to run on servers and it happens to enable
you to do really cool things but it does not have to do those things if you don't want it to because in the end it is a way to build react applications next is not something that prevents you from
having an interactive customizable live experience on your app because I guarantee you ping is more of an app than most of y'all saying you don't need nextjs or building ping is right about
as interactive and live as you can get our average page session time is 2 and 1/2 hours 2 and 1/2 hours on one page we don't care that much about how quickly that first paint comes through but having the power of a framework that
lets us build the right HTML build the right Json calling the back end in our own single Focus environment is so powerful that we use nextjs to build our single page application that is very
much an app nextjs lets us do that better and it is a great framework for it just because you don't think you need really good SEO right now does not mean you don't need the benefits of a server
rendered application framework and nextjs is still the best option for that with all that said if you still somehow don't get this ask some questions in the comments maybe come hang out in the Discord I want to figure out what isn't resonating here because a lot of people
are asking to to be frank not just dumb but outright stupid questions about nextjs versus create react app and I want to be very clear there is no use case for create react app anymore V templates for a single page app
experience if you really don't need server rendering are nice but generally speaking more often than not having server rendering will make your life easier and you should probably consider integrating it in your applications hope
this was helpful join the Discord if you haven't subscribe if you haven't for some reason buttons here I think over there click it or on that subscription grind appreciate y'all a ton thanks for
stopping by check out the next video
Loading video analysis...