与Flask一起提供create-react-app

The*_*heo 48 python flask python-3.x reactjs create-react-app

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

现在,我想npm run build从我的Flask服务器提供构建(使用)静态反应应用程序.构建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]
Run Code Online (Sandbox Code Playgroud)

通过[crypto],我的意思是在构建时生成的随机生成的字符串.

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

- GET /static/css/main.[crypto].css
- GET /static/css/main.[crypto].css
- GET /service-worker.js
Run Code Online (Sandbox Code Playgroud)

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

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')
Run Code Online (Sandbox Code Playgroud)

这样,静态资产就能成功提供.但它不是一个非常优雅的解决方案.

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

我真的不知道如何处理这个问题,以至于它让我重新考虑使用create-react-app,因为它迫使我以一种非常特殊的方式构建我的静态文件夹:没有办法我要改变应用程序从服务器请求静态内容的方式.

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

谢谢阅读 !

Jod*_*odo 53

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)
Run Code Online (Sandbox Code Playgroud)

这就是我最终的结果.所以基本上捕获所有路由,测试路径是否为file => send file => else发送index.html.这样你就可以从你希望的任何路线重新加载反应应用程序,它不会破坏.

  • 我正在使用此解决方案获取mime类型错误:-(`脚本具有不受支持的MIME类型('text/html')./ service-worker.js无法加载资源:net :: ERR_INSECURE_RESPONSE registerServiceWorker.js:71错误在服务工作者注册期间:DOMException:无法注册ServiceWorker:脚本具有不受支持的MIME类型('text/html'). (3认同)

pan*_*kaj 11

这里有一个可行的解决方案。有没有想过为什么我们需要两个单独的文件夹statictemplates. 为了隔离混乱,对吧?但是,它与生产版本的问题,因为它有两个一个文件夹statictemplates类型的文件和所有相关性链接这样。

build如果您同时考虑static和 ,则将提供该文件夹templates

使用这样的东西

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

Run Code Online (Sandbox Code Playgroud)

您的烧瓶应用程序将运行良好。

  • 这个答案救了我。所有其他人都有一些不适合我的设置的警告。 (2认同)
  • `static_url_path=''` 正是它对我有用的原因。 (2认同)

Luk*_*don 6

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

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


Run Code Online (Sandbox Code Playgroud)


Pra*_*yal 5

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

Run Code Online (Sandbox Code Playgroud)

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