如何在Next.js中禁用路由预渲染?

huangapple go评论87阅读模式
英文:

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

问题

我正在使用路由处理程序

我有一个路由,如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尝试在运行next build时预渲染此页面。如何禁用它?

我已经查阅了文档,但没有提到这一点。

我应该提到的问题是,似乎无论我设置什么设置,Next.js都会_尝试_预渲染页面,即使我添加export const dynamic = "force-dynamic";,构建仍然会出错, complaining about export const GET = async () => {}失败。

GET在构建期间失败,因为构建环境无法访问数据库,即我需要在构建期间完全跳过GET

我找到的唯一解决方法是检查变量是否未设置并返回虚拟内容,例如:

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

对于sitemap.ts也是一样的。

更新:原来对于Fabio建议的路由来说,是正确的操作方式。然而,我被sitemap.ts的行为所困扰 - 它完全忽略了dynamic属性。最终,我将sitemap.ts重写为sitemap.xml/route.ts

英文:

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

答案1

得分: 1

如在这里的文档中所示,路由处理程序在使用 Response 对象和 GET 方法时默认是静态评估的。

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);
}

然而,如果您想要一个动态路由处理程序,需要满足以下要求或配置选项之一:

  • 使用 Request 对象与 GET 方法。
  • 使用任何其他 HTTP 方法。
  • 使用动态函数cookiesheaders
  • 分段配置选项手动指定动态模式。

如果前三个选项都不符合您的需求,您可以使用如下示例中所示的分段配置:

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);
}

// 强制路由处理程序为动态
export const dynamic = "force-dynamic";

请注意,Stack Overflow 期望您在发表问题之前进行一定程度的研究,此答案是从官方文档中筛选出的精选信息,最终来源于您提供的链接。

英文:

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.

huangapple
  • 本文由 发表于 2023年7月3日 19:26:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76604290.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定