nicoalbanese / kirimase

Build full-stack Next.js apps, incredibly fast
https://kirimase.dev
MIT License
2.63k stars 120 forks source link

[Feature Request] Prepare for Partial Prerendering #87

Open leerob opened 11 months ago

leerob commented 11 months ago

While Partial Prerendering is not yet stable, we can start building apps that prepare for this model today to make enabling PPR as easy as flipping on the compiler optimization. The key is to move data fetches and other dynamic calls (like cookies or headers) down in the component tree and to wrap them with React Suspense.

For example, I saw some of the authentication code that marked a top level component as async, and then at the top of the component file made a call to get the user state. We might want to consider whether that is always necessary. For example, for routes where it's all or nothing for auth, Middleware might be a better place to put this logic. For routes where it's not, consider moving the auth promise further down in the tree, colocated in a component that is consuming it's data.

Since the entire route can be prerendered, including the Suspense fallback, this can help you more easily design loading states and have a very fast initial page load.

Example: https://github.com/leerob/leerob.io/blob/e9357c5d53737ae977d4bfcb1b58ac832d155b5f/app/page.tsx#L117-L132

Resources

nicoalbanese commented 9 months ago

Hey @leerob 👋

I've moved all of the data fetching down one level (wrapped with suspense) eg:

import { Suspense } from "react";

import Loading from "@/app/loading";
import NobelPrizeList from "@/components/nobelPrizes/NobelPrizeList";
import { getNobelPrizes } from "@/lib/api/nobelPrizes/queries";
import { getAuthors } from "@/lib/api/authors/queries";
import { checkAuth } from "@/lib/auth/utils";

export const revalidate = 0;

export default async function NobelPrizesPage() {
  await checkAuth();

  return (
    <main>
      <div className="relative">
        <div className="flex justify-between">
          <h1 className="font-semibold text-2xl my-2">Nobel Prizes</h1>
        </div>
        <NobelPrizes />
      </div>
    </main>
  );
}

const NobelPrizes = async () => {

  const { nobelPrizes } = await getNobelPrizes();
  const { authors } = await getAuthors();
  return (
    <Suspense fallback={<Loading />}>
      <NobelPrizeList nobelPrizes={nobelPrizes} authors={authors} />
    </Suspense>
  );
};

Just re-reading your note and see you mentioned auth calls too. Assume that means it will be necessary to move the checkAuth() call down to that component too?