ProNextJS
    Professional Next.js Course
    Loading price
    30-Day Money-Back Guarantee
    lesson

    The Full Route Cache

    Jack HerringtonJack Herrington

    Note: In order to build the example code you will need to be running the time-api server

    # from 01-next-caching run
    
    cd ./time-api &&
    pnpm install &&
    pnpm dev
    

    Let's explore the full route cache in the Next.js App Router.

    As the name implies, it caches the entire route. We'll work with a basic Next.js application containing a single route. When refreshed, it displays a new time.

    The Example App

    Our application is a standard Next.js setup with shadcn and Tailwind for styling.

    When we load the page, we see the current time displayed. The time updates with each refresh.

    Here's the code for our page component:

    // inside src/app/page.tsx
    export default function Home() {
      console.log(`Rendering / ${new Date().toLocaleTimeString()}`);
      return (
        <main>
          <div>{new Date().toLocaleTimeString()}</div>
        </main>
      );
    }
    

    This code logs the current time to the console and also renders it within a div element.

    When running in development mode, hitting refresh updates the displayed time, generating a new console log entry with each refresh.

    However, things behave differently in production mode.

    After building the app with the next build command and starting it in production mode (next start), refreshing the page consistently displays the same time. This behavior stems from Next.js's ability to recognize and treat this route as static during the build process.

    Static and Dynamic Routes

    Next.js classifies routes as either static or dynamic. Our page, as it stands, is a static route. It doesn't involve elements that would necessitate re-rendering on the server for each request.

    generating static pages during build

    The build process generates static HTML for these routes, resulting in the same content served on each request. Static routes are great for performance, as they eliminate server roundtrips for unchanged content.

    Conversely, dynamic routes require server-side rendering for every request.

    Inspecting the route table generated after building a Next.js application can tell you if a route is static.

    Here is our route table:

    Route table shows / is static

    Notice the "O" next to the / route. This "O" signifies a statically generated route. Static routes are optimal for performance, but there are times when you might want to force a route to render dynamically.

    Forcing Dynamic Rendering

    There are situations where you might want to force a route to render dynamically. Let's look at a couple of ways to achieve this.

    Using unstable_noStore

    One approach is to use the unstable_noStore function from next/cache. By invoking this function within our React server component, we signal to Next.js that the route should be treated as dynamic.

    Here's how we incorporate it:

    // inside app/page.tsx
    
    import { unstable_noStore as noStore } from 'next/cache';
    
    export default function Home() {
      unstable_noStore();
      console.log(`Rendering / ${new Date().toLocaleTimeString()}`);
      ...
    

    After rebuilding and starting the application, we can see that the / route is now marked with an "F", indicating it is a dynamic route:

    the f means we have a dynamic route

    Refreshing the page now generates a new time on each request. The unstable_noStore function effectively prevents Next.js from statically generating the route.

    The route table, generated during the build process, serves as the definitive guide for understanding how Next.js handles caching for your routes.

    Other Ways to Force Dynamic Rendering

    unstable_noStore isn't the only way to indicate that a route is dynamic. Actions within the component that suggest dynamic behavior can also achieve this. For instance, accessing properties of the incoming request can signal to Next.js that the component needs dynamic rendering.

    Can you think of methods to access the incoming request within a React server component?

    We'll look at some in the next lesson.

    Transcript

    The first Next.js App Writer cache we're going to take a look at is the full route cache. It does as you'd expect, it caches the full route. All right, let's take a look at our example application. It is a very simple application with a single route that when I hit refresh on it, it gives me a new time of day. Let's go take a look at the code.

    The code is a stock Next.js application. I've added shad-cn and tailwind to give us some nice formatting for a button. Let's take a look at the code for page. The page simply does a console log where it gives us the time, and then it puts that same time into a div on the page. If we take a look at our console we can see that every time we hit refresh we get a new value.

    The reason that that's happening is because we are in dev mode. If I build this and then I start that built code, so I'm now running in production mode as opposed to dev mode. If I go back into my browser and I hit refresh, I always get the same value over and over again. So why is that? Well, the reason is that during build time, Next.js has figured out that this is a static route.

    Let's go take a look at that. So as it did generating static pages, it rendered that route and decided that it wasn't doing anything that was dynamic. Therefore, it could be statically generated, saved off, and then anytime you access that page, it just gives you the static version as opposed to going back to the server and rendering a new dynamic version. So there's two different types of routes. There is the static route, which our page currently is, and there are dynamic routes.

    Dynamic routes always go back to the server for every single request. We can also see down in the route table that's given to us at the end of any Next.js build, the slash route has been marked with an O. And the O in this case means that it is a static route. Now, static routes are actually really good for performance. You want a route to be static for as long as you possibly can.

    Going back to the server every time to get a new page is very inefficient. But let's go and see different ways that you can mark a route as dynamic if you want to do that. So one way to do that is simply to say no store. We bring in unstable no store from Next Cache and we invoke that as part of the RSC. Now, let's try to run it and build it again.

    But I got to tell you over here in the package, I added a new script because I'm going to be doing this so often called build and start. It does a build and a start. So let's do that instead. And now if we look at our route table we can see that slash is marked with an F meaning that it's a function, it's dynamic. So if I go back over to my browser, I can refresh and I can see new times every second.

    So it is now a dynamic route. This route table is really the source of truth when it comes to this particular cache. You wanna look at this table and see, has Next.js decided that this is a static or a dynamic route depending on what you need it to be. Now, unstable node store is not the only way that you can say that a route is dynamic, you can actually just do things in your component that indicate to Next.js that your component is dynamic. One of those is to look at the incoming request.

    So can you think of a couple of ways that I can access the incoming request from a React server component that would indicate to Next.js that this is going to be a dynamic component? I'll tell you what those are in the next video.