next.js 13在使用fetch头部时采用动态渲染而不是静态渲染?

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

next js 13 Dynamic rendering instead of Static rendering when using headers in fetch?

问题

我正在和自己争论,要么我没有正确理解接下来的13个新概念,要么这确实是一个 bug?我不确定,非常感谢懂得更多的人提出建议。

我有一个简单的page.tsx文件,位于我的新 Next 13(最新版本)'app' 文件夹中。

当我在该页面中使用fetch获取数据,但没有添加任何头部时,构建(使用yarn/npm build)最终会显示页面在构建时以静态方式构建,但当我添加一个必需的头部(Authorization)时,构建会显示页面以动态方式呈现(根据请求)。

这是我使用的代码:

const getData = async () => {
  const res = await fetch(
    "https://endless-app.onrender.com/api/site-settings",
    {
      headers: {
        Authorization: `Bearer 24653f35c767c9d1ed04f15f143eda0ac12b1cd60d`,
      },
    }
  );
  const data = await res.json();
  return data;
};

export default async function About() {
  const data = await getData();

  return (
    <div>
      <h1>About</h1>
    </div>
  );
}

这导致以动态方式呈现:

next.js 13在使用fetch头部时采用动态渲染而不是静态渲染?

只需从fetch中删除头部,就会以静态方式呈现,就像我希望的那样:

const getData = async () => {
  const res = await fetch(
    "https://endless-app.onrender.com/api/site-settings"
  );
  const data = await res.json();
  return data;
};

非常感谢任何帮助。

谢谢!

英文:

I'm debating with myself that either I didn't understand next 13 new concepts correctly, or it's really a bug ? I'm not sure, and appreciate someone that knows better to suggest what is going on.

I have a simple page.tsx in my 'app' folder of a new next 13 (latest version).

When I fetch data in that page, with fetch, but without adding any headers, the build (yarn/npm build) ends up showing the page is build statically (during build), but when I add a required header (Authorization), the build shows the page is dynamically rendered (per request).

Is it by design? I can't pass a header to the fetch API and render the page statically ?

This is the code I'm using :

const getData = async () =&gt; {
  const res = await fetch(
    &quot;https://endless-app.onrender.com/api/site-settings&quot;,
    {
      headers: {
        Authorization: `Bearer 24653f35c767c9d1ed04f15f143eda0ac12b1cd60d`,
      },
    }
  );
  const data = await res.json();
  return data;
};

export default async function About() {
  const data = await getData();


  return (
    &lt;div&gt;
      &lt;h1&gt;About&lt;/h1&gt;
    &lt;/div&gt;
  );
}  

that ends up as dynamic rendering:
next.js 13在使用fetch头部时采用动态渲染而不是静态渲染?

Just removing the headers from fetch, ends up static rendering, as I like it to be:

const getData = async () =&gt; {
  const res = await fetch(
    &quot;https://endless-app.onrender.com/api/site-settings&quot;
  );
  const data = await res.json();
  return data;
};

next.js 13在使用fetch头部时采用动态渲染而不是静态渲染?

Appreciate any help.

Thank you !

答案1

得分: 4

以下是已经翻译好的部分:

  • 你可以通过在fetch选项中设置cache: "force-cache"来修复这个行为。

  • 如果你正在使用其他https客户端API,你可以设置以下的保留导出以强制静态渲染:

export const revalidate = 'force-cache'
  • 如果你使用fetch API,你的代码将如下所示:
const getData = async () => {
  const res = await fetch(
    "https://endless-app.onrender.com/api/site-settings",
    {
      cache: "force-cache",
      headers: {
        Authorization: `Bearer ********************************`,
      },
    }
  );
  const data = await res.json();
  return data;
};

export default async function About() {
  const data = await getData();

  return (
    <div>
      <h1>About</h1>
    </div>
  );
}
  • 如果你使用类似axios这样的HTTP客户端API,那么你必须使用保留导出revalidate,并将其设置为'force-cache',如果它们不提供重新验证选项:
import axios from "axios";

const getData = async () => {
  const res = await axios.get("https://jsonplaceholder.typicode.com/posts", {
    headers: {
      Authorization: `Bearer ********************************`,
    },
  });
  return res.data;
};

export default async function About() {
  const data = await getData();

  return (
    <div>
      <h1>About</h1>
    </div>
  );
}

export const revalidate = "force-cache";

请注意,这个选项不会覆盖单独fetch请求中设置的revalidate值。因此,第二个选项对于fetch API不起作用,因为他们已经使用了带有cache: 'force-cache'属性的重新验证选项。

这也在新的nextjs 13 beta文档中有记录,位于CachingRoute Segment Config Options

英文:

You can fix that behaviour if you set cache: &quot;force-cache&quot; inside your fetch options.

If you are using another https client api, you can set the following reserved export to force static rendering:

export const revalidate = &#39;force-cache&#39;

So your code would look like this if you use the fetch api:


const getData = async () =&gt; {
  const res = await fetch(
    &quot;https://endless-app.onrender.com/api/site-settings&quot;,
    {
      cache: &quot;force-cache&quot;,
      headers: {
        Authorization: `Bearer ********************************`,
      },
    }
  );
  const data = await res.json();
  return data;
};

export default async function About() {
  const data = await getData();


  return (
    &lt;div&gt;
      &lt;h1&gt;About&lt;/h1&gt;
    &lt;/div&gt;
  );
}  

If you are using another http client api like axios, then you have to use the reserved export revalidate and set it to 'force-cache' if they don't provide revalidation option:

import axios from &quot;axios&quot;;

const getData = async () =&gt; {
  const res = await axios.get(&quot;https://jsonplaceholder.typicode.com/posts&quot;, {
    headers: {
      Authorization: `Bearer ********************************`,
    },
  });
  return res.data;
};

export default async function About() {
  const data = await getData();

  return (
    &lt;div&gt;
      &lt;h1&gt;About&lt;/h1&gt;
    &lt;/div&gt;
  );
}

export const revalidate = &quot;force-cache&quot;;

Keep in mind that this option does not override the revalidate value set by individual fetch requests. So the second option would not work for the fetch api, since they already implemented a revalidation option with the cache: &#39;force-cache&#39; property.

This is also documented under the new nextjs 13 beta documentation under Caching and Route Segment Config Options

答案2

得分: 2

static rendering occurs when the data fetching is cached
if request contains Authorization Header the request will not be cached
https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic-rendering
https://nextjs.org/docs/app/building-your-application/data-fetching/caching

英文:

static rendering occurs when the data fetching is cached

if request contains Authorization Header the request will not be cached

https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic-rendering

https://nextjs.org/docs/app/building-your-application/data-fetching/caching

答案3

得分: 1

我不认为您试图实现的内容可以通过用户令牌/cookie来实现,如果授权令牌本身来自外部 API,就像这篇文章中使用的 Next.js v12一样,可能是可能的。

根据当前的/app v13文档:

如果使用动态方法(next/headers、export const POST或类似方法)并且fetch是POST请求(或使用授权或cookie标头),则不会缓存请求。

.....

请注意,动态函数始终将路由选为动态渲染,不论数据获取是否被缓存。换句话说,静态渲染不仅取决于数据获取行为,还取决于路由中使用的动态函数。

...

动态函数依赖于只能在请求时知道的信息,例如用户的 cookie、当前请求标头或URL的搜索参数。

英文:

I don't think what you're trying to achieve is possible with a user token/cookie, it may be possible if the Authorization token itself comes from the external api like in this article using next v12.

Per the current /app v13 docs:

Requests are not cached if:
Dynamic methods (next/headers, export const POST, or similar) are used and the fetch is a POST request (or uses Authorization or cookie headers)

.....

Note how dynamic functions always opt the route into dynamic rendering, regardless of whether the data fetching is cached or not. In other words, static rendering is dependent not only on the data fetching behavior, but also on the dynamic functions used in the route.

...

Dynamic functions rely on information that can only be known at request time such as a user's cookies, current requests headers, or the URL's search params.

huangapple
  • 本文由 发表于 2023年2月26日 22:14:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/75572580.html
匿名

发表评论

匿名网友

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

确定