Fetching data on the server

指的是在畫面渲染前,就先在server端取得好資料,這樣做的好處是可以提高SEO性能,使用者體驗及確保資料安全性。(SSR, SSG, ISR都是此方式)

在本地裝置啟用Next13的server component,可以看到API資料並不會在client端進行(network除錯上無顯示),而是會在本地端所運行的server上執行

// posts/page.js
const getPosts = async () => {
  const res = await fetch("<https://jsonplaceholder.typicode.com/posts>");
  const data = await res.json();
  return data;
};

const Posts = async () => {
  const posts = await getPosts();
  return (
    <div>
      {posts.map((item, index) => (
        <p key={index}>{item.title}</p>
      ))}
    </div>
  );
};

export default Posts;

截圖 2024-06-13 17.34.08.png

Parallel and sequential data fetching

https://martinfowler.com/articles/data-fetch-spa.html#parallel-data-fetching

Parallel Data Fetching

並行取得數據,通過並行請求數據節省時間,但在兩個Promise解決前無法看到結果

// posts/page.js
const getPosts = async () => {
  const res = await fetch("<https://jsonplaceholder.typicode.com/posts>");
  const data = await res.json();
  return data;
};
const getComments = async () => {
  const res = await fetch("<https://jsonplaceholder.typicode.com/comments>");
  const data = await res.json();
  return data;
};

const getDelayData = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve([1, 2, 3, 4]);
    }, 3000);
  });
};

const Posts = async () => {
  // 所有資料會等待delayData完成後才會顯示
  const [posts, comments, delayData] = await Promise.all([
    getPosts(),
    getComments(),
    getDelayData(),
  ]);

  return (
    <div>
      {posts.map((item, index) => (
        <p className="text-yellow-500" key={index}>
          {item.title}
        </p>
      ))}
      <hr />
      {comments.map((item, index) => (
        <p key={index}>{item.name}</p>
      ))}
      <hr />
      {`delayData: ${delayData}`}
    </div>
  );
};

export default Posts;

Sequential Data Fetching

順序取得數據,在某先情況下B資料需等待A資料完成才能進行

ISR(Incremental Static Regeneration) & ISSG(Incremental Static Site Generation)

兩者指的皆是在建構時預產生頁面,並在發出請求時重新更新頁面,在保持靜態頁面效能時又能確保內容是最新的。

在next.js中,可以透過fetch api的revalidate來控制暫存多久後需要更新資料

import Image from "next/image";

const getRandomPic = async () => {
  const width = 300;
  const height = 200;
  const res = await fetch(`https://picsum.photos/${width}/${height}`, {
    next: { revalidate: 50000 },
  });
  const url = res.url;
  return { url, width, height };
};
const Pic = async () => {
  const randomPic = await getRandomPic();

  return (
    <Image
      src={randomPic.url}
      alt="pic"
      width={randomPic.width}
      height={randomPic.height}
    />
  );
};

export default Pic;

參考:

https://juejin.cn/post/7232879267625156664

https://dhc.ink/archives/1708666582806

Next.js 13 教學 - Data Fetching (Static, Dynamic, Cache, SSR, SSG, ISR) (Next.js 教學)