Search code examples
next.jsnext.js13

How to disable route pre-rendering in Next.js?


I am using route handlers.

I have a route such as app/blog/rss.xml/route.ts:

import { getBlogPosts } from '@/routines/getBlogPosts.ts';
import Rss from 'rss';

const SITE_URL = 'https://ray.run';

export const GET = async () => {
  const blogPosts = await getBlogPosts();

  const feed = new Rss({
    description: 'Lessons learned scaling Playwright test automation',
    feed_url: `${SITE_URL}/blog/rss.xml`,
    language: 'en',
    site_url: SITE_URL,
    title: 'Rayrun Blog',
  });

  for (const blogPost of blogPosts) {
    if (!blogPost.publishedAt) {
      continue;
    }

    feed.item({
      author: blogPost.author.name,
      date: blogPost.publishedAt,
      description: blogPost.description,
      guid: `${SITE_URL}/blog/${blogPost.guid}`,
      title: blogPost.title,
      url: `${SITE_URL}/blog/${blogPost.slug}`,
    });
  }

  return new Response(feed.xml(), {
    headers: {
      'content-type': 'application/xml',
    },
  });
};

Next.js tries to pre-render this page when I run next build. How do I disable that?

I've already looked through documentation and there is no mention of this.

I should have mentioned that the problem is that it seems no matter what settings I set, Next.js attempts to pre-render the page, i.e. even if I add export const dynamic = "force-dynamic"; the build fails with error complaining about export const GET = async () => {} failing.

GET fails during the build because the build environment does not have access to the database, i.e. I need to entirely skip GET during build.

The only way I found around this is checking if the variable is unset and returning dummy content, e.g.

export const GET = async () => {
  if (!process.env.POSTGRES_DSN) {
    return new Response('OK');
  }
  // ...
};

The same is also true for sitemap.ts.

Update: Turns out that for routes what Fabio suggested is the correct course of action. However, I was thrown off by the fact that sitemap.ts does not behave that way – it ignores entirely the dynamic attribute. I ended up rewriting sitemap.ts to sitemap.xml/route.ts


Solution

  • As seen in the documentation here, route handlers are statically evaluated by default when using the GET method with the Response object.

    import { NextResponse } from 'next/server';
     
    export async function GET() {
      const res = await fetch("https://example.com/api/test");
      const data = await res.json();
      return NextResponse.json(data);
    }
    

    However if you want a dynamic route handler, one of the following requirements or configuration options need to be met:

    If none of the first three options suit your needs, you could use a segment configuration as seen in the example below:

    import { NextResponse } from 'next/server';
     
    export async function GET() {
      const res = await fetch("https://example.com/api/test");
      const data = await res.json();
      return NextResponse.json(data);
    }
    
    // forces the route handler to be dynamic
    export const dynamic = "force-dynamic";
    

    Please note that stack overflow expects you to do a certain degree on research yourself before posting a question, this answer is curated information from the official documentation, ultimately from the link you have provided yourself.