Dive into Next.js!

Dive into Next.js!

Next.js is a powerful React framework that enhances the developer experience by offering features like file-based routing, server-side rendering, and API routes out of the box. In this post, we’ll cover the core concepts of Next.js to help you build scalable and efficient web applications.

Pages and Routing

Next.js simplifies routing with its file-based system. Each file in the pages/ directory automatically becomes a route.

File-based Routing

Example:

/pages
  index.js  →  "/"
  about.js  →  "/about"
// pages/index.js
export default function Home() {
  return <h1>Welcome to Next.js!</h1>;
}

Dynamic Routes

Dynamic routes are created using square brackets.

Example:

/pages/product/[id].js
import { useRouter } from 'next/router';

export default function Product() {
  const { query } = useRouter();
  return <h1>Product ID: {query.id}</h1>;
}

Catch-All Routes

Capture multiple segments with [...param].

Example:

/pages/blog/[...slug].js

Rendering Methods

Next.js supports multiple rendering strategies:

App Router and Page Router

The App Router simplifies modern rendering, while the Page Router is the legacy system. Both coexist but prefer the App Router for new projects.

Server-Side Rendering (SSR)

Fetch data on the server at request time.

export async function getServerSideProps() {
  const res = await fetch('https://api.example.com/data');
  const data = await res.json();
  return { props: { data } };
}

export default function Page({ data }) {
  return <pre>{JSON.stringify(data, null, 2)}</pre>;
}

Client-Side Rendering (CSR)

Use useEffect to fetch data on the client.

import { useState, useEffect } from 'react';

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

  useEffect(() => {
    fetch('/api/data')
      .then((res) => res.json())
      .then(setData);
  }, []);

  return <pre>{JSON.stringify(data, null, 2)}</pre>;
}

API Routes

Next.js allows you to create backend endpoints in the pages/api directory.

Creating Endpoints

Example:

// pages/api/hello.js
export default function handler(req, res) {
  res.status(200).json({ message: 'Hello, World!' });
}

Handling Requests

Use req and res objects to handle different HTTP methods.

Example:

// pages/api/user.js
export default function handler(req, res) {
  if (req.method === 'POST') {
    res.status(201).json({ message: 'User created' });
  } else {
    res.status(405).json({ error: 'Method not allowed' });
  }
}

Assets, Metadata, and Styles

Images and Assets

Optimize images with the next/image component.

Example:

import Image from 'next/image';

export default function Home() {
  return <Image src="/logo.png" alt="Logo" width={200} height={200} />;
}

Metadata with next/head

Add SEO-friendly metadata.

Example:

import Head from 'next/head';

export default function Home() {
  return (
    <>
      <Head>
        <title>My Next.js App</title>
        <meta name="description" content="A great app built with Next.js" />
      </Head>
      <h1>Welcome!</h1>
    </>
  );
}

Styles

Next.js supports global styles and CSS modules.

Global Styles: Add styles in styles/globals.css and import in _app.js.

// pages/_app.js
import '../styles/globals.css';

export default function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}

CSS Modules: Scoped styles for specific components.

// components/Button.module.css
.button {
  background-color: blue;
  color: white;
}

// components/Button.js
import styles from './Button.module.css';

export default function Button() {
  return <button className={styles.button}>Click Me</button>;
}

Performance Optimizations

Lazy Loading

Optimize performance by lazy-loading components or images.

Example:

import dynamic from 'next/dynamic';

const DynamicComponent = dynamic(() => import('../components/HeavyComponent'));

export default function Home() {
  return <DynamicComponent />;
}

Optimizing Images and Scripts

The next/image component automatically optimizes images for size and format. Use next/script to load third-party scripts efficiently.


Conclusion

Next.js bridges the gap between frontend and backend, offering a robust framework for building modern web applications. From routing and rendering to API endpoints and performance optimizations, mastering Next.js unlocks endless possibilities for developers.

Stay tuned for the next post in the Frontend Unlocked series, where we’ll explore advanced Next.js techniques and best practices!