React Flask Heroku App Does Not Display Interface

Problem Summary

I recently tried to deploy my local application to Heroku. It is built using flex and the React / Redux interface. After working with Heroku subtleties (procfiles, where he reads package.json, etc.), I can get a backend to show (for example: the flask-admin section works the same as my database) m is still not can reach part of the interface (reaction) of my site. There are no errors that I can detect in Heroku logs, and in the local version my application works fine when starting my python server and NPM start in a static directory.

Any idea why the external interface will not display or how to get it?


Logs:

I deleted some confidential information from the details, but here is what heroku logs --tail gives me when I try to update the application.

 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 

When I look at the source code, I see the code from my index.html file (in the static folder, which is correct), and this particular line is highlighted in red, which makes me think that it does not have bundle.js? <script src="/dist/bundle.js"></script>

When I try to visit the front end, none of them are displayed. I'm really not sure where to look next.

Initial Ideas:

  • Does my server.js file really start with Heroku? I have a "start" script in my .json package, but if procfile runs Python ... does it really start? How to run it without putting it in postinstall or post-build?

  • Is webpack something messing around. My production website is slightly different from my development, so maybe during build time: is production getting spoiled? However, this does not explain why the assembly always succeeds.

  • Is my server.js or webpack forcing formatting in index.html and therefore it cannot parse correctly? Perhaps that is why I see SyntaxError: expected expression, got '< bundle.js:1 in the console?

Update: I received a note from Heroku Support that informed me that Heroku speakers were not designed to support applications with multiple processes, such as mine. As a result, they feel that I will need to make some significant changes so that all HTTP requests are forwarded through one dyno. Perhaps this is my problem?


Here are the files that can help debug:

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); }); 

File structure

 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 at the root This file exists because I am running a multi-line build. Heroku doesn't seem to recognize package.json in statics until I use this to drag it in there.

  { "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 in static

 { "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 prod

 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, }, }), ], }; 

General web package

 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); } 

PROCFILE

web: gunicorn main:app

Buildpacks in Heroku

 heroku buildpacks:set heroku/python heroku buildpacks:add heroku/nodejs 
+5
source share
2 answers

So! It turns out that the Heroku support team was incorrect in analyzing my application. My application is built in two different ways (one for production as well as for development). Using npm run start [see static / package.json ] on the local computer uses a hot reboot and benefits from faster local changes through server.js. However, in a production environment, you want to use the compressed bundle.js file, so my goal was to use npm run build:production [see static / package.json ].

The problem I ran into was SyntaxError: expected expression, got '< bundle.js:1 in the console, and it seemed to me that bundle.js was not loading at all. I have listed a number of correct questions above about why I thought this could happen, but they all suggested that the main problem is the inability to run my application to respond simultaneously with my flash application.

I was completely wrong. I don’t have to start server.js at all. The reason for REAL is that index.html and flask / python were unable to find my bundle.js package and load the interface during production due to an error in the config.py in the flask that I never thought to publish.

The flask has a very specific configuration, which allows you to define static_folder and template_folder . Some time ago, I changed my static folder to another directory, working on some image upload functions. The reason I didn’t catch it is because I am running server.js on a local server for a hot reboot, so I have never seen a compressed bundle.js file error.

After fixing this error, I clicked on the hero and surprisingly ... it worked on the first try!

Here is the correct code that fixed it:

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

When closing a flask / reaction on Heroku when starting:

  • Use multiple buildpacks (one for node, one for python).
  • Use your procfile to download the vial only.
  • You need the package.json file in your root directory ... even if you have another in your static folder like me.
  • Use webpack to compress your response code and submit it in a compressed way.
  • Use render_template with a flask to render the index.html file that contains you the root div for reaction.
  • make sure all your dependencies for React are listed inside the actual β€œdependencies” instead of β€œdevdepencies”, otherwise Heroku will ignore them.

I really hope this helps someone! I slammed my head against the wall for 2 weeks, and that turned out to be a little obscure problem ... isn't that always?

Additional resources: https://codeburst.io/creating-a-full-stack-web-application-with-python-npm-webpack-and-react-8925800503d9 Although this is very simplified ... it led me to search for my error so I will post it here.

+1
source

The checkbox of your flash drive does not work on the same port as you forward your traffic:

 Starting gunicorn 19.6.0 Listening at: 0.0.0.0:13521 (4) app.all(/^\/api\/(.*)/, (req, res) => { proxy.web(req, res, { target: 'http://0.0.0.0:8081' }); }); 

The checkbox listens on port 13521 (randomly selected), but the / api / route route is redirected to port 8081. Instead, you should probably configure machine guns to use the fixed port: http://docs.gunicorn.org/en/latest/settings .html # bind

+1
source

Source: https://habr.com/ru/post/1275274/


All Articles