Q1: Explain the difference between Server Components and Client Components. When would you use each?
Concept: React Server Components (RSC) render exclusively on the server. Their code is not included in the client-side bundle. Client Components are standard React components that are hydrated on the client.
Usage:
- Server Components (Default): Use for fetching data, accessing backend resources (DB), keeping sensitive info (API keys), and reducing client bundle size.
- Client Components (
'use client'): Use for interactivity (onClick, onChange), using State/Effects (useState, useEffect), or using browser-only APIs (localStorage, window).
Gotcha: You cannot import a Server Component into a Client Component directly. You must pass it as a children prop (Composition Pattern).
Q2: How does the App Router handle Layouts vs Templates?
Layout (layout.js): Wraps pages and preserves state on navigation. It does not re-render when navigating between sibling routes.
Template (template.js): Similar to a layout, but it creates a new instance for each child on navigation. State is reset.
Use Case: Use templates for features that rely on useEffect (like logging page views) or animation libraries (framer-motion) that need to trigger on every page transition.
Q3: What are Parallel Routes and Intercepting Routes?
Parallel Routes (@folder): Allow rendering multiple pages in the same layout simultaneously (e.g., a dashboard with @team and @analytics slots).
Intercepting Routes ((.)folder): Allow loading a route within the current layout while keeping the URL context (e.g., opening a photo in a modal when clicked from a feed, but as a full page on refresh).
Q4: How does Next.js handle Static vs Dynamic Rendering?
Static Rendering (Default): Routes are rendered at build time. Data is cached indefinitely.
Dynamic Rendering: Routes are rendered at request time. This happens automatically if you use:
- Dynamic functions:
cookies(),headers(). searchParamsprop in a page.no-storefetch requests.
Forcing Dynamic: export const dynamic = 'force-dynamic'
Q5: What are Route Handlers?
Definition: Route Handlers allow you to create custom request handlers for a given route using the Web Request and Response APIs. They replace API Routes from the Pages Router.
File: Defined in a route.js or route.ts file inside the app directory.
// app/api/users/route.js
export async function GET(request) {
const data = await fetchUsers();
return Response.json({ data });
}
Supported Methods: GET, POST, PUT, PATCH, DELETE, HEAD, and OPTIONS.
Q6: How does Data Revalidation work in the App Router?
Revalidation allows you to update cached data without rebuilding the entire site.
- Time-based Revalidation: Automatically revalidate data after a certain amount of time has passed.
fetch('...', { next: { revalidate: 3600 } }) - On-demand Revalidation: Manually revalidate data based on an event (e.g., form submission).
revalidatePath('/blog')orrevalidateTag('posts')
Q7: What is the purpose of Middleware in Next.js?
Function: Middleware allows you to run code before a request is completed. You can modify the response by rewriting, redirecting, modifying request headers, or responding directly.
Common Use Cases:
- Authentication and Authorization (protecting routes).
- Server-side Redirects (e.g., based on user role or locale).
- A/B Testing (rewriting to different variants).
- Bot protection.
Location: Defined in middleware.js at the root of your project.
Q8: What is the `generateStaticParams` function?
Purpose: It is the replacement for getStaticPaths in the App Router.
Usage: It allows you to generate static routes at build time for dynamic segments (e.g., /blog/[slug]).
export async function generateStaticParams() {
const posts = await getPosts();
return posts.map((post) => ({
slug: post.slug,
}));
}
Q9: How do you handle errors in the App Router?
File: Create an error.js file in the route segment.
Mechanism: It automatically wraps the page in a React Error Boundary. If an error occurs during rendering, the error.js component is displayed instead of crashing the whole app.
Recovery: The component receives a reset() function prop to attempt to re-render the segment.