gpt4 book ai didi

python - React Flask Heroku App 不显示前端

转载 作者:太空狗 更新时间:2023-10-30 00:01:18 25 4
gpt4 key购买 nike

问题总结

我最近尝试将我的本地应用程序部署到 Heroku。它是用 Flask 后端和 React/Redux 前端构建的。在处理了 Heroku 的复杂问题(procfiles,它读取 package.json 等)之后,我能够显示后端(例如:flask-admin 部分和我的数据库一样工作),但我'我仍然无法访问我网站的前端( react )部分。我在 Heroku 日志和本地版本上没有发现任何错误,当我启动我的 python 服务器并执行 NPM start 时,我的应用程序工作得很好。在静态目录中。

知道为什么前端不显示或如何访问它吗?


日志:

我已经从细节中删除了一些敏感信息,但这是 heroku logs --tail当我尝试刷新应用程序时给我。

2018-02-11T01:18:01.000000+00:00 app[api]: Build succeeded
2018-02-11T01:21:12.305017+00:00 heroku[web.1]: Starting process with command `gunicorn main:app`
2018-02-11T01:21:16.374150+00:00 heroku[web.1]: State changed from starting to up
2018-02-11T01:21:15.948707+00:00 app[web.1]: [2018-02-11 01:21:15 +0000] [4] [INFO] Starting gunicorn 19.6.0
2018-02-11T01:21:15.949430+00:00 app[web.1]: [2018-02-11 01:21:15 +0000] [4] [INFO] Listening at: http://0.0.0.0:29162



2018-02-11T01:21:19.278810+00:00 heroku[router]: at=info method=GET path="/" host=removed.herokuapp.com request_id=bd74ea4c-3e3a-403b-8850-198b7dec20e2 fwd="104.152.1.62" dyno=web.1 connect=1ms service=2146ms status=200 bytes=2895 protocol=https
2018-02-11T01:21:19.650759+00:00 heroku[router]: at=info method=GET path="/dist/bundle.css" host=removed.herokuapp.com request_id=48183249-fb12-4c7a-9a53-2a57ab58d89b fwd="104.152.1.62" dyno=web.1 connect=0ms service=3ms status=200 bytes=2895 protocol=https
2018-02-11T01:21:19.816113+00:00 heroku[router]: at=info method=GET path="/dist/bundle.js" host=removed.herokuapp.com request_id=1c8b258b-4187-4df6-af35-784e62fb97e5 fwd="104.152.1.62" dyno=web.1 connect=1ms service=3ms status=200 bytes=2895 protocol=https

当我查看源代码时,我看到了我的 index.html 文件中的代码(在 static 文件夹中,这是正确的)并且这一行以红色突出显示,这让我觉得它缺少 bundle.js? <script src="/dist/bundle.js"></script>

当我尝试访问前端时,没有显示任何内容。我真的不确定接下来要看哪里。

初步想法:

  1. 我的 server.js 文件实际上是在 Heroku 上启动的吗?我的 package.json 中有一个“开始”脚本,但是如果 procfile 正在执行 Python...它真的开始了吗?如何在不将其放入安装后或构建后步骤的情况下启动它?

  2. webpack 搞砸了吗?我的生产 webpack 与我的开发略有不同,所以也许在构建过程中:生产它变得一团糟?但是,这并不能解释为什么构建总是成功。

  3. 我的 server.js 或 webpack 是否强制对 index.html 文件进行格式化,因此它无法正确解析?也许这就是我看到的原因 SyntaxError: expected expression, got '< bundle.js:1在控制台?

更新:我收到了 Heroku 支持团队的通知,告诉我 Heroku dynos 不是为支持像我这样的多进程应用程序而构建的。结果,他们觉得我需要进行一些重大更改才能让所有 HTTP 请求通过一个 dyno 进行转发。也许这是我的问题?


以下是可能有助于调试的文件:

Server.js

const http = require('http');
const express = require('express');
const httpProxy = require('http-proxy');
const path = require('path');
const apiPort = process.env.PORT || 8081;

const proxy = httpProxy.createProxyServer({});

const app = express();

app.use(require('morgan')('short'));

(function initWebpack() {
const webpack = require('webpack');
const webpackConfig = require('./webpack/common.config');

const compiler = webpack(webpackConfig);

app.use(require('webpack-dev-middleware')(compiler, {
noInfo: true, publicPath: webpackConfig.output.publicPath,
}));

app.use(require('webpack-hot-middleware')(compiler, {
log: console.log, path: '/__webpack_hmr', heartbeat: 10 * 1000,
}));

app.use(express.static(path.join(__dirname, '/')));
}());


app.all(/^\/api\/(.*)/, (req, res) => {
proxy.web(req, res, { target: `http://0.0.0.0:${apiPort}` });
});

app.get(/.*/, (req, res) => {
res.sendFile(path.join(__dirname, '/index.html'));
});


const server = http.createServer(app);
server.listen(process.env.PORT || 8080, () => {
const address = server.address();
console.log('Listening on: %j', address);
console.log(' -> that probably means: http://0.0.0.0:%d', address.port);
});

文件结构

ROOT
├──/application
│ ├── models.py
│ ├── app.py
├──/static
│ ├──/bin
│ ├──/dist
│ │ ├──bundle.js
│ ├──/node_modules
│ ├──/src
│ │ ├──/actions
│ │ ├──/components
│ │ │ ├──/examplecomponenthere
│ │ │ │ ├──index.js (for example component)
│ │ ├──/constants
│ │ ├──/containers
│ │ ├──/reducers
│ │ ├──/store
│ │ ├──/webpack
│ ├──index.html
│ ├──package.json (the true one)
│ ├──server.js
├──/tests
├──config.py
├──index.py
├──main.py
├──package.json (one to help heroku start)
├──procfile
├──requirements.txt.
├──setup.py
├──tests.py

根目录中的 Package.json该文件存在是因为我正在运行多重构建。 Heroku 似乎无法识别静态的 package.json,直到我使用这个将它推到那里。

    { 
"name": "rmmd",
"version": "0.0.1",
"engines": {
"node": "6.11.1",
"npm": "3.10.10"
},
"scripts": {
"start": "node static/bin/server.js",
"heroku-postbuild": "cd static && npm install && npm run build:production"
}
}

静态的 Package.json

{
"name": "redux-easy-boilerplate",
"version": "1.3.3",
"description": "",
"scripts": {
"clean": "rimraf dist",
"build": "webpack --progress --verbose --colors --display-error-details --config webpack/common.config.js",
"build:production": "npm run clean && npm run build",
"lint": "eslint src",
"start": "node bin/server.js",
"test": "karma start"
},
"repository": {
"type": "git",
"url": ""
},
"keywords": [
"react",
"reactjs",
"boilerplate",
"redux",
"hot",
"reload",
"hmr",
"live",
"edit",
"webpack"
],
"author": "https://github.com/anorudes, https://github.com/keske",
"license": "MIT",
"devDependencies": {
"webpack-dev-middleware": "^1.5.0",
"webpack-dev-server": "^1.14.1",
"webpack-hot-middleware": "^2.6.0",
},
"dependencies": {
"ant-design-pro": "^0.3.1",
"antd": "^3.0.0",
"lodash": "^4.17.4",
"prop-types": "^15.6.0",
"react-bootstrap": "^0.31.0",
"redux-devtools-extension": "^2.13.2",
"autoprefixer": "6.5.3",
"axios": "^0.15.3",
"babel-core": "^6.4.5",
"babel-eslint": "^7.1.1",
"babel-loader": "^6.2.1",
"babel-plugin-import": "^1.2.1",
"babel-plugin-react-transform": "^2.0.0",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-polyfill": "^6.3.14",
"babel-preset-es2015": "^6.3.13",
"babel-preset-react": "^6.3.13",
"babel-preset-react-hmre": "^1.0.1",
"babel-preset-stage-0": "^6.3.13",
"bootstrap": "^3.3.5",
"bootstrap-loader": "^1.2.0-beta.1",
"bootstrap-sass": "^3.3.6",
"bootstrap-webpack": "0.0.5",
"classnames": "^2.2.3",
"css-loader": "^0.26.4",
"csswring": "^5.1.0",
"deep-equal": "^1.0.1",
"eslint": "^3.4.0",
"eslint-config-airbnb": "13.0.0",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-jsx-a11y": "^3.0.1",
"eslint-plugin-react": "^6.1.2",
"expect": "^1.13.4",
"exports-loader": "^0.6.2",
"expose-loader": "^0.7.1",
"express": "^4.13.4",
"express-open-in-editor": "^1.1.0",
"extract-text-webpack-plugin": "^1.0.1",
"file-loader": "^0.9.0",
"gapi": "0.0.3",
"history": "^4.4.1",
"http-proxy": "^1.12.0",
"imports-loader": "^0.6.5",
"jasmine-core": "^2.4.1",
"jquery": "^3.1.0",
"jwt-decode": "^2.1.0",
"karma": "^1.2.0",
"karma-chrome-launcher": "^2.0.0",
"karma-mocha": "^1.1.1",
"karma-webpack": "^1.7.0",
"less": "^2.7.2",
"less-loader": "^2.2.3",
"lodash": "^4.5.1",
"material-ui": "^0.16.4",
"mocha": "^3.0.2",
"morgan": "^1.6.1",
"node-sass": "^3.4.2",
"postcss-import": "^9.0.0",
"postcss-loader": "^1.1.1",
"q": "^1.4.1",
"qs": "^6.1.0",
"rc-datepicker": "^4.0.1",
"react": "^15.3.1",
"react-addons-css-transition-group": "^15.3.1",
"react-bootstrap": "^0.31.0",
"react-calendar-component": "^1.0.0",
"react-date-picker": "^5.3.28",
"react-datepicker": "^0.37.0",
"react-document-meta": "^2.0.0-rc2",
"react-dom": "^15.1.0",
"react-forms": "^2.0.0-beta33",
"react-hot-loader": "^1.3.0",
"react-loading-order-with-animation": "^1.0.0",
"react-onclickoutside": "^5.3.3",
"react-redux": "^4.3.0",
"react-router": "3.0.0",
"react-router-redux": "^4.0.0",
"react-tap-event-plugin": "^2.0.1",
"react-transform-hmr": "^1.0.1",
"redux": "^3.2.1",
"redux-form": "^6.0.1",
"redux-logger": "2.7.4",
"redux-thunk": "^2.1.0",
"resolve-url-loader": "^1.4.3",
"rimraf": "^2.5.0",
"sass-loader": "^4.0.0",
"style-loader": "^0.13.0",
"url-loader": "^0.5.7",
"webpack": "^1.12.11",
"webpack-merge": "^1.0.2",
"yargs": "^6.5.0"
}
}

Webpack 产品

const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
devtool: 'source-map',

entry: ['bootstrap-loader/extractStyles', './src/index'],
output: {
publicPath: '/dist/',
},

module: {
loaders: [
{
test: /\.scss$/,
loader: 'style!css!postcss-loader!sass',
},
],
},

plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"',
},
__DEVELOPMENT__: false,
}),
new ExtractTextPlugin('bundle.css'),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
},
}),
],
};

Webpack 通用

const path = require('path');
const autoprefixer = require('autoprefixer');
const postcssImport = require('postcss-import');
const merge = require('webpack-merge');

const development = require('./dev.config');
const production = require('./prod.config');

require('babel-polyfill').default;

const TARGET = process.env.npm_lifecycle_event;

const PATHS = {
app: path.join(__dirname, '../src'),
build: path.join(__dirname, '../dist'),
};

process.env.BABEL_ENV = TARGET;

const common = {
entry: [
PATHS.app,
],

output: {
path: PATHS.build,
filename: 'bundle.js',
},

resolve: {
extensions: ['', '.jsx', '.js', '.json', '.scss'],
modulesDirectories: ['node_modules', PATHS.app],
},

module: {
loaders: [{
test: /bootstrap-sass\/assets\/javascripts\//,
loader: 'imports?jQuery=jquery',
}, {
test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url?limit=10000&mimetype=application/font-woff',
}, {
test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url?limit=10000&mimetype=application/font-woff2',
}, {
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url?limit=10000&mimetype=application/octet-stream',
}, {
test: /\.otf(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url?limit=10000&mimetype=application/font-otf',
}, {
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
loader: 'file',
}, {
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url?limit=10000&mimetype=image/svg+xml',
}, {
test: /\.js$/,
loaders: ['babel-loader'],
exclude: /node_modules/,
}, {
test: /\.css$/,
include: /node_modules/,
loaders: ['style-loader', 'css-loader'],
}, {
test: /\.png$/,
loader: 'file?name=[name].[ext]',
}, {
test: /\.jpg$/,
loader: 'file?name=[name].[ext]',
}],
},

postcss: (webpack) => (
[
autoprefixer({
browsers: ['last 2 versions'],
})
]
),
};

if (TARGET === 'start' || !TARGET) {
module.exports = merge(development, common);
}

if (TARGET === 'build' || !TARGET) {
module.exports = merge(production, common);
}

过程文件

web: gunicorn main:app

Heroku 中的 Buildpack

heroku buildpacks:set heroku/python
heroku buildpacks:add heroku/nodejs

最佳答案

所以!事实证明,Heroku 支持团队对我的应用程序的分析是错误的。我的应用程序以两种不同的方式构建(一种用于生产和开发)。使用 npm run start [参见 static/package.json] 在本地利用热重载,并受益于通过 server.js 进行的更快的本地更改。但是,在生产环境中,您想使用压缩的 bundle.js 文件,所以我的目标是使用 npm run build:production [参见 static/package.json]。

我遇到的问题是 SyntaxError: expected expression, got '< bundle.js:1在控制台中,在我看来 bundle.js 根本没有加载。我在上面列出了一系列关于为什么我认为这可能会发生的有效问题,但他们都认为主要问题是无法与我的 Flask 应用程序同时运行我的 React 应用程序。

我完全错了。我根本不需要运行 server.js。 index.html 和 flask/python 无法找到我的 bundle.js 并在生产环境中加载前端的真正原因是 config.py 中的一个错误。 flask 中的文件,我从未想过要发布。

Flask 有一个非常特殊的配置,允许 static_folder待定义和template_folder .前一段时间,我在处理一些图像上传功能时将我的 static_folder 换成了另一个目录。我从未发现它的原因是因为在本地我运行 server.js 进行热重载,所以我从未看到压缩的 bundle.js 文件出错。

修复这个错误后,我推送到 heroku,令人惊讶的是......它在第一次尝试时就成功了!

这是修复它的正确代码:

app = Flask(__name__, static_folder="./static/dist", template_folder="./static")

在 Heroku 上运行 flask/react 应用程序时关闭:

  • 使用多个构建包(一个用于 Node ,一个用于 python)。
  • 使用您的 procfile 仅加载 flask 端。
  • 您的根目录中需要一个 package.json 文件...即使您像我一样在静态文件夹中有另一个文件。
  • 使用 webpack 压缩您的 React 代码并以压缩方式提供。
  • 使用render_template用 flask 渲染包含你的 index.html 文件 root用于 react 的 div。
  • 确保 React 的所有依赖项都列在实际的“依赖项”而不是“开发依赖项”中,否则 Heroku 会忽略它们。

我真的希望这对某人有帮助!我用头撞墙 2 周,结果发现这是一个不起眼的小问题......不是总是这样吗?

其他资源:https://codeburst.io/creating-a-full-stack-web-application-with-python-npm-webpack-and-react-8925800503d9虽然这非常简单……正是它让我找到了我的错误,所以我会把它贴在这里。

关于python - React Flask Heroku App 不显示前端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48713701/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com