用Flask部署Next.js的教程

1,329 阅读6分钟

Flask和Next.js是两个独特的开源网络框架,分别建立在Python和JavaScript编程语言之上。

你可以在没有Next.js的情况下建立一个Flask应用程序,你也可以在没有Flask的情况下建立一个Next.js应用程序。然而,你可能会发现自己处于这样一种情况:你已经用Flask构建了一个应用程序,后来决定使用Next.js进行服务器端渲染。

那么,这时你会怎么做呢?

你可以尝试的一件事是逐步采用Next.js或Flask。在这篇文章中,我将向你展示如何使用Next.js的增量采用设计使Next.js与Flask API无缝连接,以及如何在Ubuntu服务器上用Nginx部署它。

在Next.js和Flask中构建一个应用程序

要求

  • Node.js v12
  • 蟒蛇

让我们从构建一个Next.js应用样本开始。按照Next.js的官方文档,运行以下命令,在您的计算机上安装Next.js:npx create-next-app@latest 。按照说明,建立一个基本的应用程序。

Basic App Setup

这次安装将为我们提供一个 "Hello, World!"的应用程序,准备好进行部署。如果一切顺利,你可以在终端上运行yarn run dev ,并在浏览器上访问localhost:3000 ,以确认它是否工作。你应该看到像这样的东西。

Next.js App

这就是目前的全部内容了。接下来,让我们建立一个基本的Flask API。我假设你已经安装了Python,但如果你没有,你可以按照你的操作系统的官方文档中的说明来安装它。

首先,让我们创建并激活一个包含Python应用程序的虚拟环境。

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

接下来,通过在终端运行以下命令来安装Flask。我们将使用Flask-RESTful来创建一个restful API。

pip install Flask flask-restful

然后,创建一个名为hello.py 的文件,并在其中添加以下代码。

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)

现在,我们已经设置了Flask和Next.js应用程序。让我们继续让它们一起工作吧。

使用重写程序将 Flask API 集成到 Next.js 中

Next.js的重写允许你将传入的请求路径映射到不同的目标路径。

移动到我们刚刚创建的Next.js应用的目录中,打开next.config.js ,用下面的代码替换内容。

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

通过这种整合,我们可以直接从Next.js访问我们所有的API路由,就像API与Next.js客户端在同一个域和端口一样。这意味着我们只需要调用 [http://localhost:3000/api/](http://localhost:3000/api/)我们就能间接访问端口为5000 的API。

我们来看看一个例子。

打开/pages/index.js 文件,用下面的 "Hello, World!"组件替换其组件。

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>
    )
}

上面的代码是一个简单的Next.js组件,使用Fetch与Flask API对话。正如你所看到的,我们没有必要在调用API时输入准确的URL。Next.js会根据我们最初设定的设置来理解它。

当然,你也可以选择直接调用Flask的API。

设置Nginx

现在我们有了一个工作的集成,让我们继续在Nginx中进行部署。在你的服务器上安装Nginx(在我们的例子中是Ubuntu服务器),为你的Nginx配置创建一个配置文件,我们称之为nextflask ,并在该文件中添加以下代码。

/** 
/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;
  }
}

上面的Nginx配置将在根域yourdomainname.com ,为你的Next.js应用程序提供服务,并在yourdomainname.com/api/hello

添加完这个配置后,通过运行下面的命令启动Nginx。

sudo systemctl start nginx.service

这就是设置Nginx为我们的Flask API和Next.js服务器提供服务。把你的Flask和Next.js代码推送到你的服务器上,安装依赖项,然后分别运行它们。哦,等等,我们需要对它们进行守护

你可以用SupervisorGunicorn对Flask应用进行守护,它们是部署Python应用的两个流行工具。

我们将对Flask使用Gunicorn,对Next.js使用PM2。

将Flask API和Next.js API作为一项服务运行

让我们先用Gunicorn运行Flask API。确保你的服务器上有一个工作的Python安装,然后创建一个虚拟环境来安装Gunicorn。

创建一个虚拟环境:

python3 -m venv env

然后,安装Gunicorn和Flask:

pip install gunicorn flask

设置Gunicorn以服务于Flask应用程序

首先,在根目录下创建一个wsgi.py 文件。这将作为应用程序的入口点。在该文件中添加以下代码:

// wsgi.py
from hello import app

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

接下来,为Gunicorn创建配置文件sudo vim /etc/systemd/system/hello.service ,并在其中添加以下配置:

[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

注意参考路径。最后,通过在终端运行以下命令来启动和启用Gunicorn:

sudo systemctl start hello & sudo systemctl enable hello

要检查操作是否成功,可以通过运行下面的命令查看状态:

sudo systemctl status

如果一切顺利,我们的Flask应用应该在端口500 ,并在根域yourdomainname.com

用PM2运行Next.js应用程序

PM2是一个用于Node.js应用程序的进程管理工具。要使用它,请用以下命令全局安装PM2:

pm2 install -g pm2

接下来,在有Next.js代码的目录中运行此命令:

pm2 start "npm run start" --name nextapp

你的Next.js应用程序将开始在端口3000 ,并在根域yourdomainname.com

恭喜你!你已经成功部署了Next.js。你已经成功地将你的Next.js前端与Flask API一起部署。一开始可能看起来很复杂,但你在以后的部署中不必重复这个过程,因为这为你的应用程序正常工作设定了基本环境。你可能只需要推送你的代码和重启你的服务器,这可以由你的CI/CD管道来管理。

总结

新技术层出不穷,现在可能是你选择用Flask部署Next.js来改善你的应用程序的总体工程的时候了。我希望这篇文章对你有帮助。

就我个人而言,我有一个旧的Flask API,但我想用Next.js继续开发,同时保留一些Python后端实现。我发现在不中断或破坏我现有API的情况下,切换非常容易。