Next.js (v14)

author

Heman Alany

15 Feb, 2025

UI/UX Design

What is Next.js?

In today's rapidly evolving web development landscape, building performant, scalable, and SEO-friendly applications can be challenging. Next.js is a React-based framework that provides all the tools needed to build server-rendered and statically-generated web applications with ease. It simplifies the complexities of React and adds powerful features out-of-the-box.

History of Next.js

Initial Release (2016)
Major Milestones:
Version 9: Dynamic Routing, API Routes
Version 10: Image Optimization, ISR
Version 11: Automatic Image Optimization
Version 12: Middleware, Webpack 5
Version 13: Rust Compiler, React Server Components
Latest Version (14): Enhanced React Server Components, Improved Developer Tools, Performance and Scalability Enhancements
Next.js 15 Release Candidate (RC) is now available

Metadata

Metadata is crucial for SEO and sharing previews on social media. Next.js provides a built-in way to add metadata to your pages using the Head component from next/head.

Client Components vs Server Components

Next.js 14 introduces the ability to use React Server Components alongside traditional Client Components. Server Components allow for improved performance by offloading rendering to the server.

Client Components:
- Rendered on the client side.
- Suitable for highly interactive UI.

Server Components:
- Rendered on the server side.
- Reduce the amount of JavaScript sent to the client.
- Enhance performance and reduce Time to Interactive (TTI).

              
                // pages/index.js
                import ClientComponent from '../components/ClientComponent';
                import ServerComponent from '../components/ServerComponent';
    
                export default function Home() {
                  return (
                    //Next.js Client vs Server Components
                     // ClientComponent />
                     // ServerComponent />
                  );
                }
    
                // components/ClientComponent.js
                export default function ClientComponent() {
                  return Client Side Component;
                }
    
                // components/ServerComponent.js
                export default function ServerComponent() {
                  return Server Side Component;
                }
              
            

Data Fetching Methods

Partial Prerendering

Partial Prerendering allows you to define parts of the page that should be rendered statically and parts that should be dynamically rendered on the server.

              
                export async function getStaticProps() {
                  const res = await fetch('https://api.example.com/data');
                  const data = await res.json();
    
                  return {
                    props: {
                      data,
                    },
                  };
                }
    
                export default function Page({ data }) {
                  return (
                      //Partially Prerendered Page
                      //{data}

); }

Server Side Rendering (SSR)

SSR allows you to render your React components on the server, generating HTML that is sent to the client. This improves SEO and performance for the initial load.

              
                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 (
                      //Server Side Rendered Page
                      //{data}

); }

Static Site Generation (SSG)

SSG allows you to pre-render pages at build time, generating static HTML. This is useful for pages with content that doesn't change frequently.

              
                export async function getStaticProps() {
                  const res = await fetch('https://api.example.com/data');
                  const data = await res.json();
    
                  return {
                    props: {
                      data,
                    },
                  };
                }
    
                export default function Page({ data }) {
                  return (
                      //Static Site Generated Page
                      //{data}

); }

Incremental Static Generation (ISR)

ISR enables you to use static generation on a per-page basis, allowing you to update static content without rebuilding the entire site.

              
                export async function getStaticProps() {
                  const res = await fetch('https://api.example.com/data');
                  const data = await res.json();
    
                  return {
                    props: {
                      data,
                    },
                    revalidate: 10, // Revalidate every 10 seconds
                  };
                }
    
                export default function Page({ data }) {
                  return (
                      h1> Incrementally Static Generated Page
                      p> {data}

); }

Server Actions (Post, Put, Delete)

Next.js allows you to create API routes to handle server-side actions like POST, PUT, and DELETE requests.

              
                // pages/api/create.js
                export default async function handler(req, res) {
                  if (req.method === 'POST') {
                    // Handle POST request
                    const data = req.body;
                    // Process data...
                    res.status(200).json({ message: 'Data saved successfully' });
                  } else {
                    res.status(405).json({ message: 'Method not allowed' });
                  }
                }
              
            

Suspense and Streaming (Loading)

Suspense and streaming allow you to render parts of your application as they load, improving the user experience by displaying content progressively.

              
                import { Suspense } from 'react';
    
                function Loading() {
                  return Loading...;
                }
    
                function PageContent() {
                  // Simulate loading data
                  return new Promise((resolve) => setTimeout(() => resolve(Content Loaded), 2000));
                }
    
                export default function Page() {
                  return (
                      h1>Suspense and Streaming h1>
                      Suspense fallback={Loading />}>
                        //PageContent />
                      Suspense>
                  );
                }
              
            

Static and Dynamic Rendering

Next.js supports both static and dynamic rendering. Static rendering generates HTML at build time, while dynamic rendering generates HTML on each request.

              
                // Static Rendering
                export async function getStaticProps() {
                  const res = await fetch('https://api.example.com/data');
                  const data = await res.json();
    
                  return {
                    props: {
                      data,
                    },
                  };
                }
    
                // Dynamic Rendering
                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 (
                      h1> Static and Dynamic Rendering h1>
                      p> {data} p>
                  );
                }
              
            

Caching

Caching in Next.js helps improve performance by storing frequently accessed data. You can leverage caching mechanisms at different levels, such as CDN, server, or client-side.

              
                import useSWR from 'swr';
    
                const fetcher = url => fetch(url).then(res => res.json());
    
                export default function Page() {
                  const { data, error } = useSWR('https://api.example.com/data', fetcher, { refreshInterval: 3000 });
    
                  if (error) return div>Failed to load /div>;
                  if (!data) return div>Loading... /div>;
    
                  return (
                      h1>Caching with SWR /h1>
                      p>{data} /p>
                  );
                }
              
            

Conclusion

Next.js 14 brings numerous enhancements and new features, making it an excellent choice for building modern web applications. Whether you're looking to improve SEO, performance, or development experience, Next.js provides the tools and flexibility to achieve your goals.