如何在 FastAPI 后端上提供 React 构建的前端?

How do I serve a React-built front-end on a FastAPI backend?

我尝试使用 app.mount 将前端安装到 /,但这会使我的所有 /api 路由无效。我还尝试了以下代码将 /static 中的文件夹挂载到它们各自的路径,并在 / 上提供 index.html 文件:

@app.get("/")
def index():
    project_path = Path(__file__).parent.resolve()
    frontend_root = project_path / "client/build"
    return FileResponse(str(frontend_root) + '/index.html', media_type='text/html')

static_root = project_path / "client/build/static"
app.mount("/static", StaticFiles(directory=static_root), name="static")

这主要是有效的,但 client/build 文件夹中包含的文件未安装,因此无法访问。我知道 Node.js 有一种方法可以使用 res.sendFile("index.html", { root: </path/to/static/folder }); 的相对路径为前端页面提供服务。在 FastAPI 中是否有执行此操作的等效函数?

clmno's solution is two servers + routing. Jay Jay Cayabyab 正在 API 上寻找一个服务于 webpacked SPA 的端点,就是你在 npm run build 之后得到的那种。我 寻找完全相同的解决方案,因为这就是我用 Flask 所做的,我正试图用 FastAPI.

替换 Flask

根据 FastAPI 的文档,多次提到它基于 starlette。在 starlette 上搜索服务 SPA,我遇到了一个问题 this reply。当然,这对我来说不是现成的,因为我缺少一些导入,在建议的解决方案中没有提到。

这是我的代码,它正在运行:

from fastapi.staticfiles import StaticFiles

class SPAStaticFiles(StaticFiles):
async def get_response(self, path: str, scope):
    response = await super().get_response(path, scope)
    if response.status_code == 404:
        response = await super().get_response('.', scope)
    return response

app.mount('/my-spa/', SPAStaticFiles(directory='folder', html=True), name='whatever')

注意:我更改了端点 (my-spa)、目录(文件夹)和应用程序名称(随便什么)的名称,以强调这些不必完全相同这一点。

在这种情况下,您将构建的 SPA 放在 folder 文件夹中。为此,在 SPA 项目文件夹中,您 运行 npm run buildyarn run build,您会得到一个名为 dist 的文件夹。将 dist 中的所有文件和文件夹复制到此 folder 文件夹中。

完成此操作后,运行 您的 FastAPI 应用,然后转到 http://localhost:5000/my-spa/。为了绝对清楚起见,我使用这个特定的 URL 的原因是我的应用程序有一个像这样的主程序:

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=5000)

因此它从端口 5000 开始。您的情况可能有所不同。

我讨厌这些回复中缺少导入内容,因为有时回复似乎从来没有 运行。当我键入此内容时,我的正在 运行ning 在另一个屏幕上,所以这不是浪费你的时间。但是,假设您已经在做这些琐碎的事情,我自己可能会遗漏一些导入内容

from fastapi import FastAPI

等等。如果您尝试此操作并发现有任何遗漏,请在此处告诉我。

我认为您可以通过在文件末尾添加“proxy”这一行来更改 package.json 中的代理。例如,你的反应运行在 localhost:3000 而你的 fastapi 儿子 localhost:8000

    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "proxy": "http://localhost:8000"
}