I have a Flask back-end with API routes which are accessed by a React single page application created using create-react-app. When using the create-react-app dev server, my Flask back end works.
I would like to serve the built (using npm run build
) static React app from my Flask server. Building the React app leads to the following directory structure:
- build - static - css - style.[crypto].css - style.[crypto].css.map - js - main.[crypto].js - main.[crypto].js.map - index.html - service-worker.js - [more meta files]
By [crypto]
, I mean the randomly generated strings generated at build time.
Having received the index.html
file, the browser then makes the following requests:
- GET /static/css/main.[crypto].css - GET /static/css/main.[crypto].css - GET /service-worker.js
How should I serve these files? I came up with this:
from flask import Blueprint, send_from_directory static = Blueprint('static', __name__) @static.route('/') def serve_static_index(): return send_from_directory('../client/build/', 'index.html') @static.route('/static/<path:path>') # serve whatever the client requested in the static folder def serve_static(path): return send_from_directory('../client/build/static/', path) @static.route('/service-worker.js') def serve_worker(): return send_from_directory('../client/build/', 'service-worker.js')
This way, the static assets are successfully served.
On the other hand, I could incorporate this with the built-in Flask static utilities. But I do not understand how to configure this.
Is my solution robust enough? Is there a way to use built-in Flask features to serve these assets? Is there a better way to use create-react-app?
We now have a complete Flask + React app that uses Flask to collect data from a SQlite database and React to render output on the browser. If you followed along as you did, you should have output similar to the one below on the browser.
Let's look at the small, yet powerful JavaScript UI library ReactJS in action, as we build a basic web application. This app is powered by Python 3 and the Flask framework in the back-end and React in the front. In addition, we will use gulp.
import os from flask import Flask, send_from_directory app = Flask(__name__, static_folder='react_app/build') # Serve React App @app.route('/', defaults={'path': ''}) @app.route('/<path:path>') def serve(path): if path != "" and os.path.exists(app.static_folder + '/' + path): return send_from_directory(app.static_folder, path) else: return send_from_directory(app.static_folder, 'index.html') if __name__ == '__main__': app.run(use_reloader=True, port=5000, threaded=True)
Thats what I ended up with. So bascially catch all routes, test if the path is a file => send file => else send the index.html. That way you can reload the react app from any route you wish and it does not break.
First do npm run build
to build the static production files as mentioned by you above
from flask import Flask, render_template app = Flask(__name__, static_folder="build/static", template_folder="build") @app.route("/") def hello(): return render_template('index.html') print('Starting Flask!') app.debug=True app.run(host='0.0.0.0')
Unfortunately, I don't think you can get it work with the development hot-reload.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With