Tengo un back-end de Flask con rutas API a las que se accede mediante una aplicación de una sola página de React creada con create-react-app. Cuando uso el servidor de desarrollo create-react-app, mi back-end de Flask funciona.
Me gustaría servir la aplicación React estática construida (usando npm run build ) desde mi servidor Flask. La creación de la aplicación React conduce a la siguiente estructura de directorios:
- 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] Por [crypto] , me refiero a las cadenas generadas aleatoriamente generadas en el momento de la compilación.
Habiendo recibido el archivo index.html , el navegador realiza las siguientes solicitudes:
- GET /static/css/main.[crypto].css - GET /static/css/main.[crypto].css - GET /service-worker.js¿Cómo debo servir estos archivos? Se me ocurrió esto:
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')De esta manera, los activos estáticos se sirven con éxito.
Por otro lado, podría incorporar esto con las utilidades estáticas integradas de Flask. Pero no entiendo cómo configurar esto.
¿Es mi solución lo suficientemente robusta? ¿Hay alguna manera de usar las funciones integradas de Flask para servir estos activos? ¿Hay una mejor manera de usar create-react-app?
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)Eso es con lo que terminé. Entonces, básicamente, capture todas las rutas, pruebe si la ruta es un archivo => enviar archivo => de lo contrario, envíe index.html. De esa manera, puede recargar la aplicación de reacción desde cualquier ruta que desee y no se rompe.
Primero npm run build para construir los archivos de producción estáticos como lo mencionó anteriormente
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')Desafortunadamente, no creo que puedas hacerlo funcionar con la recarga en caliente de desarrollo.
Una solución de trabajo aquí. ¿Alguna vez pensó por qué necesitamos dos carpetas separadas para static y templates ? Para segregar el desorden, ¿no? Pero, es un problema con la compilación de producción, ya que tiene una carpeta para archivos static y de templates y todas las dependencias están vinculadas de esa manera.
La carpeta de build se servirá si la considera tanto static como templates .
Usa algo como esto
from flask import Flask, render_template app = Flask(__name__, static_url_path='', static_folder='build', template_folder='build') @app.route("/") def hello(): return render_template("index.html")Su aplicación de matraz funcionará bien.