Eze Sunday Eze Sunday is a full-stack software developer and technical writer passionate about solving problems, one line of code at a time. Contact Eze at [email protected]

Deploying Next.js with Flask

5 min read 1418

Deploying Next.js With Flask

Flask and Next.js are two unique open source web frameworks built on top of the Python and JavaScript programming languages, respectively.

You can build a Flask application without Next.js, and you can also build a Next.js app without Flask. However, you might find yourself in a situation where you’ve built an application with Flask and later decide to use Next.js for server-side rendering.

So, what do you do at this point?

One thing you can try is to incrementally adopt Next.js or Flask. In this article, I’ll show you how to make Next.js work seamlessly with a Flask API using the Next.js incremental adoption design, and how you can deploy it with Nginx on an Ubuntu server.

To jump ahead in this article:

Build an app in Next.js and Flask

Requirements

  • Node.js v12
  • Python

Let’s start by building a sample Next.js application. Following the official Next.js documentation, run the following command to install Next.js on your computer: npx [email protected]. Follow the instructions to set up a basic app.

Basic App Setup

This installation will give us a “Hello, World!” app, ready for deployment. If all goes well, you can run yarn run dev on the terminal and visit localhost:3000 on your browser to confirm that it works. You should see something like this:

Next.js App

That’s all there is to it for now. Next, let’s build a basic Flask API. I’ll assume you have Python installed, but if you don’t, you can install it by following the instructions in the official documentation for your OS.



First, let’s create and activate a virtual environment to contain the Python application.

python3 -m venv env & source ./env/bin/activate

Next, install Flask by running the following command in your terminal. We’ll use Flask-RESTful to create a restful API:

pip install Flask flask-restful

Then, create a file called hello.py and add the following code to it:

from flask import Flask
from flask_restful import reqparse, Api, Resource
app = Flask(__name__)
api = Api(app)

parser = reqparse.RequestParser()
parser.add_argument('task')
class Message(Resource):
    def get(self):
        return {"message": 'Hello World'}
api.add_resource(Message, '/api/hello')

if __name__ == '__main__':
    app.run(debug=True)

Now, we have both the Flask and the Next.js app set up. Let’s proceed with making them work together.

Integrating Flask API into Next.js using rewrites

Next.js rewrites allow you to map an incoming request path to a different destination path.

Move into the directory of the Next.js app we just created, open the next.config.js file, and replace the content with the code below:

module.exports = () => {
  const rewrites = () => {
    return [
      {
        source: "/hello/:path*",
        destination: "http://localhost:5000/hello/:path*",
      },
    ];
  };
  return {
    rewrites,
  };
};

With this integration, we can access all of our API routes directly from Next.js as though the API is in the same domain and port as the Next.js client. This means we’ll only need to call http://localhost:3000/api/ and that we’ll be able to reach the API at port 5000 indirectly.

Let’s look at an example.

Open the /pages/index.js file and replace its component with the “Hello, World!” component below:

import styles from '../styles/Home.module.css'
import { useEffect, useState } from 'react'

export default function Home() {
    const [message, setMessage] = useState("");
    const [loading, setLoading] = useState(true);

    useEffect(() => {
        fetch('/hello/')
            .then(res => res.json())
            .then(data => {
                setMessage(data.message);
                setLoading(false);
            })
    }, [])

    return (
        <div className={styles.container}>
            <p> {!loading ? message : "Loading.."}</p>
        </div>
    )
}

The code above is a simple Next.js component that talks to the Flask API using Fetch. As you can see, we didn’t have to put the exact URL in the call to the API. Next.js understood it based on the settings we initially set.

Of course, you can also choose to call the Flask API directly.

Set up Nginx

Now that we have a working integration, let’s proceed to deployment in Nginx. Install Nginx on your server (an Ubuntu server, in our case), create a config file for your Nginx configuration, which we’ll call nextflask, and add the following code to the file:


More great articles from LogRocket:


/** 
/etc/nginx/sites-available/nextflask
**/
server {
    server_name        yourdomainname.com www.yourdomainname.com;
    listen 80;

  location /hello/ {
    proxy_pass http://127.0.0.1:5000/hello/;
    proxy_http_version 1.1;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
  location / {
    proxy_pass http://0.0.0.0:3000;
    proxy_http_version 1.1;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}

The Nginx config above will serve your Next.js app on the root domain yourdomainname.com and serve your API on yourdomainname.com/api/hello.

After adding this configuration, start Nginx by running the command below:

sudo systemctl start nginx.service

That’s it for setting up Nginx to serve our Flask API and Next.js server. Push your Flask and Next.js code to your server, install the dependencies, and run them separately. Oh, wait, we’ll need to daemonize them.

You can daemonize a Flask app with either Supervisor or Gunicorn, which are two popular tools for deploying Python applications.

We’ll use Gunicorn for Flask and PM2 for Next.js.

Run the Flask API and the Next.js API as a service

Let’s start with running the Flask API with Gunicorn. Ensure that you have a working Python installation on your server, then create a virtual environment to install Gunicorn.

Create a virtual environment:

python3 -m venv env

Then, install Gunicorn and Flask:

pip install gunicorn flask

Set up Gunicorn to serve the Flask application

First, create a wsgi.py file in the root directory. This will serve as the entry point of the application. Add the following code to the file:

// wsgi.py
from hello import app

if __name__ == "__main__":
    app.run()

Next, create config file sudo vim /etc/systemd/system/hello.service for Gunicorn and add the following configuration to it:

[Unit]
Description=Gunicorn instance to serve hello
After=network.target

[Service]
User=eze
Group=www-data
WorkingDirectory=/path/to/your/app/directory
ExecStart=/path/to/gunicorn/bin/gunicorn --workers 3 --bind unix:hello.sock -m 007 wsgi:app

[Install]
WantedBy=multi-user.target

Pay attention to the reference paths. Finally, start and enable Gunicorn by running the following command in your terminal:

sudo systemctl start hello & sudo systemctl enable hello

To check if the operation was successful, review the status by running the command below:

sudo systemctl status

If all goes well, our Flask app should be up and running on port 500 and in the root domain, yourdomainname.com.

Run the Next.js app with PM2

PM2 is a process management tool for Node.js applications. To use it, install PM2 globally with the following command:

pm2 install -g pm2

Next, run this command in the directory that has your Next.js code:

pm2 start "npm run start" --name nextapp

Your Next.js application will start working on port 3000 and in the root domain, yourdomainname.com.

Congratulations! You have successfully deployed your Next.js frontend with your Flask API. It might seem complicated at first, but you won’t have to repeat this process in your future deployments, because this sets the basic environment for your application to work properly. You might only need to push your code and restart your server, which can be managed by your CI/CD pipeline.

Conclusion

New technologies come and go all the time, and now might be the time for you to choose to deploy Next.js with Flask to improve the general engineering of your application. I hope you find this article helpful.

Personally, I had an old Flask API, but I wanted to continue development with Next.js while retaining some of the Python backend implementations. I found it very easy to switch without interrupting or breaking my existing API.

Check out this sample Next.js project, which you can clone to replicate the process from this article. Cheers!

LogRocket: Full visibility into production Next.js apps

Debugging Next applications can be difficult, especially when users experience issues that are difficult to reproduce. If you’re interested in monitoring and tracking state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket is like a DVR for web and mobile apps, recording literally everything that happens on your Next app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your Next.js apps — .

Eze Sunday Eze Sunday is a full-stack software developer and technical writer passionate about solving problems, one line of code at a time. Contact Eze at [email protected]

Leave a Reply