通过 FastAPI 部署 React 的构建文件夹
Deploy React's build folder via FastAPI
我想使用 FastAPI 为我的 React 前端提供服务。目标是用户的 0 Javascript 依赖性。用户可以简单地下载 Python 代码,启动服务器,并在本地主机上查看网站。
我的文件夹结构是:
- my-fullstack-app
- frontend/
- build/
- public/
- ...
- package.json
- backend/
- main.py
- static/
我 运行 npm run build
生成 frontend/build/
文件夹,其中包含:
build/
├── asset-manifest.json
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
├── robots.txt
└── static
├── css
│ ├── main.073c9b0a.css
│ └── main.073c9b0a.css.map
├── js
│ ├── 787.cda612ba.chunk.js
│ ├── 787.cda612ba.chunk.js.map
│ ├── main.af955102.js
│ ├── main.af955102.js.LICENSE.txt
│ └── main.af955102.js.map
└── media
└── logo.6ce24c58023cc2f8fd88fe9d219db6c6.svg
我复制了 frontend/build/
文件夹里面的内容 backend/static/
.
现在,我想通过 FastAPI 为这个 backend/static/
文件夹提供服务,而不是 运行 另一个服务器。
在我的 FastAPI 中 main.py
我有:
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
app = FastAPI()
app.mount("/", StaticFiles(directory="static/"), name="static")
然后我使用 - uvicorn main:app --reload
.
启动服务器
但是没用。
当我在浏览器中打开 http://127.0.0.1:8000/
时,输出是一个 JSON 文件,上面写着 {"detail":"Not Found"}
并且控制台有 Content Security Policy: The page's settings blocked the loading of a resource at http://127.0.0.1:8000/favicon.ico ("default-src").
.
如何让它工作?我看过 examples for similar functionality with React and Express.
@flakes 提到的 正是我要找的。查看更多详情。
为了完整性,
没有 html=True
标志。
app.mount("/", StaticFiles(directory="static/"), name="static")
导航至 http://127.0.0.1:8000/index.html
查看 html 文件。
带有html=True
标志。
app.mount("/", StaticFiles(directory="static/", html=True), name="static")
导航至 http://127.0.0.1:8000/
查看 html 文件。
你可以做的是让 index.html
服务除 API 特定路由之外的所有路由,然后加载所有静态资产。我的方法是这样的:
from fastapi import FastAPI, Request
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
from fastapi.exception_handlers import http_exception_handler
from starlette.exceptions import HTTPException as StarletteHTTPException
def SPA(app: FastAPI, build_dir: Union[Path, str]) -> FastAPI:
# Serves a React application in the root directory
@app.exception_handler(StarletteHTTPException)
async def _spa_server(req: Request, exc: StarletteHTTPException):
if exc.status_code == 404:
return FileResponse(f'{build_dir}/index.html', media_type='text/html')
else:
return await http_exception_handler(req, exc)
if isinstance(build_dir, str):
build_dir = Path(build_dir)
app.mount(
'/static/',
StaticFiles(directory=build_dir / 'static'),
name='React app static files',
)
然后在你的入口文件中
app: FastAPI = SPA(FastAPI(title='PROJECT_NAME', './build')
我想使用 FastAPI 为我的 React 前端提供服务。目标是用户的 0 Javascript 依赖性。用户可以简单地下载 Python 代码,启动服务器,并在本地主机上查看网站。
我的文件夹结构是:
- my-fullstack-app
- frontend/
- build/
- public/
- ...
- package.json
- backend/
- main.py
- static/
我 运行 npm run build
生成 frontend/build/
文件夹,其中包含:
build/
├── asset-manifest.json
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
├── robots.txt
└── static
├── css
│ ├── main.073c9b0a.css
│ └── main.073c9b0a.css.map
├── js
│ ├── 787.cda612ba.chunk.js
│ ├── 787.cda612ba.chunk.js.map
│ ├── main.af955102.js
│ ├── main.af955102.js.LICENSE.txt
│ └── main.af955102.js.map
└── media
└── logo.6ce24c58023cc2f8fd88fe9d219db6c6.svg
我复制了 frontend/build/
文件夹里面的内容 backend/static/
.
现在,我想通过 FastAPI 为这个 backend/static/
文件夹提供服务,而不是 运行 另一个服务器。
在我的 FastAPI 中 main.py
我有:
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
app = FastAPI()
app.mount("/", StaticFiles(directory="static/"), name="static")
然后我使用 - uvicorn main:app --reload
.
但是没用。
当我在浏览器中打开 http://127.0.0.1:8000/
时,输出是一个 JSON 文件,上面写着 {"detail":"Not Found"}
并且控制台有 Content Security Policy: The page's settings blocked the loading of a resource at http://127.0.0.1:8000/favicon.ico ("default-src").
.
如何让它工作?我看过 examples for similar functionality with React and Express.
@flakes 提到的
为了完整性,
没有 html=True
标志。
app.mount("/", StaticFiles(directory="static/"), name="static")
导航至 http://127.0.0.1:8000/index.html
查看 html 文件。
带有html=True
标志。
app.mount("/", StaticFiles(directory="static/", html=True), name="static")
导航至 http://127.0.0.1:8000/
查看 html 文件。
你可以做的是让 index.html
服务除 API 特定路由之外的所有路由,然后加载所有静态资产。我的方法是这样的:
from fastapi import FastAPI, Request
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
from fastapi.exception_handlers import http_exception_handler
from starlette.exceptions import HTTPException as StarletteHTTPException
def SPA(app: FastAPI, build_dir: Union[Path, str]) -> FastAPI:
# Serves a React application in the root directory
@app.exception_handler(StarletteHTTPException)
async def _spa_server(req: Request, exc: StarletteHTTPException):
if exc.status_code == 404:
return FileResponse(f'{build_dir}/index.html', media_type='text/html')
else:
return await http_exception_handler(req, exc)
if isinstance(build_dir, str):
build_dir = Path(build_dir)
app.mount(
'/static/',
StaticFiles(directory=build_dir / 'static'),
name='React app static files',
)
然后在你的入口文件中
app: FastAPI = SPA(FastAPI(title='PROJECT_NAME', './build')