+1 (843) 212-6898+8801897661858
Whatsapp-colorCreated with Sketch.
sales@mediusware.comSchedule A Call
Logo
Company
Services
Hire Developers
Industries
Case StudySTART FREE TRIALicon

About

Who We Are

Our Team

Blogs

Women Empowerment

Career

CSR

Delivery Models

Engagement Model

Services

Software Development

Web Development

Mobile App Development

E-commerce Development

Software Development

Enterprise Solutions

UI/UX Design

API Integration

Technology

React.js

Vue.js

Angular js

Laravel

Android

Flutter

iOS

React Native

Hire Developers

Hire Mobile App Developers

Hire Front-end Developers

Hire Backend Developers

Hire E-commerce Developers

Hire Developers

Hire Android Developers

Hire iOS Developers

Hire Swift Developers

Hire Flutter Developers

Hire React Native Developers

Hire Django Developers

Hire Node.js Developers

Hire Laravel Developers

We shape the art of technology
Headquarter

Headquarter

1050 Johnnie Dodds Blvd Mount Pleasant South Carolina USA ,Zip- 29464

sales@mediusware.io

+1 843-212-7149

Bangladesh Office

Bangladesh Office

24/1, Taj Mahal Road, Shiya Masjid mor, Floor - 8th & 9th, Ring Road, 1207, Dhaka, Bangladesh

sales@mediusware.com

+8801897661858

© 2025 Mediusware. All Rights Reserved

Terms & ConditionsPrivacy Policy

Table of contents

  1. Introduction
  2. Why use Next.js for React applications?
  3. How routing works in Next.js?
  4. Automatic Code Splitting in Next.js
  5. Server-side Rendering (SSR)
  6. Static Site Generation (SSG)
  7. Incremental Static Regeneration (ISR)
  8. API Routes & Data Fetching in Next.js
  9. Next.js Server Actions
  10. Authentication in Next.js
Share This Blog !
Get the best of our content straight to your inbox!

Don’t worry, we don’t spam!

Next.js Fundamentals: A Comprehensive Guide

Next.js Fundamentals: A Comprehensive Guide image

Last Update: 18 Oct 2024

Introduction

What is Next.js? 

Next.js is a powerful React framework that simplifies the process of building web applications, especially those that require server-side rendering (SSR) or static site generation (SSG). By providing a structured approach and built-in features, Next.js helps developers create high-performance, scalable, and SEO-friendly applications.

Brief history and development

Next.js was first released in October 2016 by Vercel (formerly Zeit), a company founded by Guillermo Rauch. The framework was born out of the need to simplify and improve React application development, particularly in areas where React alone fell short.

Key milestones in Next.js history:

  • 2016: Initial release of Next.js
  • 2018: Introduction of dynamic imports and static exports
  • 2019: Addition of API routes and built-in CSS support
  • 2020: Launch of Next.js 10 with major performance improvements and image optimization
  • 2021: Release of Next.js 11 with improved performance and developer experience
  • 2022: Introduction of Next.js 13 with app directory, server components, and streaming
  • 2023: Release of Next.js 14 with further optimizations and feature enhancements

Throughout its development, Next.js has consistently focused on improving developer experience, performance, and scalability, making it one of the most popular React frameworks in use today.

Why use Next.js for React applications?

Next.js offers several compelling reasons for developers to choose it over vanilla React or other React-based frameworks:

  1. Simplified Server-Side Rendering (SSR): Next.js makes it easy to implement SSR, which can significantly improve initial page load times and SEO.
  2. Static Site Generation (SSG): For content-heavy sites, Next.js provides excellent support for generating static sites, combining the benefits of static hosting with the dynamic capabilities of React.
  3. Automatic Code Splitting: Next.js automatically splits your code into smaller chunks, improving load times and performance without any additional configuration.
  4. File-based Routing: The intuitive file-system based router simplifies the process of creating and managing routes in your application.
  5. API Routes: Next.js allows you to easily create API endpoints as part of your application, simplifying full-stack development.
  6. Built-in CSS Support: With built-in CSS and Sass support, styling your application becomes more straightforward.
  7. Image Optimization: Next.js provides automatic image optimization, helping to improve performance and Core Web Vitals scores.
  8. Developer Experience: Features like Fast Refresh for instantaneous feedback during development enhance the overall developer experience.
  9. TypeScript Support: Next.js has excellent built-in TypeScript support, making it easy to use TypeScript in your projects.

Performance Optimization: Many performance optimizations are handled automatically by Next.js, saving developers time and effort. 

How routing works in Next.js?

1. File-based Routing

Next.js uses a file-system based routing mechanism. This approach simplifies the routing process by automatically creating routes based on the file structure in your project's pages directory. Here's how it works:

  • Each file inside the pages directory becomes a route and The file name determines the route's URL path.
  • Nested folders create nested routes.
  • Special file names like index.js and _app.js have specific roles.

For example:

  • pages/index.js becomes the home route (/)
  • pages/about.js becomes the about route (/about)
  • pages/blog/index.js becomes the blog index route (/blog)
  • pages/blog/[slug].js becomes a dynamic route for blog posts (/blog/:slug)

2. App Routing in Next.js

Next.js 13 introduced the App Router, which builds upon the file-based routing concept but offers more flexibility and powerful features.

Key features of the App Router:

  1. Supports nested layouts
  2. Server Components by default
  3. Simplified data fetching
  4. Supports parallel routes and intercepting routes

Here's how it works:

  • Each folder in the app directory represents a route segment
  • Files named page.js define the unique UI of a route
  • Files named layout.js define shared UI for multiple pages
  • Special file names like loading.js and error.js provide built-in UX features

Example of App Router structure: 

app/
├── page.js
├── about/
│   └── page.js
├── blog/
│   ├── page.js
│   └── [slug]/
│       └── page.js
└── layout.js

Example Code Snippet for App Router: 

// app/page.js
export default function Home() {
  return <h1>Welcome to the Home Page</h1>
}

// app/about/page.js
export default function About() {
  return <h1>About Us</h1>
}

// app/blog/page.js
export default function BlogIndex() {
  return <h1>Blog Posts</h1>
}

// app/blog/[slug]/page.js
export default function BlogPost({ params }) {
  return <h1>Blog Post: {params.slug}</h1>
}

// app/layout.js
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}

3. Dynamic Routing in Next.js 

Creating Dynamic Routes:

  • Use square brackets ([]) to define dynamic segments in your route paths. For example: [id].
  • Create a corresponding component file in the pages directory.
// pages/blog/[id].js
import { useRouter } from 'next/navigation';

function BlogPost() {
  const router = useRouter();
  const { id } = router.query;

  return (
    <div>
      <h1>Blog Post: {id}</h1>
    </div>
  );
}

export default BlogPost;

Handling Parameters:

  • Access the dynamic parameters using the useRouter hook and the query object.

Use Cases:

  • Creating dynamic product pages based on product IDs.
  • Building user profiles based on usernames or IDs.
  • Generating blog posts or articles with unique URLs.
  • Implementing search functionality with dynamic query parameters.

Automatic Code Splitting in Next.js

What is code splitting?

Code splitting is a technique that breaks down large JavaScript bundles into smaller, more manageable chunks. These chunks are then loaded on demand, which can significantly improve the initial load time of your application.

How Next.js implements it automatically:

Next.js provides automatic code splitting out of the box. It achieves this through a few key mechanisms:

  • Page-based splitting: Each file in the pages directory (or app directory for App Router) becomes its own JavaScript bundle.
  • Dynamic imports: Next.js supports dynamic import() statements, which allow you to load modules on demand.
  • Prefetching: Next.js automatically prefetches the code for other pages in the background, making navigation feel instant.

Benefits for performance:

  • Faster initial load times: Only the code necessary for the current page is loaded initially.
  • Improved caching: Smaller, separate chunks can be cached more efficiently.
  • Reduced memory usage: Less unused code is kept in memory.
  • Faster navigation: Prefetching ensures smooth transitions between pages. 

Code Examples:

// pages/index.js
export default function Home() {
  return <h1>Welcome to the home page!</h1>
}

// pages/about.js
export default function About() {
  return <h1>About us</h1>
}

In this example, Next.js automatically creates separate bundles for the home and about pages. When a user visits the home page, only the code for that page is loaded.

Dynamic imports for component-level code splitting:

import dynamic from 'next/dynamic'

const DynamicComponent = dynamic(() => import('../components/heavy-component'))

export default function Page() {
  return (
    <div>
      <h1>Page with dynamic import</h1>
      <DynamicComponent />
    </div>
  )
}

Here, HeavyComponent is only loaded when the page renders, not during the initial page load.

Dynamic imports with custom loading component:

import dynamic from 'next/dynamic'

const DynamicComponentWithCustomLoading = dynamic(
  () => import('../components/heavy-component'),
  {
    loading: () => <p>Loading...</p>
  }
)

export default function Page() {
  return (
    <div>
      <h1>Page with dynamic import and custom loading</h1>
      <DynamicComponentWithCustomLoading />
    </div>
  )
}

This example shows how to display a custom loading state while the dynamic component is being loaded.

Server-side Rendering (SSR)

How SSR works in Next.js

In SSR, the HTML is generated on the server for each request. Next.js performs this automatically for every page, unless specified otherwise.

Example of SSR in Next.js:

// pages/ssr-example.js
export async function getServerSideProps() {
  const res = await fetch('https://api.example.com/data')
  const data = await res.json()

  return { props: { data } }
}

export default function SSRPage({ data }) {
  return <div>SSR Page with data: {data.title}</div>
}

In this example, getServerSideProps fetches data on every request, and the page is rendered on the server with this data.

When to  use SSR : Use cases and benefits

  • Real-time data: Good for pages that need to show frequently updated data
  • User-specific content: Useful for personalized pages
  • SEO: Provides fully rendered pages to search engines

Static Site Generation (SSG)

Understanding SSG in Next.js

SSG generates HTML at build time, creating static pages that can be served quickly.

Example of SSG in Next.js:

// pages/ssg-example.js
export async function getStaticProps() {
  const res = await fetch('https://api.example.com/static-data')
  const data = await res.json()

  return { props: { data } }
}

export default function SSGPage({ data }) {
  return <div>SSG Page with data: {data.title}</div>
}

Here, getStaticProps fetches data at build time, and the page is pre-rendered with this data.

When to use SSG

  • Marketing pages
  • Blog posts
  • E-commerce product listings
  • Documentation

SSG is ideal for content that doesn't change frequently and can be generated ahead of time.

Comparison between SSR and SSG: 

1. Build Time vs. Request Time

  • SSG: Pages are generated at build time
  • SSR: Pages are generated at request time

2. Data Freshness

  • SSG: Data can become stale if not revalidated
  • SSR: Always serves fresh data

3. Performance

  • SSG: Fastest, as pages are pre-built
  • SSR: Slower than SSG, but faster than client-side rendering

4. Use Cases

  • SSG: Static content, blogs, product pages
  • SSR: Real-time data, user-specific content

5. Scalability

  • SSG: Highly scalable, can be served from a CDN
  • SSR: Requires more server resources

Incremental Static Regeneration (ISR)

Next.js also offers ISR, which combines benefits of both SSG and SSR:

// pages/isr-example.js
export async function getStaticProps() {
  const res = await fetch('https://api.example.com/data')
  const data = await res.json()

  return {
    props: { data },
    revalidate: 60 // Regenerate page every 60 seconds
  }
}

export default function ISRPage({ data }) {
  return <div>ISR Page with data: {data.title}</div>
}

ISR allows you to update static pages after you've built your site, combining the benefits of SSG with the ability to serve fresh content.

API Routes & Data Fetching in Next.js

API Routes

  • Purpose: Handle server-side logic, data fetching, and API interactions within your Next.js application.
  • Location: Created in the pages/api directory.
  • Request/Response: Use the req and res objects to handle incoming requests and send responses.

Creating and Using API Routes: 

// pages/index.js
import { useState, useEffect } from 'react';

export default function Home() {
  const [data, setData] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch('/api/hello');
        const data = await response.json();
        setData(data);
      } catch (error) {
        console.error('Error fetching data:', error);
      }
    };

    fetchData();
  }, []);

  return (
    <div>
      {data && <p>Hello, {data.name}!</p>}
    </div>
  );
}

 

Next.js Server Actions

  • Purpose: Perform server-side actions without creating separate API routes.
  • Usage:
// pages/index.js
import { useServerAction } from 'next/server';

export default function Home() {
  const fetchData = useServerAction(async () => {
    const response = await fetch('/api/hello');
    return response.json();
  });
  const data = fetchData();
  return (
    <div>
      {data && <p>Hello, {data.name}!</p>}
    </div>
  );
}

Key Benefits of Next.js Server Actions

  • Improved Performance: Faster initial load times and better user experience.
  • Enhanced SEO: Better search engine rankings due to pre-rendered content.
  • Reduced Client-Side Processing: Offloads computationally intensive tasks to the server.
  • Data Privacy: Protects sensitive data by processing it on the server.
  • Simplified Development: Streamlines server-side logic within Next.js components.

Authentication in Next.js

Implementing Authentication:

1. Choose an authentication strategy:

  • Server-side rendering (SSR): Ideal for applications that require authentication before rendering pages.
  • Client-side rendering (CSR): Suitable for applications where authentication is handled after the initial page load.

2. Use a suitable authentication library:

  • NextAuth.js: A popular choice for handling authentication in Next.js applications.
  • Passport.js: A flexible authentication middleware for Node.js.
  • Custom implementation: If you prefer more control, you can build your own authentication system.

3. Store authentication tokens:

  • Cookies: Store tokens on the client-side.
  • Local storage: Store tokens in the browser's local storage.
  • Session storage: Store tokens in the browser's session storage.

4. Protecting Routes:

  • Use getServerSideProps or getStaticProps: For SSR, protect routes by checking for authentication tokens in these functions.
  • Use middleware: For CSR, create middleware that checks for authentication tokens before rendering pages.
  • Redirect unauthorized users: If a user is not authenticated, redirect them to a login page or other appropriate location.
// pages/api/auth/[...nextauth].js
import NextAuth from 'next-auth';
import Providers from 'next-auth/providers';

export default NextAuth({
  providers: [
    Providers.GitHub({
      clientId: process.env.GITHUB_ID,
      clientSecret: process.env.GITHUB_SECRET,
    }),
  ],
});

// pages/profile.js
import { getSession } from 'next-auth/react';

export default function Profile() {
  return (
    <div>
      {/* Profile content */}
    </div>
  );
}

export async function getServerSideProps(context) {
  const session = await getSession(context);

  if (!session) {
    return {
      redirect: {
        destination: '/login',
        permanent: false,
      },
    };
  }

  return {
    props: {
      session,
    },
  };
}
Trendingblogs
The Software Development Life Cycle (SDLC): A Complete Guide for Software Success image

The Software Development Life Cycle (SDLC): A Complete Guide for Software Success

Zustand: A Lightweight State Management Library for React image

Zustand: A Lightweight State Management Library for React

From Bugs to Beauty: Integrating UI/UX Testing into Software Quality Assurance image

From Bugs to Beauty: Integrating UI/UX Testing into Software Quality Assurance

Why is a Gaming PC the Ultimate Tool for Both Gaming and Professional Development? image

Why is a Gaming PC the Ultimate Tool for Both Gaming and Professional Development?

Why React Native is the Best Choice for Cross-Platform Development image

Why React Native is the Best Choice for Cross-Platform Development

Let's Deep Dive Into Threads with Rust image

Let's Deep Dive Into Threads with Rust

Get the best of our content straight to your inbox!

Don’t worry, we don’t spam!

Frequently Asked Questions