I am working on an app with a Flask backend and a React frontend, and I was unable to get hot reloading working. I then tried modifying the react-hot-loader-minimal-boilerplate example to work with a Flask backend, and then hot reloading stopped working as well, and I had to Ctrl-F5 it in order to get the changes to show. The Flask server code is given below:
from flask import Flask, render_template
app = Flask(__name__, static_url_path='',
template_folder='', static_folder='dist')
@app.route('/')
def main():
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True, reloader_type='stat', port=8080)
I also modified package.json, and moved the script to start:
{
"scripts": {"start": "webpack-dev-server --hot --inline --progress"},
"name": "react-hot-loader-minimal-boilerplate",
"version": "1.0.0",
"description": "",
"main": "index.js",
"repository": {
"type": "git",
"url": "git+https://github.com/wkwiatek/react-hot-loader-minimal-boilerplate.git"
},
"keywords": [],
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/wkwiatek/react-hot-loader-minimal-boilerplate/issues"
},
"homepage": "https://github.com/wkwiatek/react-hot-loader-minimal-boilerplate#readme",
"dependencies": {
"react": "^15.4.2",
"react-dom": "^15.4.2",
"react-router-dom": "^4.2.2"
},
"devDependencies": {
"babel-core": "^6.23.1",
"babel-loader": "^6.3.2",
"babel-polyfill": "^6.23.0",
"babel-preset-latest": "^6.22.0",
"babel-preset-react": "^6.23.0",
"react-hot-loader": "^3.0.0-beta.6",
"webpack": "^2.2.1",
"webpack-dev-server": "^2.4.1"
}
}
Any help is appreciated, thanks!
EDIT: I should additionally note that I built the app.js file using the "webpack -w" command.
You should refer to https://github.com/gaearon/react-hot-loader/tree/master/docs#migration-to-30
Sorry, I'm not understanding what the migration to version 3.0 has to do
with my question? Could you go into a bit more detail please?
ᐧ
On Sat, Sep 30, 2017 at 3:02 PM, Greg Bergé notifications@github.com
wrote:
You should refer to https://github.com/gaearon/
react-hot-loader/tree/master/docs#migration-to-30—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/gaearon/react-hot-loader/issues/649#issuecomment-333329085,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ANiP1m0xjr97cherpiuo4c_1VzsIQAJrks5snpBUgaJpZM4PppsC
.
In fact, there is no good documentation for now. And it is the best documentation we have. You have several things to do:
<AppLoader>module.hot.acceptreact-hot-loader/patch) to your bundlereact-hot-loader/babel) to your babel configApologies, I don't think the OP was clear. I am using the example code from https://github.com/wkwiatek/react-hot-loader-minimal-boilerplate to start out, which is one of the recommended examples for react-hot-loader. The code does all four of the things you mentioned already, and hot reloading works fine. However, when I made the modifications that I mentioned in the OP, such as switching the server to Flask, and slightly changing package.json, the hot reloading stopped working. I am trying to figure out why, and how to fix these issues.
@neoziro, Do you think you could reopen this issue, since there doesn't seem to be a solution yet?
The only wrong thing I see in your example is using "start": "..." rather than "scripts: { "start": "..." }.
You should also try to use webpack-dev-server in proxy mode on your server.
Hmm, I changed the "start:..." to "scripts": {"start": "webpack-dev-server --hot --inline --progress"}, but the problem persists. I'll take a look at webpack-dev-server proxy mode. Also, @gaearon, do you have any idea what could be wrong here?
You have to use proxy mode if you want to use your Flask server + webpack-dev-server.
It has nothing related with react-hot-loader.
Sorry, I'm not following. The fact that hot reloading works with node, but not with flask seems to indicate that this does have something to do with react-hot-loader, doesn't it?
I modified my webpack configuration file to use webpack proxying (on port 8080), but hot reloading still does not work. How exactly do I configure it properly:
const webpack = require('webpack')
const path = require('path')
module.exports = {
devtool: 'source-map',
entry: {
'app': [
'babel-polyfill',
'react-hot-loader/patch',
'./src/index'
]
},
output: {
path: path.resolve(__dirname, './dist'),
filename: '[name].js'
},
module: {
rules: [
{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader' }
]
},
devServer: {
proxy: {
"/": "http://localhost:8080"
}
}
}
Thanks for your help.
@alexanderwhatley you missed { "hot": true } in devServer.
Server doesn't influence hot reloading, it is just a problem in your webpack / babel / patch / AppLoader configuration, nothing related to Flask.
Hmm, it still doesn't work. If it isn't too much trouble for you, do you think you could try to replicate the problem on your end? It should be quick.
Clone the repository https://github.com/wkwiatek/react-hot-loader-minimal-boilerplate and run 'npm run dev' and verify that hot reloading works by changing the text in the file src/containers/Root.js.
To enable the flask server, stop the npm server, and create a file app.py with the following code:
from flask import Flask, render_template
app = Flask(__name__, static_url_path='',
template_folder='', static_folder='dist')
@app.route('/')
def main():
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True, reloader_type='stat', port=8080)
Change package.json to the following:
{
"scripts": {"start": "webpack-dev-server --hot"},
"name": "react-hot-loader-minimal-boilerplate",
"version": "1.0.0",
"description": "",
"main": "index.js",
"repository": {
"type": "git",
"url": "git+https://github.com/wkwiatek/react-hot-loader-minimal-boilerplate.git"
},
"keywords": [],
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/wkwiatek/react-hot-loader-minimal-boilerplate/issues"
},
"homepage": "https://github.com/wkwiatek/react-hot-loader-minimal-boilerplate#readme",
"dependencies": {
"react": "^15.4.2",
"react-dom": "^15.4.2",
"react-router-dom": "^4.2.2"
},
"devDependencies": {
"babel-core": "^6.23.1",
"babel-loader": "^6.3.2",
"babel-polyfill": "^6.23.0",
"babel-preset-latest": "^6.22.0",
"babel-preset-react": "^6.23.0",
"react-hot-loader": "^3.0.0-beta.6",
"webpack": "^2.2.1",
"webpack-dev-server": "^2.4.1"
}
}
Change webpack.config.js to the following:
const webpack = require('webpack')
const path = require('path')
module.exports = {
devtool: 'source-map',
entry: {
'app': [
'babel-polyfill',
'react-hot-loader/patch',
'./src/index'
]
},
output: {
path: path.resolve(__dirname, './dist'),
filename: '[name].js'
},
module: {
rules: [
{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader' }
]
},
devServer: {
"hot": true,
proxy: {
"/": "http://localhost:8080"
}
}
}
I am sorry, I do not have time to do that, just follow webpack hot reloading and react hot reloading documentation and it will work. With a quick look, I can tell that you devServer config is not correct: "hot" is under proxy.
"hot" is not under proxy, it is under devServer (https://webpack.js.org/configuration/dev-server/#devserver-hot).
The fact that hot reloading is not working under my configuration could indicate either a potential bug, or perhaps something in the library that could be improved to make it easier to use. I understand that you're busy, but could you at least reopen this issue, so that someone else could maybe take a look and try replicating? Thanks.
There is no dependence on Flask or any backend in this library. I think you may have this a bit confused. In development, you have the webpack-dev-server which serves two files index.html and main.js. With just the basic set-up, it assumes NO backend API. It looks like here you are trying to use Flask to also serve index.html and main.js (although I see no code right now that additionally serves main.js) This will not work. You cannot use both webpack-dev-server and Flask. You have to use webpack-dev-server. The only use for Flask is to proxy API requests and it looks like now you are not even using webpack-dev-server because you are running webpack -w.
I suggest doing this instead:
webpack-dev-server like in the example. Copy exactly the example. HOST = 0.0.0.0 /api to localhost:5000Here is an example config for the dev server with proxy mode(I am using Flask for an API server in project). It has socket.io also, you may not need that.
devServer: {
hot: true,
proxy: {
'/api': {
target: 'http://localhost:5000',
pathRewrite: {'^/api': ''}
},
'/socket.io': {
target: 'http://localhost:5000',
ws: true
}
},
historyApiFallback: true,
contentBase: resolve(__dirname, 'public'),
port: 8881,
publicPath: '/',
host: '0.0.0.0',
overlay: {
warnings: true,
errors: true
},
watchContentBase: true,
watchOptions: {
poll: true
}
},
Thanks @mrwillis, I will give that a try. When you say "api requests starting with /api", are you referring to the Flask routes?
Indeed. So anything ending with */api will get routed to localhost:5000 (usually it would get routed to localhost:5000/api but I specified in the above config a pathRewrite: {'^/api': ''}. Hopefully that is clear. Here is a snippet in my actual app with the above config.
Flask endpoint:
@app.route('/etf-static-info', methods=['POST'])
@login_required
def get_static_data():
requestedEtf = request.get_json()['etf']
static_info = queries.get_static_data(requestedEtf, utils.get_last_trading_day())
return jsonify(static=static_info)
And the call in JS:
fetch('/api/etf-static-info', {
credentials: 'same-origin',
method: 'POST',
body: JSON.stringify({
etf: etf
}),
headers: {
'Content-Type': 'application/json'
}
}).then(handleFetchErrorMiddleware).then(r => r.json())
Hi @mrwillis, I was able to get hot reloading with dev server working! Thanks for your help! How do you do the hot reloading in production mode though?
@alexanderwhatley There is no hot reloading in production. All of this is just for development. You don't need to hot reload anything. In production, you use webpack to bundle main.js and then all you're doing is hosting the bundled index.html and main.js on a web server. A popular set-up for instance using Flask is using nginx as a reverse proxy, hosting main.js and index.html, and then 'reverse proxying' any API requests to a gunicorn server.
Hmm, so how do I update the web pages without a hard refresh? With the current setup, using Flask and 'webpack -w' to make the bundle, the old version of the webpage gets cached, and does not change until I do a hard refresh.
@mrwillis?
@alexanderwhatley you have to trigger an hard refresh for your users. You can take a look at Service Worker or you can do it by yourself:
I close this issue since it is not related with React Hot Loader, feel free to continue the discussion here.
Thanks all for indulging the discussion despite it not being quite RHL related. I am also new to a mixed Flask/ React setup & had similar questions. @mrwillis had some responses that pointed me towards the right questions.
Since this thread still comes up p high on a google search, I think it may be useful to point others with similar questions about setting up React HMR w/ a Flask server to this article on The Missing Manual to React Hot Loader.
It's focused on a different implementation, but the article helps clarify hot module & proxying concepts, and ultimately shows you how to sync HMR and the webpack-dev-server with a Flask app by just proxying everything.
Most helpful comment
There is no dependence on Flask or any backend in this library. I think you may have this a bit confused. In development, you have the
webpack-dev-serverwhich serves two filesindex.htmlandmain.js. With just the basic set-up, it assumes NO backend API. It looks like here you are trying to use Flask to also serveindex.htmlandmain.js(although I see no code right now that additionally servesmain.js) This will not work. You cannot use bothwebpack-dev-serverand Flask. You have to usewebpack-dev-server. The only use for Flask is to proxy API requests and it looks like now you are not even usingwebpack-dev-serverbecause you are runningwebpack -w.I suggest doing this instead:
webpack-dev-serverlike in the example. Copy exactly the example.HOST = 0.0.0.0/apitolocalhost:5000Here is an example config for the dev server with proxy mode(I am using Flask for an API server in project). It has
socket.ioalso, you may not need that.