Heroku部署FastAPI+React应用时无法加载静态JS/CSS文件
我有一个FastAPI后端与React前端同根目录的应用,在Heroku上构建和部署无报错,FastAPI路由可正常访问,但加载client/build/static文件夹中的JavaScript和CSS文件时出现404 NOT FOUND错误。
现有配置信息
main.py中的静态资源挂载代码
日志显示static_dir为/app/client/build:
# Construct the correct path to the "client/build" directory static_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "client/build") # logging shows static_dir = /app/client/build # Mount the static files from "client/build" app.mount("/static", StaticFiles(directory=static_dir), name="static")
React构建后的index.html内容
通过Heroku bash终端确认index.html的src标签路径正确:
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>MoodRaker</title><base href="/"/><script defer="defer" src="/static/js/main.71b3f3e2.js"></script><link href="/static/css/main.e6c13ad2.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script></body></html>
Heroku访问日志
访问根目录时,静态资源请求返回404:
2023-12-14T19:44:19.106578+00:00 app[web.1]: 98.59.132.14:0 - "GET / HTTP/1.1" 200 2023-12-14T19:44:19.107626+00:00 heroku[router]: at=info method=GET path="/" host=moodtracker-35756345a3ca.herokuapp.com request_id=cb46c81b-2de2-4e1c-b408-d54965e732b2 fwd="98.59.132.14" dyno=web.1 connect=0ms service=2126ms status=200 bytes=1318 protocol=https 2023-12-14T19:44:19.280321+00:00 heroku[router]: at=info method=GET path="/static/css/main.e6c13ad2.css" host=moodtracker-35756345a3ca.herokuapp.com request_id=5517735c-adc3-4bc4-a606-64201bfd30fa fwd="98.59.132.14" dyno=web.1 connect=0ms service=3ms status=404 bytes=173 protocol=https 2023-12-14T19:44:19.273165+00:00 app[web.1]: 98.59.132.14:0 - "GET /js/main.71b3f3e2.js HTTP/1.1" 404 2023-12-14T19:44:19.278364+00:00 app[web.1]: 98.59.132.14:0 - "GET /css/main.e6c13ad2.css HTTP/1.1" 404 2023-12-14T19:44:19.273982+00:00 heroku[router]: at=info method=GET path="/static/js/main.71b3f3e2.js" host=moodtracker-35756345a3ca.herokuapp.com request_id=1424389f-e890-4231-b158-67616f9549d3 fwd="98.59.132.14" dyno=web.1 connect=0ms service=2ms status=404 bytes=173 protocol=https 2023-12-14T19:44:19.813433+00:00 heroku[router]: at=info method=GET path="/manifest.json" host=moodtracker-35756345a3ca.herokuapp.com request_id=5977aef1-6d06-448c-a764-7fffb1f5c650 fwd="98.59.132.14" dyno=web.1 connect=0ms service=8ms status=200 bytes=1318 protocol=https 2023-12-14T19:44:19.622001+00:00 heroku[router]: at=info method=GET path="/favicon.ico" host=moodtracker-35756345a3ca.herokuapp.com request_id=b7618d08-66e9-4eb5-b1b6-19f43f1af972 fwd="98.59.132.14" dyno=web.1 connect=0ms service=10ms status=200 bytes=1318 protocol=https 2023-12-14T19:44:19.619219+00:00 app[web.1]: 98.59.132.14:0 - "GET /favicon.ico HTTP/1.1" 200 2023-12-14T19:44:19.812451+00:00 app[web.1]: 98.59.132.14:0 - "GET /manifest.json HTTP/1.1" 200
直接访问静态资源URL返回404:
// 20231214104738 // https://moodtracker-35756345a3ca.herokuapp.com/static/js/main.71b3f3e2.js { "detail": "Not Found" }
已尝试重新构建React应用并重新部署,本地运行正常,未找到Heroku官方文档相关解决方案,求下一步排查方向。
1. 修正静态资源挂载路径
当前挂载的是/app/client/build,但React构建后静态资源实际存放在client/build/static子目录下。请求/static/js/xxx.js会被FastAPI导向client/build/js/xxx.js,自然找不到文件。
修改main.py中的挂载代码,直接指向client/build/static目录:
static_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "client/build/static") app.mount("/static", StaticFiles(directory=static_dir), name="static")
2. 验证Heroku上的文件存在性
通过Heroku bash终端确认静态资源是否在预期位置:
heroku run bash # 进入容器后执行以下命令检查文件 ls -la /app/client/build/static/js/ ls -la /app/client/build/static/css/
如果文件不存在,说明React构建过程未正确执行:
- 检查React项目
package.json中的build命令是否为"build": "react-scripts build" - 确认Heroku的构建脚本(如
Procfile或package.json中的scripts)是否包含了npm install && npm run build步骤
3. 调整路由挂载顺序
确保静态资源挂载代码放在所有API路由定义之前,避免被其他路由规则拦截匹配。
4. 检查.gitignore配置
如果.gitignore文件中包含client/build,会导致该目录不被纳入Heroku的slug中。修改.gitignore,移除对build目录的排除,或者确保Heroku构建时重新生成build文件夹。
5. 配置React homepage(可选)
如果资源路径生成仍有问题,在React项目的package.json中添加"homepage": ".",重新构建后部署,确保静态资源路径相对正确。
内容的提问来源于stack exchange,提问作者kaliko_kalikova

