Server-Side Rendering (SSR)
Server-Side Rendering (SSR)
Using the getServerSideProps Function
To perform server-side rendering on a page, use the getServerSideProps function to fetch data and render the page on the server.
// pages/home/index.js
export default function HomePage({ data }) {
return (
<div>
<h1>Welcome to Home Page</h1>
<p>Data: {data.message}</p>
</div>
);
}
export async function getServerSideProps() {
const response = await fetch('/api/data');
const data = await response.json();
return {
props: {
data,
},
};
}API Route
Create an API route to handle requests and return data.
// pages/api/data.js
export default function handler(req, res) {
res.status(200).json({ message: 'Hello from the API!' });
}Fetching Data with getServerSideProps
The getServerSideProps function runs on every request, allowing you to fetch the latest data on the server.
// pages/home/index.js
export default function HomePage({ data }) {
return (
<div>
<h1>Welcome to Home Page</h1>
<p>Data: {data.message}</p>
</div>
);
}
export async function getServerSideProps(context) {
const { req, res } = context;
// Simulate fetching data from a database
const data = await fetch('/api/data', { headers: req.headers })
.then((response) => response.json());
return {
props: {
data,
},
};
}Summary
- Using
getServerSideProps: UsegetServerSidePropsin page components to fetch data and render pages on the server. - Fetching Data: Fetch data on the server using
getServerSideProps. - Conditional Rendering: Decide whether to render the page or redirect based on server-side data.
Static Site Generation (SSG)
Static Site Generation (SSG)
Using the getStaticProps Function
To perform static site generation on a page, use the getStaticProps function to fetch data and generate static pages at build time.
// pages/post/[id].js
import { useRouter } from 'next/router';
export default function PostPage({ post }) {
const router = useRouter();
const { id } = router.query;
return (
<div>
<h1>Post ID: {id}</h1>
<p>Title: {post.title}</p>
<p>Content: {post.content}</p>
</div>
);
}
export async function getStaticProps(context) {
const { params } = context;
const id = params.id;
// Simulate fetching data from a database
const response = await fetch(`https://example.com/api/posts/${id}`);
const post = await response.json();
return {
props: {
post,
},
};
}
export async function getStaticPaths() {
// Simulate fetching all post IDs from a database
const response = await fetch('https://example.com/api/posts');
const posts = await response.json();
const paths = posts.map((post) => ({
params: { id: post.id.toString() },
}));
return {
paths,
fallback: false, // Can be set to 'blocking' or 'unstable_blocking' for dynamic routes
};
}Fetching Data with getStaticProps
The getStaticProps function runs once at build time, allowing you to fetch data and inject it into the page’s props.
// pages/post/[id].js
import { useRouter } from 'next/router';
export default function PostPage({ post }) {
const router = useRouter();
const { id } = router.query;
return (
<div>
<h1>Post ID: {id}</h1>
<p>Title: {post.title}</p>
<p>Content: {post.content}</p>
</div>
);
}
export async function getStaticProps(context) {
const { params } = context;
const id = params.id;
// Simulate fetching data from a database
const response = await fetch(`https://example.com/api/posts/${id}`);
const post = await response.json();
return {
props: {
post,
},
};
}Dynamic Routes with getStaticPaths
The getStaticPaths function defines parameters for dynamic routes, enabling the generation of corresponding static pages at build time.
// pages/post/[id].js
import { useRouter } from 'next/router';
export default function PostPage({ post }) {
const router = useRouter();
const { id } = router.query;
return (
<div>
<h1>Post ID: {id}</h1>
<p>Title: {post.title}</p>
<p>Content: {post.content}</p>
</div>
);
}
export async function getStaticProps(context) {
const { params } = context;
const id = params.id;
// Simulate fetching data from a database
const response = await fetch(`https://example.com/api/posts/${id}`);
const post = await response.json();
return {
props: {
post,
},
};
}
export async function getStaticPaths() {
// Simulate fetching all post IDs from a database
const response = await fetch('https://example.com/api/posts');
const posts = await response.json();
const paths = posts.map((post) => ({
params: { id: post.id.toString() },
}));
return {
paths,
fallback: false, // Can be set to 'blocking' or 'unstable_blocking' for dynamic routes
};
}Using the revalidate Option
Use the revalidate option to specify when a page should be regenerated.
// pages/post/[id].js
import { useRouter } from 'next/router';
export default function PostPage({ post }) {
const router = useRouter();
const { id } = router.query;
return (
<div>
<h1>Post ID: {id}</h1>
<p>Title: {post.title}</p>
<p>Content: {post.content}</p>
</div>
);
}
export async function getStaticProps(context) {
const { params } = context;
const id = params.id;
// Simulate fetching data from a database
const response = await fetch(`https://example.com/api/posts/${id}`);
const post = await response.json();
return {
props: {
post,
},
revalidate: 60, // Regenerate the page every 60 seconds
};
}
export async function getStaticPaths() {
// Simulate fetching all post IDs from a database
const response = await fetch('https://example.com/api/posts');
const posts = await response.json();
const paths = posts.map((post) => ({
params: { id: post.id.toString() },
}));
return {
paths,
fallback: false, // Can be set to 'blocking' or 'unstable_blocking' for dynamic routes
};
}Summary
- Using
getStaticProps: UsegetStaticPropsin page components to fetch data and generate static pages at build time. - Dynamic Routes: Use
getStaticPathsto define parameters for dynamic routes. - Regenerating Pages: Use the
revalidateoption to specify when pages should be regenerated.
Automatic Static Optimization
Enabling Automatic Static Optimization
Without Using Specific Static Generation or Server-Side Rendering Functions
If you do not use getStaticProps, getStaticPaths, getServerSideProps, or generateStaticParams and load functions, Next.js will automatically select the most suitable rendering strategy.
// pages/home/index.js
export default function HomePage() {
return (
<div>
<h1>Welcome to Home Page</h1>
<p>This is a static page.</p>
</div>
);
}How Automatic Static Optimization Works
When Next.js detects that a page does not use the aforementioned functions, it will:
- Static Generation: If the page does not require dynamic data or user authentication, Next.js generates it as a static page.
- Server-Side Rendering: If the page requires dynamic data or user authentication, Next.js performs server-side rendering.
Determining If a Page Is Statically Generated
You can check the __NEXT_DATA__ object’s props property to determine if a page is statically generated.
// pages/home/index.js
export default function HomePage() {
const isStaticGenerated = typeof window !== 'undefined' && !window.__NEXT_DATA__.props;
return (
<div>
<h1>Welcome to Home Page</h1>
<p>{isStaticGenerated ? 'This is a statically generated page.' : 'This is a server-side rendered page.'}</p>
</div>
);
}When to Use Automatic Static Optimization
Automatic static optimization is suitable for the following scenarios:
- No Dynamic Data Required: The page content does not change based on user requests.
- No User Authentication Required: The page is accessible without user login.
- Infrequent Updates: The page content does not require frequent updates.
Summary
- Avoid Specific Functions: If the page does not need dynamic data or user authentication, avoid using
getStaticProps,getStaticPaths,getServerSideProps, orgenerateStaticParamsandloadfunctions. - Check
__NEXT_DATA__: Determine if a page is statically generated by checking the__NEXT_DATA__object. - Applicable Scenarios: Suitable for pages without dynamic data or user authentication requirements.
Client-Side Rendering (CSR)
Client-Side Rendering (CSR) is a rendering mode that allows pages to dynamically load and update content in the client browser. It is typically used for applications requiring real-time interaction, such as chat applications or dynamic forms.
Enabling Client-Side Rendering
Using React Hooks like useEffect or useState
Use React Hooks such as useEffect or useState in page components to handle client-side state and side effects.
// pages/chat/index.js
import { useState, useEffect } from 'react';
export default function ChatPage() {
const [messages, setMessages] = useState([]);
useEffect(() => {
const fetchMessages = async () => {
const response = await fetch('/api/messages');
const data = await response.json();
setMessages(data);
};
fetchMessages();
}, []);
return (
<div>
<h1>Chat Room</h1>
<ul>
{messages.map((message) => (
<li key={message.id}>{message.text}</li>
))}
</ul>
</div>
);
}Using useEffect and useState
Use useEffect to listen for events or perform side effects, and useState to manage page state.
// pages/chat/index.js
import { useState, useEffect } from 'react';
export default function ChatPage() {
const [messages, setMessages] = useState([]);
useEffect(() => {
const fetchMessages = async () => {
const response = await fetch('/api/messages');
const data = await response.json();
setMessages(data);
};
fetchMessages();
// Listen for new messages
const handleNewMessage = (event) => {
const newMessage = JSON.parse(event.data);
setMessages((prevMessages) => [...prevMessages, newMessage]);
};
window.addEventListener('message', handleNewMessage);
return () => {
window.removeEventListener('message', handleNewMessage);
};
}, []);
return (
<div>
<h1>Chat Room</h1>
<ul>
{messages.map((message) => (
<li key={message.id}>{message.text}</li>
))}
</ul>
</div>
);
}Dynamic Loading with useEffect
Use useEffect to handle data fetching on initial page load.
// pages/chat/index.js
import { useState, useEffect } from 'react';
export default function ChatPage() {
const [messages, setMessages] = useState([]);
useEffect(() => {
const fetchMessages = async () => {
const response = await fetch('/api/messages');
const data = await response.json();
setMessages(data);
};
fetchMessages();
}, []);
return (
<div>
<h1>Chat Room</h1>
<ul>
{messages.map((message) => (
<li key={message.id}>{message.text}</li>
))}
</ul>
</div>
);
}Handling Events with useEffect
Use useEffect to listen for events or perform side effects.
// pages/chat/index.js
import { useState, useEffect } from 'react';
export default function ChatPage() {
const [messages, setMessages] = useState([]);
useEffect(() => {
const fetchMessages = async () => {
const response = await fetch('/api/messages');
const data = await response.json();
setMessages(data);
};
fetchMessages();
// Listen for new messages
const handleNewMessage = (event) => {
const newMessage = JSON.parse(event.data);
setMessages((prevMessages) => [...prevMessages, newMessage]);
};
window.addEventListener('message', handleNewMessage);
return () => {
window.removeEventListener('message', handleNewMessage);
};
}, []);
return (
<div>
<h1>Chat Room</h1>
<ul>
{messages.map((message) => (
<li key={message.id}>{message.text}</li>
))}
</ul>
</div>
);
}Summary
- Using
useState: UseuseStatein page components to manage state. - Using
useEffect: UseuseEffectto handle client-side side effects, such as data fetching and event listening. - Dynamic Data Loading: Use
useEffectto handle data fetching on initial page load. - Event Listening: Use
useEffectto listen for events or perform side effects.



