1. ホーム
  2. python

create-react-appで作成したフロントエンドをFlaskでサービスする

2023-09-06 10:10:12

質問

私は、create-react-appを使用して作成されたReactの単一ページアプリケーションによってアクセスされるAPIルートを持つFlaskのバックエンドを持っています。create-react-appの開発サーバーを使用する場合、私のFlaskバックエンドは動作します。

私はビルドされたものを提供したいと思います ( npm run build を使って)構築された静的なReactアプリを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]

によって [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内蔵の静的ユーティリティで取り込むこともできました。しかし、これをどのように設定するのかがわかりません。

私のソリューションは十分に堅牢ですか?これらの資産を提供するために、Flaskの組み込み機能を使用する方法はありますか?create-react-appを使用する良い方法はありますか?

どのように解決するのですか?

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アプリを再読み込みしても、壊れることはありません。