Migrating from NextJs 12 `pages` router

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we're going to look at server side rendering static site generation and incremental static regeneration in mixtures 13 new app directory hey friends welcome back to the channel if you're new here my name is Hamid I'm a full stack web developer and here in this channel we talk about modern web dev topics like react and xjs now in Nexus 12 we had specific functions like get server-side props and get static props that we could export from our pages that would instruct next.js how to generate these Pages whether statically at build time or on demand at request time now in the app directory we don't have these functions but we are using a simpler API that's built on top of the fetch function and async react server components in this video we're going to go over the migration guide inside of the next JS documentation for the app router which is the beta version of their documentation and we're going to also create this simple to do app together to put this Concepts in practice by building static pages and contrast them with server-side rendered pages and also incremental static regeneration so let's go back to the docs where we have this migrating data fetching methods inside of next JS and as I explained inside of the Pages directory we had get server side props or get static props to fetch Pages or data for our Pages whereas in the app directory we're going to use the fetch function directly inside of our react server components because they can be turned into async functions and therefore you can fetch the required data right inside of your components now if you're using the fetch function directly inside of your page components to fetch data you can pass in options such as cache Force cache to instruct next.js to Cache the results of this fetch function until it is manually invalidated or you can pass in no store that instructs next.js not to store the result of this fetch function so therefore it will be dynamic just like get server-side props you can also pass options like this next revalidate to replicate the incremental static regeneration we had in the Pages directory or in xjs 12. now this fetch function is an extension of the fetch API that's why you're able to pass this custom options to it such as this next revalidate but oftentimes if you're not using fetch directly when we're interacting with our databases or when we are fetching data oftentimes if you have database clients for example in our app we're going to be using mongodb to fetch our to-do's and we're not directly using this fetch function to be able to pass these options to it and that's where your route config options come into place so these segment config options allow you to define the behavior of your page by exporting these variables from your page or your layouts now specifically we're going to talk about dynamic and revalidate which will Define the behavior of your page replicating get static props or get service site props we're going to also look at the dynamic params which is used together with generate static prompts which is for your Dynamic segments so if you're having let's say to Do's for a slash and then to do ID and you're dynamically rendering that segment you're going to look at these two functions that help us render Dynamic paths the fetch cache is when you want to override the cash behavior of this new fetch function inside next.js it is an advanced feature and you should only use it if you really want to override the caching behavior of it so if you're not going to touch this now runtime is your runtime this can be your node.js or the edge runtime and then a region for where your functions would be deployed so basically to statically generate Pages or make them server-side rendered we would have to deal with Dynamic and revalidate these are the two options we're going to closely look at and then we're going to talk about the dynamic problems and generate static prompts that's for dynamic segments now let's start from the dynamic option and here you can see this Dynamic you can export it from a page and this is useful again for when you're not directly working with a fetch function and we're going to see this in action inside of our code in a second but let's just read the explanation here before we dive into the code so this changes the dynamic behavior of a layout or page if I mention page anywhere in this video just know that it also can be exported from the from your layouts too and if you don't know how this new structure is set up in the app directory I have a video on the channel where I introduced this new whole structure of layouts and Pages you can watch that to better understand how that's set up in this video we are not going to dive deep into that I assume that you know how pages and layouts work in the app directory we just want to turn them into static Pages versus Dynamic pages now this Dynamic changes the behavior of the page to fully static or fully dynamic the possible values are you can set it to Auto you can set it to force Dynamic to error and force static now there's a little migration note here that's interesting or good to know it says the new model in the app directory favors granular caching control at the fetch request level over the binary All or Nothing model of get server-side props or get static props at the page level now inside of the Pages directory when you are exporting the get server side props from a page it turns that whole page into a server render page or when you export get the static props it turns the whole page to a static page so it's at the page level whereas in the new app directory you can control based on or at the fetch or request level if you want a specific request to be dynamic or versus a specific request being static now this Dynamic option which is a route config option you can export from any page or layout is a way to opt back into the previous model as a convenience and provides a simpler migration path so by exporting this Dynamic you're kind of replicating what you were doing in Pages directory in exercise 12 which means that you're defining what happens to the page or layout at the page level so you're not going into the specific fetch requests and change them at that level you're just defining the whole page and this makes it easy for us to migrate our pages to the app directory by just playing around with this Dynamic so let's see what what are the values that we can export we can set this Dynamic constant to so the auto which is the default is going to cash as much as possible without preventing a component into opting into Dynamic Behavior so if you leave this option alone and don't even export it it's going to default to auto which is going to Cache as much as possible or it's going to replicate get static props as much as possible unless a function is opting into Dynamic functions and fetching data dynamically it is going to be generated statically and it's going to be cached now if you don't want to leave it to Auto you can set it to force Dynamic which forces Dynamic rendering and it's equivalent to your get server-side props inside of your Pages directory now this is also similar to passing in this options to your fetch function so if you're using fetch directly you can pass a cache no store and next revalidate zero to turn that fetch request Dynamic meaning that nextures will not cache the result of the fetch function now we can also change this fetch cache config to be Force no store this is not the default behavior of the fetch function and as I mentioned you should only change this if you really want to overwrite the behavior of your fetch function now the next value you can export your dynamic config option is air and this is going to force static rendering and static data fetching and it's going to cause an error or a 404 page if the component is trying to render or access any any Dynamic functions again this is going to be equivalent to your get static props where every page is rendered statically so here again we are having a we are forcing a static rendering and if the page or any component inside of it is going to access any Dynamic function we're going to show a 404. now our last value is forces static and as the name implies it's going to force static rendering and static data fetching and it's doing so by forcing cookies headers and usage pram functions to return an empty object or value now following the migration guide it recommends to set the dynamic to force Dynamic if we wanted to turn the page into a server render page similar to get server-side props and also Dynamic to error if we wanted to turn it into a static page similar to get static props so even though the forces static is very similar to the error the documentation recommends setting it to error instead of force static and to be honest I'm not quite sure what the exact difference of these two are but at this point at least we know this is the recommended way let's actually put this into practice on the left hand side you can see a Nexus application I created by running npx create next app and I have turned the experimental app directory flag on so that we have this app directory and inside of it as you see we have these three folders SSG SSR and ISR which represents static site generation or static pages dssr is server-side rendered or are Dynamic pages and disr which is incremental static regeneration which is going to be when we want to revalidate a statically built page now we're going to implement the same Pages as we saw in the beginning for this to do app in the three different strategies and see how we can replicate the behavior of the Pages directory or an xgs 12 here but for now let's ignore the ISR and SSR and dive into the SSG and see what we're doing there as you can see I have a dynamic folder that's going to be responsible for when we are trying to access a specific to do and if you can see up there there's SSG and then the dynamic ID and then we're going to have this page.jsx inside of the SSG which is representing this index page which is at forward slash SSG now again if you're not familiar with how the app directory is structured I recommend watching the video that I Linked In the card first to understand how the new app directory the segments the routes pages and layouts works and then come back to this now inside of our SSG folder this page as I mentioned is representing the index route pointing to forward slash SSG and now let's dive into this page and see what we're doing here now first things first we are exporting this page component that's responsible for rendering this specific page it's a react server component because by default any component inside of the app directory is a react server component therefore we can turn it into an async function and that enables us to fetch our data right inside of our page component so we are calling this get all to those function which we're going to look at in a second we're getting our to-do's back and we are mapping over our to-do's to render this list now we also have this new to do form which allows us to add new to-do's to our list over here and as I mentioned the idea is when if you're building Pages statically versus dynamically we want to be able to add new to-do's and see if they show up on the list over here or not now let's quickly look at this get all to this function that's helping us connect to our mongodb database and fetch our to-do's if you're not familiar with how to integrate mongodb in xjs application I have a video on the channel you can look that up it's pretty straightforward but we are initializing the connection to the database and we're trying to fetch all of our to-do's by calling this function on our collection in mongodb and then passing the results back over here which is used directly inside of our page component okay great now we have our data how do we go about turning this page into a static page now as I mentioned if this was inside the Pages directory in next year is 12 we would have just exported get static props function and that function would turn this page into a static page that's generated at build time but here we don't have these functions instead we have this route config options we can export now if you remember the default value for this Dynamic config option was Auto and auto meant that next.js would try to Cache as much as it can unless the component is trying to access Dynamic functions like headers and cookies or it's trying to dynamically fetch data so let's actually leave this out without exporting any config option and see how would this page behave let's go ahead and create a new tasks let's say third to do task now as you can see it immediately popped down here in my list you might think well if this page was static we shouldn't have seen this third option but the problem is when you're running the development server everything is going to be server rendered so to really see the behavior in action we have to first build our application and once the build process is done we have to serve up that production bundle by running npm start instead of npm run Dev to just serve up that built application okay so the build process is done let me just run npm start to run the production server and now if I come back to my page and refresh I still have the three tasks that I've created before let's now add a fourth task to this and see what happens as you see this time the fourth task is not added automatically to the list because this page is built statically at build time and at build time where the HTML was generated this last task or fourth task wasn't there now to confirm that this actually was creating a task in our database let me just open up mongodb compass and refresh the list of my to-do's and as you can see here the fourth task is created here so this confirms that our page was created statically and that's because the default value of this Dynamic option that we can export from our page is auto which means next.js will try to Cache as much as possible and unless the page component is trying to access Dynamic functions it will be generated statically however if your page actually tries to access cookies and headers or fetch data dynamically it's not going to 404 it's not going to err out it's actually going to run the page component and try to generate that page dynamically if that's not the behavior you want and you want to exactly replicate the get static props in Nexus 12. instead of the auto we can export the dynamic parameter and set it equal to error this way we're forcing static rendering and if a dynamic function is used inside of the page component it's going to show a 404. now as I mentioned there's an alternative to this which is force a static which has the similar behavior of the error and the only difference is that the values for your Dynamic functions such as cookies and headers or use search prompts will be an empty value so it's not going to error it's not going to 404 and instead it's not going to be able to access the values of those functions but again as I mentioned in the docs it recommends using Dynamic air for pages that you want to statically generate and 404 if it's not static now to contrast this with server-side rendering or SSR let's dive into our SSR folder and access this same page component that's responsible for rendering the page dynamically and as you can see we have the same exact page component fetching our to-do's and passing it down to this list and the only difference is that when exporting this Dynamic option we are setting it to force dynamic which forces a dynamic rendering and prevents next.js from statically generating this page at build time now let's test this out if I go back to my home page and access this SSR or dynamic route which points to forward slash SSR where this page component we just looked at is responsible for rendering the page we immediately see this fourth task on the list because this page is a dynamic page rendered ad request time on demand and it already has this fourth to do task and just to confirm this is the case if I add another to do over here we would see it immediately added to the bottom of the list again this page with the use of this Dynamic config option set to force Dynamic is now forced to be dynamic and rendered at request time now with these two out of the way let's talk about incremental static regeneration which is useful when you want to update your statically built Pages without having to rebuild and redeploy your app so if you go back to the documentation there is a section that talks about incremental static regeneration and as a refresher inside of the Pages directory where you're exporting your git static props from a page to generate that page statically you can also set a field called revalidate and set it to a number of seconds that you want next.js to actually invalidate that cache or regenerate this page so therefore the next user after this many amount of seconds is going to get a newly generated updated page now in the app directory we don't have such a function but as I mentioned earlier if you're using the fetch API to fetch data directly in your react server component you can pass in this next revalidate options directly to the fetch function and if you're not using the fetch function like our to-do app you're using a client database to fetch or to Do's you can export route config options and specifically this revalidate option that does the same thing so let's actually look at the revalidate config option we can export from our pages and see what values we can pass and what the behavior would be so as I mentioned this revalidate config option defines the revalidation behavior of a layout or a page you can set it to false Force cache 0 or a positive number Now the default value for revalidate is false as you can see here which effectively means that the resource should be cached indefinitely so it's not going to revalidate our results as you can see next.js default Behavior similar to the dynamic default value is trying to optimize our Pages as much as it can it's trying to build them aesthetically as much as it can and caches them as much as it can and if we leave this revalidate to false which is a default Behavior it's not going to revalidate our resources unless we are using a dynamic function now the other option is to set revalidate to zero which will ensure that layout or page is always dynamically rendered even if no Dynamic function or dynamic data features are discovered Now setting revalidate to zero is the equivalent of setting Dynamic to force Dynamic which we saw earlier in our SSR component so instead of exporting Dynamic we could have exported revalidate to zero which basically does the same thing and it ensures that our pager layout is always dynamically rendered now this was just a side note but to actually see the revalidation of our statically built Pages let's go back to our ISR folder and inside of our page that renders the same component as you can see here we're fetching the to Do's we're just exporting the revalidate config option and we're setting it to 10 seconds which instructs next JS that after 10 seconds we want to revalidate the cache regenerate this page and then show the regenerated updated page to the next user from that point on now to test this out if I go back to my home page and access this ISR or revalidate path which points to forward slash ISR where this component is responsible for rendering the page and actually add another to do tasks over here we won't be able to see this immediately on our list because we've set the revalidate property to 10 seconds which means that next.js is going to invalidate the cache after 10 seconds regenerate this page aesthetically and serve it up therefore if I refresh this page after the 10 second I should be able to see that last six to do tasks that we just added great let's recap so far we have looked at static search generation SSR or server side rendering and incremental static Regeneration all with the use of exporting route config options in the beginning we looked at the dynamic option we can export from every page this would Define or change the behavior of a page from fully static to fully Dynamic the default was Auto which meant next JS is going to try to statically generate as much as it can if we wanted to force a static we could have set it to error which would force building these Pages aesthetically and it will 404 if you're trying to access a dynamic function or a dynamic data fetching we did the same thing on our SSR page we just set it to force Dynamic and this would cause this page to be rendered dynamically they also saw that instead of this we could have exported the revalidate 0 which has the same effect of making sure this page is dynamically rendered and then on the incremental static regeneration we just export a revalidate set to a positive number of seconds which is the frequency of revalidation for this specific page now so far we've only looked at static Pages inside of our route segments how should we go about these Dynamic paths that are responsible for rendering this individual to do tasks let me just close this pages and let's start with static site generation or SSG let's dive into this Dynamic ID path and the page component inside of it which is responsible for rendering this individual to do task ignore this generates static prompts function up top for now what we're doing down here is if you're exporting a react server component that's responsible for rendering that page it receives the prams object from next.js and on it the ID of the page that the user is trying to access we are using this ID and the function get to do by ID from our library to fetch this specific ID from our mongodb and return it to our page component if we find it to do with that ID if you're going to render the title and if there is no to do with that specific ID we are returning this not found function which we imported from next navigation this is a new function which basically returns a 404. now let's look at this generate static prams function that's similar to get static paths inside the Pages directory if I go back to the documentation and as a refresher inside of the Pages directory for a dynamic path such as this ID alongside the get static props which actually Returns the data to the page component you have to export a function called get static paths which tells next JS what paths to actually generate statically at build time similar to that we have the generate static params in the app directory which again returns an array of paths you want next to us to generate statically at build time but there's a subtle difference between the two functions and that mainly is for the Pages directory for your Dynamic segments like this Dynamic ID If you eliminate this get static paths function this would error out because next.js doesn't know what to do or what pages to generate statically whereas inside of the app directory If you eliminate this function altogether or back in our own example if we comment this out our page component will still run and it will still try to fetch this to do and render this page on demand at request time dynamically so this generates static prams function acts more like an optimization technique you could use to tell next.js what paths or what pages it can generate statically at build time now the reason for this behavior is this Dynamic prams config option that works together with this generate static prompts if I go back to the docs for Route segment config options we've been looking at in this video one of the config options we can export from a page is this Dynamic params this works together with generate static params to tell next JS what should happen if a user is trying to access a page that we did not generate statically or we did not return from this function so if I scroll down to the dynamic prams part you can see can either be true or false the true which is the default means that the dynamic segment not included in the generated static params in this function are going to be generated on demand or dynamically at request time and if you set it to false the segments that are not returned from generated static problems will return a 404. so let's come back to our page and see what happened actually here so if we eliminate this and we don't have that set because the dynamic params is already defaulting to true even if we eliminate this generate static params from the page it will still try to render this page dynamically because this defaults to true and the true is to generate pages on demand that's why if we eliminate this function it still works in the app directory whereas in the Pages directory If you eliminate get static paths it will error out now if you want to disable this Behavior you can export your generate static prompts and actually set your Dynamic prompts to false so therefore if the user is trying to access a path that you did not return from generate static Rams it's going to 404. this is similar to the fallback property inside the Pages directory so if I go back to the documentation indicate static paths inside the Pages directory we could set this fallback option inside of our get static paths function which would determine what should happen if the user is trying to access a path that we have not created it could be true false or blocking and it's set to True next.js is going to show a fallback state to the user it's going to then generate that page on demand and then swap the fallback with the page component once it's created if you set the file back to false it's going to return an error return at 404 and the blocking was to block the browser until the page is generated and then render the page so this is similar to what we have in the route segment options with this Dynamic params we only have true and false we don't have the blocking option because when it is set to true and we are actually generating the pay it's using react streaming with server components and the difference is negligible so therefore there is no blocking option here it's either true or false true meaning that if the user is trying to access a segment that we didn't return from generative static prams inside of the app directory here it's going to run the page and tries to generate that page on demand and when it is set to false just like the fallback Falls it's going to 404 if the user tries to access a page that's not built statically let's actually see this in action I'm going to comment this out even though it doesn't make any difference because we are running the production server if I go back to the home page for the static path as you can see if you're not seeing those extra tasks we added if I go to this first task we can see this path rendering if I open up mongodb right now let me just open this up and let's say we grab the ID let me just refresh because I think we have six tasks over here if I grab the ID for this last task that we created just close this off now if I go back you see we only see these three tasks over here again this is an SSG or static page at the time we builted this page we only had these three tasks so no matter how many times I refresh I'm not going to see the other tasks but interestingly enough if I go to this first task and actually paste in the ID of that six sixth task we created together we could see this path is generated and rendered dynamically and the reason for it is what we discussed over here this generates static prams at the time of the build ran we had three tasks it instructed next years to build those pages statically but because we are not exporting these dynamic prams function we weren't doing it then it defaults to True which means if you're trying to access a page like this page with this ID that was not returned from this generator static prams this page component is going to run anyways and it's going to generate and render this page on demand dynamically at request time now to contrast this if I set this to false this time meaning that I don't want to generate these Pages dynamically add request time if it's not returned from generate static params I want a 404 let's actually save this and rebuild our application and see how it would act differently so npm run build now if I start the production server by running npm start by actually go back to the index of our SSG or static page we can see all six to do tasks are here and if we try to access each individual one or even the last one it will be created but the difference with this Dynamic params is set to false is now here if I add another one let's say seventh to do task as we can see here this is a static page over here we're not going to see it added to the list here but even if I go to mongodb and let me just open this up and refresh to get this seventh task we just created so I'm going to grab this ID so trying to do the same thing we did before but this time if I just go into this first task and paste in the ID that we got from the seventh task we're going to follow for this time because we set the dynamic params to false which means if the user is trying to access an ID or a path or a value that was not generated or returned from generated static params we're going to 404. okay let's recap so inside of our SSG folder let me just close this off so if you understand what we're doing here so for our static lead generated Pages if we were on the index page this is a static page over here all we needed to do to mimic the get static props function of the Pages directory you had to export this Dynamic config option either leaving alone because it defaults to auto which instructs next.js to Cache as much as possible or set it to error specifically to say hey this page needs to be static and if it is using anything Dynamic just error out and for the dynamic part of it which was this ID all we needed to do to statically build these Pages was to export a function called generate static prams which tells an xjs what paths to actually generate statically and then with the use of this Dynamic prams config option we could decide what should happen if the user is trying to access a segment or a path that has not been generated statically and was not returned from this generate static problems function if it was true which is the default it's going to go ahead and render this page component and try to render that page dynamically at request time and if we set it to false just as how we saw it it 404s now let's actually dive into the SSR and see what happens for rssr page and this Dynamic ID inside of it so at the page level what we did is we exported this dynamic config option and set it to force Dynamic to change this page to a server rendered page so it makes sure that this page is forced to render dynamically at all times we also saw that instead of this we could have just exported the revalidate to zero which does the same thing again we're going to go ahead with what the documentation says about exporting this Dynamic to force Dynamic now for this page that is responsible for rendering that Dynamic part as you can see here this is very similar to the page component that we just saw in the static and it's not exporting any options so let me just open them side by side so inside of the SSG we have this page component over here and inside of this SSR we have this page component over here just close this off we're not actually talking about this so we have these two pages one of them is for SSG which we just saw with the use of this generate static params and dynamic params the other one which is SSR and we want to dynamically render we haven't exported any options and the reason is because this is a dynamic path inside of this ID if we do not include this generate static params next.js is not going to dynamically generate any of these Pages for this SSR so we are not instructing it to build anything statically and as you remember these Dynamic params defaults to true so by me not including anything I'm basically saying don't build anything aesthetically and my dynamic prams option is defaulting to True which means that you need to generate these pages add request time on demand dynamically now to actually demonstrate that this is happening if I go back to my home page and inside the SSR index we can see all the seven tasks are here because this is rendered dynamically so it updates with the latest task we have over here and if I now just open my mongodb and actually go to the first task let's say and edit this task and let's just add some exclamations to the end of the title so let's close this off now if I go ahead and open up this first to-do task we should be able to see this updated task with the exclamation marks again because this page is rendered always dynamically at request time and the reason for it is that we are not exporting the generate static params to build it statically and because the dynamic prompts config option defaults to true it means that any page that wasn't returned from generate static problems in this case we don't even have that function should be always rendered add request time or dynamically on demand this is obviously in contrast with the statically built pages that is not going to change with the updated task now with these two out of the way the only thing remaining is our Dynamic ID inside of our ISR or incremental static regeneration so let's look at that component here as you can see we are still rendering that same page component that features are to do very similar to the static site generation with this generate static Prime so we have the same thing over here we are generating some pages statically the only difference is that we are exporting this revalidate config option with the value of 10 seconds which means that next JS is going to invalidate the cache and regenerate these Pages after 10 seconds now similar to our static page as I explained we can also export this Dynamic false which defines the behavior of the page if the user is trying to access a page that we haven't generated so if we set the default to false what happens is if we create a new page or a new task and the user tries to act access it it's going to 404 whereas without this option if we create a new task and the user is trying to access it it's not from the pages that we built statically the page component will still run we still try to generate that page on demand and for their statically built Pages it's going to revalidate them every 10 seconds so now to see this in action if I go back to our home page and access this ISR or revalidate page we see this first to-do task is still showing the on updated or the state it was at build time if I refresh this page we should be able to see that exclamation marks added to it as you can see here after the 10 seconds next year is regenerated this page and if I go and access this individual task for the first time you can see because it was revalidated this path now has the updated task as well I know we've covered a lot so let's recap to do SSR SSG or ISR in the app directory we learn that we do not have the get server-side props or get static props functions we had in the Pages directory instead we had a simpler API that was working on top of the fetch API and react server components we learned that if you're using the fetch API directly to fetch data inside of our react server components we can pass some options to the fetch that instructs nexjs to Cache the result or not cache the result revalidate or not and therefore create Pages aesthetically or render them dynamically at request time we also learned that if we are not using the fetch API we can export route config options that result in the same behavior specifically we learned about dynamic dynamic prams and revalidate config options now the dynamic option changes the behavior of our page or layout from fully static to fully Dynamic we learned that we can set it to force Dynamic to replicate get server-side props or dynamically render the page on demand or set it to error which replicates the get static props or statically build the page at build time the next one we talked about was revalidate we learned that revalidate would allow us to revalidate or invalidate the cache or regenerate a page that was built aesthetically without having to rebuild and redeploy your app you could set it to false which is the default Behavior it tries to Cache as much as possible and it's not going to revalidate any of our Pages unless it needs to we could set it to zero which would make sure that the page is rendered dynamically always or a positive number which was similar to the revalidate property we could have used in the Pages directory to show the frequency of revalidation to an xjs for that specific page we also talked about the dynamic prams config option that's used with the generate static prams function a similar Behavior to get static paths inside of the Pages directory where all you need you're trying to do is to instruct next.js what dynamic segments you want to be built or generated statically at build time the dynamic prompts config option was just determining what should happen if a user is trying to access a page that wasn't created at real time now I hope this video helped you learn the new mental model for data fetching in next year's app directory if you have any questions like always hit me up in the comments and I'll see you in the next one bye
Info
Channel: Hamed Bahram
Views: 11,688
Rating: undefined out of 5
Keywords:
Id: OJ5GaNVujaw
Channel Id: undefined
Length: 43min 26sec (2606 seconds)
Published: Sun Apr 09 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.