CSR vs SSR vs SSG
- Client Side rendering
Upside
- Rendering of webpage happens in the browser
- Used with CDN's as rendering happens on the Client Side
- Example - React
Downside
- Not SEO Optimized, web-crawler only reads an empty html file with no info
- Users sees a flash before page renders
- Server Side Rendering
Upside
- Rendering happens on Server Side
- SEO Optimization
Downside
- Expensive since every request needs to be rendered on server
- Harder to scale , can't user CDN
- Static Side Generation
Upside
- Page is generated at build time.
- Same page is reused on every request
- Saves Money by dec. operations
Example -
// Build statically by default
export default async function Blog() {
const res = await fetch("https://sum-server.100xdevs.com/todos");
const data = await res.json();
const todos = data.todos;
console.log("todos");
return (
<div>
{todos.map((todo: any) => (
<div key={todo.id}>
{todo.title}
{todo.description}
</div>
))}
</div>
);
}
Ways to update the page
- using
revalidate
Updating Every 10 seconds
const res = await fetch("https://sum-server.100xdevs.com/todos", {
next: { revalidate: 10 },
});
- Tagging the fetch and then using server action to revalidate
import { revalidateTag } from "next/cache";
const res = await fetch("https://sum-server.100xdevs.com/todos", {
next: { tags: ["todos"] },
});
// ServerAction.ts
// Now we can call this function and our data will get refreshed
("use server");
import { revalidateTag } from "next/cache";
export default async function revalidate() {
revalidateTag("todos");
}
- Using
generateStaticParams
This can be used to statically generate the Dynamic RoutesgenerateStaticParams
is a function that generates a list of params for dynamic routes.
For Ex -
// This code should be in your Dynamic Route component file and is exported.
export async function generateStaticParams() {
const response = await fetch("https://jsonplaceholder.typicode.com/posts");
const posts = await response.json();
// A list of params is returned
return posts.map((post) => ({
postId: post.id.toString(),
}));
}
Also make sure to modify the next.config.js
const nextConfig = {
output: "export",
};
🎯 Bonus - What is difference b/w below 2 codes
Code - 1
export default async function Blog() {
const res = await fetch("https://sum-server.100xdevs.com/todos");
const data = await res.json();
const todos = data.todos;
console.log("todos");
return (
<div>
{todos.map((todo: any) => (
<div key={todo.id}>
{todo.title}
{todo.description}
</div>
))}
</div>
);
}
Code -2
export default function Blog() {
const [todos, setTodos] = useState([]);
useEffect(() => {
const res = fetch("https://sum-server.100xdevs.com/todos")
.then((res) => res.json())
.then((data) => setTodos(data.todos));
}, []);
console.log("todos");
return (
<div>
{todos.map((todo: any) => (
<div key={todo.id}>
{todo.title}
{todo.description}
</div>
))}
</div>
);
}
Code - 1 will run on Server Side & is used in NextJS while Code - 2 will run on Client Side & likely to used in ReactJS.
Happy Coding.