如何在 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 build
或 yarn 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"
}
我尝试使用 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.
根据 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 build
或 yarn 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"
}