Obsługujący front end stworzony z create-react-app z Flask

Mam back-end Flask z trasami API, do których dostęp ma Pojedyncza strona Reacta utworzona przy użyciu create-react-app. Podczas korzystania z serwera deweloperskiego create-react-app back end my Flask działa.

Chciałbym obsługiwać zbudowaną (używając npm run build) statyczną aplikację Reactową z mojego serwera Flask. Budowanie aplikacji Reactowej prowadzi do następującej struktury katalogów:

- 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]

Przez [crypto], mam na myśli losowo generowane ciągi generowane w czasie budowania.

Mając po odebraniu pliku index.html przeglądarka wykonuje następujące żądania:

- GET /static/css/main.[crypto].css
- GET /static/css/main.[crypto].css
- GET /service-worker.js

Jak mam podawać te pliki? Wymyśliłem to:

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')

W ten sposób zasoby statyczne są z powodzeniem obsługiwane.

Z drugiej strony, mógłbym włączyć to z wbudowanymi narzędziami statycznymi kolby. Ale nie rozumiem, jak to skonfigurować.

Czy moje rozwiązanie jest wystarczająco wytrzymałe? Czy istnieje sposób na wykorzystanie wbudowanych funkcji Flask do obsługi tych zasobów? Czy istnieje lepszy sposób użycia create-react-app?
Author: davidism, 2017-05-26

4 answers

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)
To z tym skończyłem. Tak więc zasadniczo Złap wszystkie trasy, sprawdź, czy ścieżka jest plikiem = > Wyślij plik = > else wyślij indeks.html. W ten sposób możesz przeładować aplikację react z dowolnej trasy i nie pęknie.
 79
Author: Jodo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-30 06:02:24

Najpierw zrób npm run build, aby zbudować statyczne pliki produkcyjne, o których wspomniałeś powyżej

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')

Niestety, nie wydaje mi się, aby można było to zrobić z rozwojem hot-reload.

 12
Author: Pranay Aryal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-11 03:22:46

Tutaj działa rozwiązanie. Zastanawiałeś się kiedyś, dlaczego potrzebujemy dwóch oddzielnych folderów dla static i templates. Segregować bałagan, prawda? Ale jest to problem z kompilacją produkcyjną, ponieważ ma jeden folder dla plików static i templates i wszystkie zależności są połączone w ten sposób.

Folder build zostanie dostarczony, jeśli rozważysz zarówno static, jak i templates.

Użyj czegoś takiego

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")

Twoja aplikacja flask będzie działać dobrze.

 9
Author: pankaj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-26 09:52:49

Zaakceptowana odpowiedź nie działa na mnie. Użyłem

import os

from flask import Flask, send_from_directory, jsonify, render_template, request

from server.landing import landing as landing_bp
from server.api import api as api_bp

app = Flask(__name__, static_folder="../client/build")
app.register_blueprint(landing_bp, url_prefix="/landing")
app.register_blueprint(api_bp, url_prefix="/api/v1")


@app.route("/")
def serve():
    """serves React App"""
    return send_from_directory(app.static_folder, "index.html")


@app.route("/<path:path>")
def static_proxy(path):
    """static folder serve"""
    file_name = path.split("/")[-1]
    dir_name = os.path.join(app.static_folder, "/".join(path.split("/")[:-1]))
    return send_from_directory(dir_name, file_name)


@app.errorhandler(404)
def handle_404(e):
    if request.path.startswith("/api/"):
        return jsonify(message="Resource not found"), 404
    return send_from_directory(app.static_folder, "index.html")


@app.errorhandler(405)
def handle_405(e):
    if request.path.startswith("/api/"):
        return jsonify(message="Mehtod not allowed"), 405
    return e


 3
Author: Lukasz Madon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-25 17:37:29