Python 使用 Flask 为使用 create-react-app 创建的前端提供服务
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/44209978/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Serving a front end created with create-react-app with Flask
提问by Theo
I have a Flask back-end with API routes which are accessed by a React single page application created using create-react-app. When using the create-react-app dev server, my Flask back end works.
我有一个带有 API 路由的 Flask 后端,这些路由由使用 create-react-app 创建的 React 单页应用程序访问。使用 create-react-app 开发服务器时,我的 Flask 后端工作正常。
I would like to serve the built (using npm run build
) static React app from my Flask server. Building the React app leads to the following directory structure:
我想npm run build
从我的 Flask 服务器提供构建(使用)静态 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]
By [crypto]
, I mean the randomly generated strings generated at build time.
通过[crypto]
,我的意思是在构建时所产生的随机生成的字符串。
Having received the index.html
file, the browser then makes the following requests:
收到index.html
文件后,浏览器会发出以下请求:
- GET /static/css/main.[crypto].css
- GET /static/css/main.[crypto].css
- GET /service-worker.js
How should I serve these files? I came up with this:
我应该如何提供这些文件?我想出了这个:
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')
This way, the static assets are successfully served.
这样,静态资产就成功服务了。
On the other hand, I could incorporate this with the built-in Flask static utilities. But I do not understand how to configure this.
另一方面,我可以将它与内置的 Flask 静态实用程序结合起来。但我不明白如何配置它。
Is my solution robust enough? Is there a way to use built-in Flask features to serve these assets? Is there a better way to use create-react-app?
我的解决方案足够健壮吗?有没有办法使用内置的 Flask 功能来服务这些资产?有没有更好的方法来使用 create-react-app?
回答by Jodo
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)
Thats what I ended up with. So bascially catch all routes, test if the path is a file => send file => else send the index.html. That way you can reload the react app from any route you wish and it does not break.
这就是我的结局。所以基本上捕获所有路由,测试路径是否为文件 => 发送文件 => 否则发送 index.html。这样你就可以从你想要的任何路线重新加载反应应用程序,它不会中断。
回答by Pranay Aryal
First do npm run build
to build the static production files as mentioned by you above
首先做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')
Unfortunately, I don't think you can get it work with the development hot-reload.
不幸的是,我认为您无法通过开发热重载来实现它。
回答by Lukasz Madon
The accepted answer does not work for me. I have used
接受的答案对我不起作用。我用过了
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
回答by pankaj
A working solution here.
Ever thought why we need two separate folders for static
and templates
. To segregate the mess, right?
But, it's a problem with the production build since it has one folder for both static
and templates
type of files and all dependencies are linked like that.
这里有一个可行的解决方案。有没有想过为什么我们需要两个单独的文件夹static
和templates
. 为了隔离混乱,对吧?但是,它与生产版本的问题,因为它有两个一个文件夹static
和templates
类型的文件和所有相关性链接这样。
The build
folder will be served if you consider it both static
and templates
.
build
如果您同时考虑static
和 ,则将提供该文件夹templates
。
Use something like this
使用这样的东西
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")
Your flask app will run fine.
您的烧瓶应用程序将运行良好。