我有一个带有API路径的烧瓶后端,可以通过使用create-react-app样板创建的React单页面应用程序访问。当使用create-react-app内置开发服务器时,我的Flask后端工作,没问题。
现在,我想从我的Flask服务器提供构建的(使用npm run build
)静态反应应用程序。构建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')
这样,静态资产就能成功投放。但它不是一个非常优雅的解决方案。
另一方面,我可以将其与内置的烧瓶静态实用程序结合使用。但我不明白如何配置它。
我真的不知道如何处理这个问题,以至于它让我重新考虑使用create-react-app,因为它迫使我以一种非常特殊的方式构建我的静态文件夹:我无法改变应用程序从服务器请求静态内容的方式。
总体而言:我的解决方案是否足够强大?有没有办法使用内置的烧瓶功能来提供这些资产?有没有更好的方法来使用create-react-app?任何输入都表示赞赏。如果需要,我可以提供更多信息。
感谢阅读!
答案 0 :(得分:44)
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)
这就是我最终的结果。因此,基本上捕获所有路线,测试路径是否为文件=&gt;发送文件=&gt;否则发送index.html。这样你就可以从你希望的任何路线重新加载反应应用程序,它不会破坏。
答案 1 :(得分:7)
一种可行的解决方案。
曾经想过为什么我们需要两个分别用于static
和templates
的文件夹。隔离混乱,对不对?
但是,这对于生产版本来说是个问题,因为它为static
和templates
类型的文件都有一个文件夹,并且所有依赖项都这样链接。
如果您同时考虑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")
烧瓶应用将正常运行。
答案 2 :(得分:4)
首先执行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')
不幸的是,我认为您无法使其与开发热重装一起使用。
答案 3 :(得分:1)
接受的答案对我不起作用。我用过
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
答案 4 :(得分:0)
我使用了一个只有一个路由/的flask服务器,它从Create react app(CRA)的build文件夹中读取index.html文件
from flask import Flask
app = Flask(__name__)
app.static_folder = '../build'
@app.route('/')
def index():
fref = open(r'../build/index.html')
html_text = fref.read()
fref.close()
return html_text
app.run()
这样设置我遇到了一个错误,静态文件由于路径不匹配而无法正确提供,所以我使用的解决方案是
{ "name":"应用名称", “版本”:””, “依赖项”:{} "homepage":"/static",....[其他键]}
Add **homepage** key parallel to the **dependencies** key in the package.json file
这个 homepage 属性将在 CRA 的构建过程中使用,用于代替 index.html 的 %PUBLIC_URL% 并附加到其他静态资产 URL 路径(您可以在构建过程后通过查看 index.html 代码进行验证)
构建过程完成后,运行flask服务器,我们可以看到第一次带有/的GET请求,index.html将被提供然后是请求 /static/static/js/[[filename]] 来自 HTML 文件的其他静态资产,一切正常