jQuery全盛期にフロントエンドエンジニアをやっていたんですが、JavaScriptにめっきり触れなくなって最近はPythonで小物を作っているという私がやってみた時の疑問です。
ディレクトリ構成はどうすれば良いの?
とりあえず分けておくのが良さそうなので、プロジェクトフォルダの下にfrontendとbackendを作りました。
- my_project
- frontend
- backend
プロジェクトフォルダの下にfrontendという名前でreactのアプリを作成します。
npx create-react-app frontend
バックエンド側はbackendフォルダの下に…
gitのリポジトリは分けたほうが良いの?
Render.comを使いたくて、リポジトリは2つ必要?と思いましたが、一つのリポジトリで問題ありませんでした。
フロントエンド
- name:my_project
- TYPE:Static Site
- Root Directory:frontend
バックエンド
- name:my_project-backend
- TYPE:Web Service
- Root Directory:backend
という感じで2つのサイトを登録してRoot Directoryにそれぞれのディレクトリを指定することで、GitHubの一つのリポジトリを参照させることができました。
ポート問題
Flaskのデフォルトポートは5000番ですが、MacのAirPlay等の別サービスが既に使用していると、OSError: [Errno 98] Address already in use
のようなエラーが発生します。Flaskで使用するポートは下記のように指定できます。
if __name__ == '__main__':
app.run(debug=True, host='localhost', port=8000)
いまどきの非同期通信はどうやって書くの?
fetchを使います。具体的な書き方は後述。
Fetch_API
CORS
CORSの設定なしでフロントエンドからバックエンドにアクセスしようとすると、下記のようなエラーが表示されてしまいます。
Access to fetch at 'http://localhost:8000/' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
CORSは無闇に別のオリジンからの要求を受け入れないようにするため、アクセスを許可しても良いオリジンを制限するものです。
pip install Flask-Cors
でインストールし、制限なしでとりあえず試すだけの場合は、
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
としてからPythonのコードを書いていきます。
参考
Flask-CORS
フロントエンド側は、先ほどのfetchで投げる際に、mode: "cors"
を指定します。(下記参照)
データの受け渡し部分はどうやって書くの?
やっとここまで来ました。
const onClickHandler = async () => {
const response = await fetch(URL, {
mode: "cors",
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({name: name}) // 1 フロントエンドから送信するデータ
})
const json = await response.json() // 3 バックエンドから受信したデータ
console.log(json["greeting"])
}
from flask import Flask, request
@app.route('/', methods=['POST'])
def index():
data = request.json.get('name') # 2 フロントエンドから受信したデータ
return {"greeting": "Hello! {}".format(name)}
以上です
Reactの勉強をするのが目的だったのですが、ここまで来るだけで大変でした。
引き続き頑張ります。