在Heroku部署Django+React项目遇Uncaught SyntaxError问题求助
解决Django+React部署Heroku时bundle.js返回index.html的问题
嘿,这个问题我之前帮朋友排查过,本质上就是Heroku上请求你的bundle.js时,Django没找到对应的静态文件,反而返回了index.html,浏览器把HTML当JS解析自然就报Uncaught SyntaxError: Unexpected token <错了。咱们一步步来解决:
1. 先搞定Heroku的构建顺序
Heroku需要先打包React代码,再收集Django静态文件,所以得调整buildpack的顺序:
- 登录Heroku控制台,进入你的项目设置,找到Buildpacks
- 添加两个buildpack:先加
heroku/nodejs,再加heroku/python(顺序很重要,先处理Node.js的构建)
2. 确保Webpack打包能在Heroku上自动执行
- 打开React项目目录下的
package.json,在scripts里添加生产环境打包命令:"scripts": { "build": "webpack --mode production", // 其他脚本... } - 如果你的React项目在子目录(比如
frontend),根目录的package.json要把build命令指向子目录:"scripts": { "build": "cd frontend && npm run build" }
3. 修正Django的静态文件配置(关键)
打开settings.py,调整这些配置:
- 确保
INSTALLED_APPS里whitenoise的顺序正确(在django.contrib.staticfiles之前):INSTALLED_APPS = [ 'whitenoise.runserver_nostatic', 'django.contrib.staticfiles', # 你的其他应用... ] - 调整
MIDDLEWARE顺序(WhiteNoiseMiddleware要在SecurityMiddleware之后):MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware', # 其他中间件... ] - 配置静态文件路径,让Django能找到Webpack打包后的文件:
from pathlib import Path BASE_DIR = Path(__file__).resolve().parent.parent STATIC_URL = '/static/' STATIC_ROOT = BASE_DIR / 'staticfiles' # Heroku收集静态文件的目录 STATICFILES_DIRS = [ BASE_DIR / 'frontend' / 'dist', # 替换成你的Webpack输出目录 ] # 启用Whitenoise的压缩和缓存优化(可选但推荐) STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
4. 检查Webpack的配置
打开webpack.config.js,确保publicPath和BundleTracker的路径正确:
const path = require('path'); const BundleTracker = require('webpack-bundle-tracker'); module.exports = { entry: './src/index.js', // 你的React入口文件 output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist'), // 输出到对应目录 publicPath: '/static/' // 关键!生成的bundle路径要以/static/开头 }, plugins: [ new BundleTracker({ path: path.resolve(__dirname, '../'), // 生成webpack-stats.json到项目根目录 filename: 'webpack-stats.json' }) ], // 其他Webpack配置... };
5. 修正Django的URL路由顺序
确保你的SPA catch-all路由是最后一个,这样静态文件请求不会被它拦截:
from django.urls import path from django.views.generic.base import TemplateView urlpatterns = [ # 你的API路由、admin路由等... # 最后添加SPA的兜底路由 path('', TemplateView.as_view(template_name='index.html')), ]
6. 最后检查几个细节
- 确保Heroku上的
DEBUG环境变量设为False(生产环境不能开DEBUG):
用Heroku CLI执行:heroku config:set DEBUG=False - 查看Heroku的构建日志,确认:
npm run build成功执行,生成了bundle.jspython manage.py collectstatic成功把bundle.js复制到了staticfiles目录
这样调整后,Heroku就能正确识别并返回你的bundle.js,不会再返回index.html了。
内容的提问来源于stack exchange,提问作者Jehob
相关产品推荐
相关产品推荐

