FE3: Server rendering with Next.js
Loading data on the server
🎯You'll be able to
Load data on the server with sensible caching and revalidation, and handle loading and error states.
🏠The everyday picture
A waiter who checks the kitchen before taking you to your table can tell you straight away what's available. A waiter who seats you first and then goes to check makes you wait at an empty table.
📘What it really is
-
Server components can fetch data directly (from an API or a database) before the page is sent, so the user doesn't wait for a second round trip from the browser.
-
Caching and revalidation: you can mark data to be cached and refreshed after a time (
revalidate) or on demand (after a price change). Caching defaults have changed between Next.js versions, so check the documentation for yours. -
Parallel fetching: start independent requests together (
Promise.all) instead of one after another. - Streaming: with
loading.tsxorSuspense, the page shows its shell first and fills in slower parts as they arrive. - Mutations: forms can post to the server (Next.js server actions or an API route), then revalidate the affected pages.
- Secrets stay on the server: API keys used in server components never reach the browser, as long as they aren't passed to client components or exposed through public environment variables.
📝A worked example
Kirana's product page needs the product, the store's stock and three "often bought together" items:
const [product, stock, related] = await Promise.all([
getProduct(id), getStock(storeId, id), getRelated(id)
]);
| Approach | Time before content shows |
|---|---|
| Three fetches one after another | 900 ms |
Promise.all in parallel |
420 ms |
| Parallel, with "related" streamed in later | 260 ms for product and stock; related appears ~200 ms later |
🌍Where it's used
- Product, article and profile pages.
- Dashboards that combine several data sources.
- Forms that save to a database.
📝Case scenario
After an admin changes the price of a 5 kg atta bag, the product page still shows the old price for an hour. The page is cached with a one-hour revalidation. You add on-demand revalidation for that product's page whenever its price is saved, so the new price shows within seconds, while the page stays fast for everyone else.
🖱️Try it
Build the Kirana product page to load three pieces of data, first one after another, then in parallel, then with one streamed. Time each version with the Network tab or server logs.
⚠️Common mistakes
- Fetching on the client what the server already has. Sign: a spinner on a page that could have arrived complete. Fix: fetch in the server component.
- Caching personal data for everyone. Sign: one user sees another's details. Fix: never cache per-user data as shared static output.
🛠️For your project
If you add a real product API to Kirana Express, decide its revalidation time and write it in your Project 2 notes.
✅Quick check
Why use Promise.all for independent requests?
Show the answer
So they run at the same time instead of waiting for each other.
How can a page show a new price immediately without giving up caching?
Show the answer
Revalidate that page on demand when the price is saved.
