どういうことか
index.html
とstaticファイルが同じ階層にあり、かつSPAである場合のルーティングに少々手こずったのでメモしておく。
どうしてこうなったかというと、使用しているプラグインの問題でビルドの出力先を変更できなかったのだ。
ディレクトリ構造
├── front
│ └── ... # Vueの開発環境
├── static
│ ├── assets
│ │ ├── index-C1jF7hUS.css
│ │ └── index-PL200lct.js
│ ├── index.html
│ ├── manifest.webmanifest <-こいつらが問題
│ ├── pwa-512x512.png <-こいつらが問題
│ ├── registerSW.js <-こいつらが問題
│ ├── sw.js <-こいつらが問題
│ ├── workbox-0225851e.js <-こいつらが問題
│ └── ...
└── main.py # FastAPIサーバーファイル
結論
from fastapi import FastAPI, Request
from fastapi.staticfiles import StaticFiles
from fastapi.exceptions import HTTPException
from fastapi.templating import Jinja2Templates
app = FastAPI()
@app.get("/api/hello")
def hello():
return {"message": "Hello World"}
@app.get("/api/goodbye")
def goodbye():
return {"message": "Goodbye!"}
app.mount("/", StaticFiles(directory="static"), name="static")
templates = Jinja2Templates(directory="static")
@app.exception_handler(404)
def spa(request: Request, _: HTTPException):
return templates.TemplateResponse(request=request, name="index.html")
解説
-
/api
など、routeに登録されているか確認 -
static
フォルダの中に存在するか確認 - 上記のどれにも当てはまらなければ、
index.html
を返却
このようにすることで、バックエンド側でリソースが見つかればそれを返し、見つからなければSPAにルーティングを投げる、という処理を実装することができる。