Archived
为什么:前端迁移到 Vite 后,首页应直接返回 frontend/dist/index.html 字节(golden 口径随之变为构建产物原样字节),仅当 dist 未构建时 回退 Jinja2 渲染的 legacy 模板。同步挂载 /assets 静态目录、排除 frontend 的 node_modules/tsbuildinfo 入库、docker 构建只带 dist 不带源码、ruff/pyright 排除 frontend 目录(TS 侧由 tsc+vite 把关)。
40 lines
1.3 KiB
Python
40 lines
1.3 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""首页与静态资源。
|
||
|
||
- GET / 首页:优先服务 React 构建产物 frontend/dist/index.html;
|
||
dist 未构建时回退旧版 templates/index.html(平滑过渡)
|
||
- 静态资源由 Starlette StaticFiles 挂载 /assets 与 /static(见 web/app.py)
|
||
"""
|
||
from pathlib import Path
|
||
|
||
from fastapi import APIRouter, Request
|
||
from fastapi.responses import HTMLResponse
|
||
|
||
router = APIRouter()
|
||
|
||
_PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent
|
||
_DIST_INDEX = _PROJECT_ROOT / 'frontend' / 'dist' / 'index.html'
|
||
_LEGACY_TEMPLATE = _PROJECT_ROOT / 'templates' / 'index.html'
|
||
|
||
|
||
def _render_index() -> str:
|
||
"""渲染首页 HTML:React 构建产物优先,缺失时回退旧模板。"""
|
||
if _DIST_INDEX.is_file():
|
||
return _DIST_INDEX.read_text(encoding='utf-8')
|
||
import jinja2
|
||
|
||
env = jinja2.Environment(
|
||
loader=jinja2.FileSystemLoader(str(_LEGACY_TEMPLATE.parent)),
|
||
autoescape=True,
|
||
)
|
||
return env.get_template(_LEGACY_TEMPLATE.name).render()
|
||
|
||
|
||
@router.get('/', response_class=HTMLResponse)
|
||
async def index(request: Request) -> HTMLResponse:
|
||
"""首页(禁止缓存,确保前端更新即时生效)。"""
|
||
return HTMLResponse(
|
||
content=_render_index(),
|
||
headers={'Cache-Control': 'no-cache, no-store, must-revalidate'},
|
||
)
|