Next.js
Overview of Next.js
Section titled “Overview of Next.js”Introduction
Section titled “Introduction”Next.js is a React framework that enables developers to build high-performance, scalable web applications with ease. It provides a robust set of features for server-side rendering, static site generation, and client-side rendering, making it a top choice for modern web development.
Why do we need this?
Section titled “Why do we need this?”In the modern web landscape, users demand fast, interactive, and SEO-friendly websites. Traditional client-side rendering (CSR) approaches often lead to slow initial loads and poor SEO. Next.js addresses these challenges by offering hybrid rendering capabilities, allowing developers to choose the optimal rendering strategy for each page, resulting in improved performance, better SEO, and enhanced user experience.
Problem Statement
Section titled “Problem Statement”Developers struggle with balancing performance, SEO, and developer experience when building React applications. Configuring server-side rendering, static generation, and client-side hydration manually is complex and error-prone. There is a need for a framework that abstracts these complexities while providing flexibility and excellent performance out of the box.
Real World Story
Section titled “Real World Story”Netflix faced challenges with their React-based web application, where initial load times were slow due to client-side rendering, impacting user engagement and SEO. After adopting Next.js, they implemented server-side rendering for their landing pages, reducing time-to-interactive by 50% and significantly improving search engine rankings. This allowed them to deliver a faster, more engaging experience to millions of users worldwide.
Real World Analogy
Section titled “Real World Analogy”Think of Next.js as a smart restaurant kitchen. In a traditional restaurant (client-side React), customers wait while chefs prepare each dish from scratch after ordering (slow initial load). In a fast-food restaurant with pre-made items (static generation), common dishes are ready instantly but customization is limited. Next.js is like a hybrid kitchen: popular items are prepped ahead (static generation), while special orders are cooked fresh when ordered (server-side rendering), optimizing both speed and customization.
Visual Explanation
Section titled “Visual Explanation”Next.js simplifies web development by providing a unified framework that handles routing, rendering, and data fetching automatically. Developers focus on building components while Next.js optimizes performance behind the scenes.
Mermaid Diagram 1: Request Lifecycle in Pages Router
Section titled “Mermaid Diagram 1: Request Lifecycle in Pages Router”sequenceDiagram participant User as User participant Browser as Browser participant NextJS as Next.js Server participant CDN as CDN participant DB as Database
User->>Browser: Requests /products/123 Browser->>CDN: Checks for static asset alt Cached CDN-->>Browser: Returns HTML/CSS/JS else Not Cached CDN->>NextJS: Forward request NextJS->>DB: Fetch product data DB-->>NextJS: Return product data NextJS->>NextJS: Render page (SSR/SSG) NextJS-->>CDN: Send HTML CDN-->>Browser: Returns HTML end Browser->>Browser: Hydrate page (if needed) Browser-->>User: Display interactive pageInternal Working
Section titled “Internal Working”Next.js operates through a sophisticated pipeline that combines file-system routing, intelligent rendering strategies, and automatic code splitting. When a request arrives, Next.js first checks if the page can be served as a static asset from the CDN (ISR/SSG). If not, it dynamically renders the page on the server (SSR) or client (CSR) based on the page’s configuration. During rendering, React components are executed, data is fetched, and the resulting HTML is sent to the browser. For interactive pages, JavaScript bundles are sent for hydration, making the page interactive after initial load.
Mermaid Diagram 2: Data Fetching Flow
Section titled “Mermaid Diagram 2: Data Fetching Flow”sequenceDiagram participant Dev as Developer participant NextJS as Next.js Framework participant React as React participant Data as Data Source
Dev->>NextJS: Create page with getServerSideProps NextJS->>NextJS: Identify data fetching method NextJS->>Data: Execute getServerSideProps at request time Data-->>NextJS: Return data NextJS->>React: Pass data as props to page component React->>React: Render component with data React-->>NextJS: Return HTML NextJS-->>User: Send rendered pageArchitecture
Section titled “Architecture”A typical Next.js application follows a modular architecture that separates concerns between routing, components, styling, and data layers. The file-system based routing in the pages or app directory automatically creates routes. Components are organized by feature or route, with shared components in a components directory. Styling can be implemented via CSS Modules, Styled Components, or Tailwind. Data fetching occurs either at build time (getStaticProps), request time (getServerSideProps), or on the client (SWR, React Query). API routes or server actions handle backend logic, enabling full-stack capabilities within the same project.
Mermaid Diagram 3: Application Component Structure
Section titled “Mermaid Diagram 3: Application Component Structure”graph TD A[Root Layout] --> B[Global CSS] A --> C[Navigation] A --> D[Main Content] D --> E[Home Page] D --> F[Product Page] D --> G[Blog Page] E --> H[Product Card] E --> I[Newsletter Signup] F --> J[Product Details] F --> K[Add to Cart] G --> L[Blog Post] G --> M[Comment System] style A fill:#f9f,stroke:#333 D fill:#bbf,stroke:#333Step-by-Step Flow
Section titled “Step-by-Step Flow”- Create a file in the
pagesdirectory (e.g.,pages/about.js) - Export a React component as the default export
- Add content using JSX and Tailwind/CSS classes
- Optional: Export
getStaticPropsorgetServerSidePropsfor data fetching - Optional: Export
getStaticPathsfor dynamic routes - Next.js automatically creates a route at
/about - During build: Pre-render as HTML if using SSG/ISR
- During request: Serve from cache (ISR/SSG) or render on-demand (SSR)
- Browser: Receives HTML + JavaScript for hydration
- User: Sees fast-loading, interactive page
Mermaid Diagram 4: Rendering Strategies Comparison
Section titled “Mermaid Diagram 4: Rendering Strategies Comparison”graph LR A[Request] --> B{Route Type} B -->|Static Page| C[Generate at Build Time] B -->|Dynamic Page| D{Data Fetching Method} D -->|getStaticProps| E[Generate at Build Time + Revalidate] D -->|getServerSideProps| F[Generate on Each Request] D -->|No Data Fetching| G[Generate at Build Time] C --> H[Serve from CDN] E --> H F --> I[Server Render -> Send HTML] G --> H H --> J[Browser Receives HTML] I --> J J --> K[Hydrate with JavaScript] K --> L[Interactive Page]Syntax
Section titled “Syntax”Basic Page Creation
Section titled “Basic Page Creation”export default function HomePage() { return ( <div> <h1>Welcome to My Next.js App</h1> <p>This is the home page.</p> </div> );}Page with Data Fetching (SSR)
Section titled “Page with Data Fetching (SSR)”export async function getServerSideProps({ params }) { const product = await fetch(`https://api.example.com/products/${params.id}`) .then(res => res.json());
return { props: { product } };}
export default function ProductPage({ product }) { return ( <div> <h1>{product.title}</h1> <p>{product.description}</p> </div> );}Page with Static Generation (SSG)
Section titled “Page with Static Generation (SSG)”export async function getStaticPaths() { // Fetch all blog post slugs from CMS const posts = await fetch('https://api.example.com/posts') .then(res => res.json());
return { paths: posts.map(post => ({ params: { slug: post.slug } })), fallback: 'blocking' // or 'false' or true };}
export async function getStaticProps({ params }) { const post = await fetch(`https://api.example.com/posts/${params.slug}`) .then(res => res.json());
return { props: { post }, // Revalidate every 60 seconds revalidate: 60 };}
export default function BlogPost({ post }) { return ( <article> <h1>{post.title}</h1> <time>{new Date(post.date).toLocaleDateString()}</time> <div dangerouslySetInnerHTML={{ __html: post.content }} /> </article> );}API Route
Section titled “API Route”export default function handler(req, res) { res.status(200).json({ message: 'Hello from Next.js API!' });}Basic Example
Section titled “Basic Example”Let’s create a basic “About Us” page:
- Create
pages/about.js - Add a functional component returning JSX
- Start the development server with
npm run dev - Visit
http://localhost:3000/aboutto see the page
import Link from 'next/link';
export default function AboutPage() { return ( <section className="container mx-auto py-12"> <h1 className="text-3xl font-bold mb-6">About Us</h1> <p className="mb-4"> We are a team of passionate developers building amazing web applications with Next.js and React. </p> <Link href="/" className="text-blue-500 hover:underline"> ← Back to Home </Link> </section> );}Explanation:
- We import
Linkfromnext/linkfor client-side navigation - The
AboutPagefunction returns JSX for our page content - We use Tailwind CSS classes for styling (assuming Tailwind is configured)
- The link provides navigation back to the home page
- When exported as default, Next.js automatically creates the
/aboutroute
Intermediate Example
Section titled “Intermediate Example”Let’s create a user profile page that fetches data on each request:
- Create
pages/profile/[id].js - Implement
getServerSidePropsto fetch user data - Create the profile component to display the data
- Visit
http://localhost:3000/profile/1to see the profile
import { useRouter } from 'next/router';
export async function getServerSideProps({ params }) { try { const res = await fetch(`https://jsonplaceholder.typicode.com/users/${params.id}`); if (!res.ok) { return { notFound: true }; } const user = await res.json(); return { props: { user }, }; } catch (error) { return { notFound: true }; }}
export default function ProfilePage({ user }) { const router = useRouter();
if (router.isFallback) { return <div>Loading...</div>; }
return ( <section className="container mx-auto py-8"> <h1 className="text-2xl font-bold mb-4">{user.name}</h1> <div className="grid gap-4"> <div><span className="font-medium">Email:</span> {user.email}</div> <div><span className="font-medium">Phone:</span> {user.phone}</div> <div><span className="font-medium">Website:</span> <a href={user.website} className="text-blue-500">{user.website}</a></div> <div><span className="font-medium">Company:</span> {user.company.name}</div> </div> <Link href="/" className="mt-6 inline-block text-blue-500 hover:underline"> ← Back to Home </Link> </section> );}Explanation:
getServerSidePropsruns on each request, fetching user data from an external API- We handle 404 cases by returning
{ notFound: true }if the user isn’t found - The component receives the user data as a prop and displays it
- We use
useRouterto handle loading states during static generation fallback - The page is server-rendered on each request, ensuring fresh data
Advanced Example
Section titled “Advanced Example”Let’s create a blog that uses ISR to update content without rebuilding:
- Create
pages/blog/[slug].js - Implement
getStaticPathsto define possible routes - Implement
getStaticPropswithrevalidateoption - Create the blog post component
- Visit
http://localhost:3000/blog/first-postto see the post
import Link from 'next/link';
export async function getStaticPaths() { // In a real app, fetch from your CMS const posts = [ { slug: 'first-post', title: 'My First Post' }, { slug: 'nextjs-tutorial', title: 'Next.js Tutorial' } ];
return { paths: posts.map(post => ({ params: { slug: post.slug } })), fallback: 'blocking' // Show fallback until page is generated };}
export async function getStaticProps({ params }) { // In a real app, fetch from your CMS const post = { slug: params.slug, title: 'Understanding ISR in Next.js', content: '<p>Incremental Static Regeneration (ISR) enables you to use static-generation on a per-page basis, without needing to rebuild the entire site.</p>' };
return { props: { post }, // Revalidate every 60 seconds revalidate: 60 };}
export default function BlogPost({ post }) { return ( <article className="container mx-auto py-8"> <h1 className="text-2xl font-bold mb-4">{post.title}</h1> <div dangerouslySetInnerHTML={{ __html: post.content }} /> <Link href="/" className="mt-6 inline-block text-blue-500 hover:underline"> ← Back to Home </Link> </article> );}