Back to Blog

Building Modern Web Applications with Next.js 14

Building Modern Web Applications with Next.js 14

March 15, 2024

8 min read
Next.js
React
Performance
TypeScript

Introduction

Next.js has become one of the most popular React frameworks for building modern web applications. In this guide, we'll explore the key features that make Next.js an excellent choice for your next project and walk through setting up a basic application.

Key Features of Next.js

  • Server-side rendering (SSR) and static site generation (SSG)
  • File-based routing system
  • API routes for backend functionality
  • Built-in image optimization
  • Automatic code splitting
  • Hot module replacement during development

Setting Up a Next.js Project

Let's start by creating a new Next.js project. Open your terminal and run:

npx create-next-app@latest my-next-app
cd my-next-app
npm run dev

This will create a new Next.js project with TypeScript, ESLint, and Tailwind CSS configuration. The development server will start at http://localhost:3000.

Project Structure

A typical Next.js project structure looks like this:

my-next-app/
├── app/
│   ├── layout.tsx
│   ├── page.tsx
│   └── globals.css
├── public/
│   └── assets/
├── components/
├── package.json
└── next.config.js

Creating Pages and Routes

Next.js 13+ uses the App Router, which is based on the file-system. Here's how to create basic routes:

// app/page.tsx
export default function Home() {
  return (
    <main>
      <h1>Welcome to Next.js!</h1>
    </main>
  );
}

To create nested routes, simply create folders in the app directory:

app/
├── page.tsx          // → /
├── about/
│   └── page.tsx      // → /about
└── blog/
    └── [slug]/
        └── page.tsx  // → /blog/post-1, /blog/post-2

Data Fetching

Next.js provides several ways to fetch data in your applications:

// Server Component
async function getData() {
  const res = await fetch('https://api.example.com/data');
  if (!res.ok) throw new Error('Failed to fetch data');
  return res.json();
}

export default async function Page() {
  const data = await getData();
  return <main>{/* Render data here */}</main>;
}

API Routes

API routes allow you to build backend endpoints within your Next.js app.

// pages/api/hello.ts
import { NextApiRequest, NextApiResponse } from 'next';

export default function handler(req: NextApiRequest, res: NextApiResponse) {
  res.status(200).json({ message: 'Hello from Next.js API Route!' });
}

Image Optimization

The Next.js Image component automatically optimizes images for size and performance.

import Image from 'next/image';

export default function Avatar() {
  return (
    <Image
      src="/me.png"
      alt="My Avatar"
      width={200}
      height={200}
      placeholder="blur"
    />
  );
}

Middleware

Middleware runs before requests are processed, useful for authentication, redirects, and rewriting URLs.

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  if (!request.nextUrl.pathname.startsWith('/api')) {
    // perform logic
  }
  return NextResponse.next();
}

Incremental Static Regeneration (ISR)

ISR allows you to update static pages after build without a full rebuild.

export async function getStaticProps() {
  const data = await fetchData();
  return {
    props: { data },
    revalidate: 60, // Revalidate every 60 seconds
  };
}

Environment Variables

Store sensitive config in .env.local and prefix public vars with NEXT_PUBLIC_.

// .env.local
NEXT_PUBLIC_API_URL=https://api.example.com
DATABASE_URL=postgres://user:pass@localhost:5432/db

Authentication with NextAuth

NextAuth makes adding authentication and OAuth providers straightforward.

import NextAuth from 'next-auth';
import GitHubProvider from 'next-auth/providers/github';

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

Internationalization (i18n)

Enable locale routing with built-in i18n support in next.config.js.

// next.config.js
module.exports = {
  i18n: {
    locales: ['en', 'fr', 'es'],
    defaultLocale: 'en',
  },
};

Performance Optimization

Monitor Lighthouse scores, use React Profiler, and analyze bundle size via webpack-bundle-analyzer.

Deployment to Vercel

Deploy your Next.js app seamlessly with Vercel CLI or through Git integration.

npm install -g vercel
vercel login
vercel --prod

Conclusion

Next.js combines powerful features with an easy developer experience. Explore these sections to build scalable, high-performance web apps.