python-用Flask服务一个create-react-app

我有一个带有API路由的Flask后端,可通过使用create-react-app样板创建的React单页应用程序访问API路由。 当使用create-react-app内置开发服务器时,我的Flask后端可以正常工作,没问题。

现在,我想从Flask服务器提供内置的(使用index.html)静态React应用程序。 构建react应用会导致以下目录结构:

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

用[crypto]表示在构建时生成的随机生成的字符串。

收到index.html文件后,浏览器随后发出以下请求:

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

我的问题是:我应该如何处理这些文件?我想出了这个:

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

这样,静态资产就可以成功使用。 但这不是一个很好的解决方案。

另一方面,我可以将其与内置flask静态实用程序合并。 但是我不明白如何配置它。

我真的不知道该如何处理,以至于让我重新考虑使用create-react-app,因为这迫使我以一种非常特殊的不便方式来构造我的静态文件夹: 我可以更改应用程序从服务器请求静态内容的方式。

总体而言:我的解决方案足够强大吗? 有没有办法使用内置的烧瓶功能来服务这些资产? 有没有更好的方法来使用create-react-app? 任何输入表示赞赏。 如果需要,我可以提供更多信息。

谢谢阅读 !

Theo asked 2020-06-23T13:01:05Z
3个解决方案
53 votes
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)

那就是我最终得到的。 因此,基本上捕获所有路由,测试路径是否为文件=>发送文件=>否则发送index.html。 这样,您可以从任何希望的路线重新加载react应用,并且不会中断。

Jodo answered 2020-06-23T13:01:20Z
5 votes

首先执行npm run build以构建您上面提到的静态生产文件

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

不幸的是,我认为您无法在开发热重装中使用它。

Pranay Aryal answered 2020-06-23T13:01:44Z
0 votes

接受的答案对我不起作用。 我用过了

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


Lukasz Madon answered 2020-06-23T13:02:04Z
translate from https://stackoverflow.com:/questions/44209978/serving-a-create-react-app-with-flask