Skip to content

How to Combine NestJS with Next.js ?

combine nestJs with next.js

Creating a project to combine NestJS with Next.js can be an exciting. In this guide, we’ll walk through the initial setup and choosing a server-side rendering (SSR) strategy. This tutorial assumes that you have Node.js and npm (Node Package Manager) installed on your system.

If you wanna knwo the difference between NestJS vs. Next.js and when to use which one check the following article: click here

Introduction

Nest JS and Next.js are both popular JavaScript frameworks. Nest.js is used for building server-side applications, while Next.js is primarily used for building React-based front-end applications. Combining these two frameworks can lead to powerful full-stack web applications.

What’s the advantage to combine Nestjs with Next.js?

To Combine Nestjs with Next.js offers a multitude of advantages that empower developers to build powerful, SEO-friendly, and efficient full-stack applications. The synergy between these two frameworks lies in their complementary strengths:

  1. Server-Side Rendering (SSR): Next.js excels in SSR, rendering web pages on the server, which enhances SEO, improves initial page load times, and ensures better performance. By integrating Nest.js with Next.js, you can seamlessly incorporate SSR into your backend services, providing a consistent and fast user experience.
  2. Full-Stack Development: Nest.js, with its TypeScript-based, modular architecture, is ideal for building the backend of your application. It offers features like dependency injection, decorators, and a well-defined structure that simplifies server-side logic. On the frontend, Next.js, built on top of React, provides a robust framework for creating dynamic and interactive user interfaces. Combining these two frameworks enables you to cover both backend and frontend development needs within a single project.
  3. SEO-Friendly Applications: Search engines favor SSR because it delivers fully-rendered HTML content, which is easily indexed. Nest.js, in conjunction with Next.js, ensures that your application’s pages are pre-rendered on the server, optimizing your site’s SEO performance.
  4. Data Synchronization: The combination allows for smooth data synchronization between the server and the client, ensuring that your web application remains up-to-date and responsive.
  5. Cohesive Development Experience: Nest.js and Next.js share a similar structure and tooling, making it easier for developers to switch between backend and frontend code seamlessly. This cohesive development experience can lead to increased productivity and reduced learning curve.
  6. Scalability and Maintainability: Nest.js encourages best practices in backend development, promoting maintainable and scalable codebases. When paired with Next.js on the frontend, you can build applications that are both performant and easily maintainable as they grow.

Before We Start To combine NestJS with Next.js:

Before we dive into the project setup, ensure you have the following prerequisites:

  1. Node.js and npm: Make sure you have Node.js (at least version 14) and npm installed. You can download them from nodejs.org.
  2. IDE (Integrated Development Environment): Choose an IDE or code editor of your choice. Visual Studio Code is a popular choice.

Creating a Nest.js Application:

Let’s start by creating a Nest.js application. We’ll assume you have basic knowledge of Nest.js. If not, you can learn more on the Nest.js official website.

  • 1. Open your terminal and navigate to the directory where you want to create your project.
  • 2. Run the following command to create a new Nest.js project:
npx @nestjs/cli new nest-next-project
  • 3. Follow the prompts to configure your project. You can choose options like the package manager (npm or yarn), the type of application you want to create (empty, full, etc.), and other project-specific settings.
  • 4. Once the project is created, navigate to the project directory:
cd nest-next-project

Step 1: Install Dependencies

Install the required dependencies for Next.js.

  1. Inside your Nest.js project directory, run the following command to install Next.js:
npm install next react react-dom

Step 2: Create a Nest.js Controller

You can create a Nest.js controller that handles data fetching and rendering for your Next.js pages. Create a Nest.js controller named app.controller.ts: Here’s a basic example:

import { Controller, Get, Render } from '@nestjs/common';

@Controller()
export class AppController {
  @Get()
  @Render('index')
  async home() {
    const data = await this.fetchData(); // Temporary data
    return { data };
  }

  private async fetchData() {
    // For the sake of simplicity we are using demo data
    // you have to connect your database here
    return [
      { id: 1, name: 'Item 1' },
      { id: 2, name: 'Item 2' },
      { id: 3, name: 'Item 3' },
    ];
  }
}

Step 3: Create a Next.js Page

Create a Next.js page named index.js in the pages directory. This page will render the data received from the Nest.js controller.

import React from 'react';

const Home = ({ data }) => {
  return (
    <div>
      <h1>Server-Side Rendering with Nest.js and Next.js</h1>
      <ul>
        {data.map((item) => (
          <li key={item.id}>{item.name}</li>
        ))}
      </ul>
    </div>
  );
};

export const getServerSideProps = async () => {
  const res = await fetch('http://localhost:3000'); // Fetch data from your Nest.js server
  const data = await res.json();

  return {
    props: {
      data,
    },
  };
};

export default Home;

In this example, we use the getServerSideProps function to fetch data from the Nest.js server.

Step 4: Start the Development Server

Now, you can start both the Nest.js and Next.js development servers:

// Start the Nest.js server
npm run start

// In a separate terminal, start the Next.js server
npm run dev

Visit http://localhost:3000 in your browser to see the server-side rendered data.

Please note that this example uses temporary data for demonstration purposes. In a real-world scenario, you would replace the fetchData method in the Nest.js controller with logic to fetch data from a database or an API.

Wrapper For Fetching Data:

You can create a wrapper for fetch that sets the appropriate base URL for your Nest.js server and handles authentication if needed. This makes it easier to send requests to your Nest.js API from your Next.js pages.

Basically, creating wrapper means something like create a separate component for the fetching of API data which will make the main code clean and easy to understandable. All you will do is just call the API and pass value and it will return the response as show below:

// Create a file (e.g., api.js) to define your API wrapper
const BASE_URL = 'http://localhost:3000'; // Replace with your Nest.js server URL

export async function apiFetch(path, options = {}) {
  const url = `${BASE_URL}${path}`;
  
  try {
    const response = await fetch(url, options);
    
    if (response.ok) {
      return await response.json();
    } else {
      throw new Error('Request failed');
    }
  } catch (error) {
    throw new Error(error.message);
  }
}

Now you can import and use this apiFetch function in your Next.js pages to make requests to your Nest.js server:

import { useEffect, useState } from 'react';
import { apiFetch } from '../path-to-api'; // Import your API wrapper

function MyPage() {
  const [data, setData] = useState(null);

  // Fetch data using the API wrapper when the component mounts
  useEffect(() => {
    async function fetchData() {
      try {
        const fetchedData = await apiFetch('/api/data'); // Use the wrapper function
        setData(fetchedData); // Store the fetched data in the component's state
      } catch (error) {
        console.error('Error:', error.message);
      }
    }

    fetchData();
  }, []);

  return (
    <div>
      <h1>My Page</h1>
      {data ? (
        <div>
          <p>Data from the API:</p>
          <pre>{JSON.stringify(data, null, 2)}</pre>
        </div>
      ) : (
        <p>Loading data...</p>
      )}
    </div>
  );
}

export default MyPage;

In the code above:

  1. We initialize a data state variable using the useState hook to store the fetched data.
  2. In the useEffect hook, we fetch data from the API using the apiFetch function and update the data state when the data is successfully retrieved.
  3. In the component’s JSX, we conditionally render the data. If the data state is not null (meaning data has been fetched), we display it using the <pre> tag. Otherwise, we show a “Loading data…” message.

Passing Path Parameters:

When you need to handle dynamic routes and pass parameters to your SSR pages, Next.js makes it easy. Create a file inside the “pages” directory with brackets to indicate dynamic segments, like [id].js. You can then access the parameters using useRouter or getServerSideProps.

// pages/[id].js

import { useRouter } from 'next/router';

const DynamicPage = () => {
  // Use useRouter to access the dynamic "id" parameter from the route
  const router = useRouter();
  const { id } = router.query;

  return (
    <div>
      <h1>Dynamic Page</h1>
      <p>Parameter "id" from the route: {id}</p>
    </div>
  );
};

export default DynamicPage;

In this example:

  1. We import the useRouter hook from Next.js to access the router object.
  2. Inside the component, we use useRouter() to get the router object.
  3. We extract the “id” parameter from the router.query object. This parameter corresponds to the value provided in the URL, such as /dynamic/123, where “123” is the value of the “id” parameter.

Now, when you visit a URL like /dynamic/123, the “Dynamic Page” component will display “Parameter ‘id’ from the route: 123” on the page. You can use this parameter to fetch data or customize the content of your page based on the URL.

In your Nest.js controller, you can then access this parameter like this:

// In your Nest.js controller
import { Controller, Get, Param } from '@nestjs/common';

@Controller('users')
export class UsersController {
  @Get(':id')
  getUserProfile(@Param('id') id: string) {
    // Use the 'id' parameter to fetch user data
    // Return the user's profile
  }
}

This allows you to create dynamic routes in Next.js and pass path parameters to your Nest.js controllers for custom data fetching based on the route parameters.

Conclusion

In this article, we’ve explored the initial steps of creating a full-stack application to combine NestJS with Next.js. We set up a NestJs application and installed Next.js to enable Server-Side Rendering (SSR). Also write a basic example for you understand how these two works together.

FAQ:

Q1: What is Server-Side Rendering (SSR)?

Server-Side Rendering is a technique in web development where web pages are generated on the server and sent to the client as fully-rendered HTML. This can improve SEO, performance, and user experience.

Q2: How do I fetch real data instead of using temporary data?

To fetch real data, replace the temporary data in the Nest.js controller’s fetchData method with code to access your database or call an API. Ensure your Next.js page uses the correct URL to fetch data from your Nest.js server.

Q3: Can I use a different database or API with this setup?

Yes, you can use any database or API that suits your project. Nest.js and Next.js are flexible and can integrate with various data sources and services.

Q4: What’s the advantage to combine NestJS with Next.js?

Combining Nest.js for the backend and Next.js for the frontend allows you to build a full-stack application with SSR capabilities, making it SEO-friendly and efficient. It also provides a cohesive development experience.

Q5: Where can I find more information about Nest.js and Next.js?

You can explore the official documentation for Nest.js at nestjs.com and for Next.js at nextjs.org. Both resources offer extensive guides, tutorials, and examples.

Leave a Reply

Your email address will not be published. Required fields are marked *