【完全版】React + FastAPIで開発するモダンなwebアプリ
はじめに
フロントエンドはリッチに作りたい!だけどバックエンドはFirebaseだけじゃなくてpythonでも書きたい...
そんな悩みを一度は抱いたことがあるのではないでしょうか?
今日はそんな要望に答えるべく、ゼロから始めるReact✕FastAPIと題しまして、フロントエンドはReact、API側はpythonで作ってリッチなwebアプリを作っていきましょう。
なぜReact?
Reactは、Javascriptのフレームワークの一つです。同種のフレームワークとして、Vue.jsやAngular.jsが挙げられますが、Googleでの検索数も、githubの利用者数もReactが一番多く、注目度は高い言えます。webのフロントエンドを触る上で、是非習得したいフレームワークと言えると思います。
なぜFastAPI?
今回は、APIをPythonのフレームワーク、FastAPIで作ることにします。実はPythonにはDjangoやFlaskなどの一般的によく使用されるフレームワークが存在しているので、
なぜFastAPI?
と思われた方もいるのではないでしょうか。確かに、DjangoやFlaskを用いてフルスタックにwebアプリを構築する方法や、それらのフレームワークのAPIモードを用いてAPIだけを作成するやり方もあります。
しかし、これらのフレームワークは最初からAPIを作ることを想定して設計されたフレームワークではなく、どうしてもAPIを作る上で必要ない部分の機能が数多くあります。
その点、FastAPIはPythonでAPIを作ることを前提に設計されたフレームワークで、FastAPIにしかない機能が多くあります。(有名なものとしては型チェックや、APIリファレンスの自動生成などがあります)
現在のWebアプリ開発では、大規模なフレームワークを用いてフルスタックに開発するというよりも、フロントエンドとバックエンドの処理を別々に分けて開発する方が主流になりつつあります。フロントエンドはリッチなReact、APIはFastAPIを用いて開発することで、モダンなwebアプリ開発ができると思います。
また、APIを作る言語にPythonを選択することで、AIを利用したアプリを作りやすいというメリットもあります。(pythonはAI回這うtで一番といっていいほどよく使用される言語です)
始め方
フロントエンド(React)
1. Reactの原型を作る
まずは、Reactのスターターを利用し、テンプレートを自動で生成します。今回は、詳しいコマンドの説明は割愛します。
$ npx create-react-app undou-front
$ cd undou-front
ここでは、名前はundou-front
としました。みなさんの好きな名前をつけてください。
2. サーバーを起動
実は、1番のコマンドをうっただけで、デフォルトのReactアプリが自動で生成されており、ローカルのサーバーを起動することができます。早速起動してみましょう。
$ yarn start
yarnではなくnpmを用いたい方は、
npm start
と打ってください。
サーバーが起動できたら、http://localhost:3000/
にアクセスしてみましょう。デフォルトで画面が開かれるかもしれません。
このような画面が出力されれば成功です。
デフォルトの画面 |
3. APIを利用するための便利なライブラリをインストール
Reactでは、便利なライブラリをインストールすることで、様々な機能を簡単に実装することができます。
今回は、API通信を簡単に実装できる、axios
というライブラリをインストールします。
$ yarn add axios
npmを使いたい方は、
npm install axios
と打ってください。
4. デフォルトの画面を削除
create-react-app
を実行すると、デフォルトの画面が自動で生成されるのですが、今はFastAPIとの通信を実装したいので、シンプルにするために削除します。
src
ディレクトリの中の、App.js
をApp.jsx
に変更します。jsx
というのは、React特有の拡張子です。
App.jsx
はデフォルトでこのようになっていると思います。
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
いらない部分を消します。そうすると、以下のようにしてくだいさい。
App.jsx
import React from "react";
function App() {
return (
<div>
<div>ここに処理を書いていきます</div>
</div>
);
}
export default App;
ローカルサーバーを起動(yarn start
)し、http://localhost:3000/
を表示してみましょう。
こんな画面が表示されたらOKです(上の黒い棒は気にしないでください)。
これで準備はOKです。後ほどaxios
を利用して、API通信をしていきます。
API(FastAPI)
1. ディレクトリ作成&pythonの仮想環境構築
$ mkdir undou-back
$ cd undou-back
pythonの仮想環境は、venvと呼ばれます。pythonのバージョンは同じですが、ライブラリの構成を環境ごとにわけることができるため、便利です。
$ python -m venv venv
これで仮想環境を構築します。
次に、仮想環境に入ります。
シェルにFishを使っている方は、
$ . venv/bin/activate.fish
と打ってください。
Zshやbashを使っている方は、
$ . venv/bin/activate
と打ってください。おそらくうまくいくと思います。
2. 必要なライブラリをインストール
FastAPIを使う上で必要なライブラリは2つあります。
fastapi
uvicorn
の2つです。fastapi
はFastAPI本体で、uvicornはローカルで動くサーバーです。この2つのライブラリがないと動作しないので、忘れずにinstallしましょう。
$ pip install fastapi uvicorn
3. 基本的なAPIの作成
今回は、基本的なAPIの作成をします。
main.py
を作りましょう。
$ touch main.py
main.py
が作成できましたら、次のように中身を書いてみてください。
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
origins = [
"http://localhost:3000",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/")
def Hello():
return {"Hello":"World!"}
簡単にコード解説をします。詳しい説明は、わかりやすい公式のチュートリアルがあるので、そちらを参照してみてください。
from fastapi import FastAPI
app = FastAPI()
この2行は、決り文句でして、はじめにfastapiからFastAPIを読み込み、クラスをインスタンス化してappという変数に代入します。あまり深く考えずに、覚えていいと思います。
from fastapi.middleware.cors import CORSMiddleware
origins = [
"http://localhost:3000",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
このコードは、主にセキュリティ面のコードです。Reactのアプリケーションと通信する際には、必要になります。
最初にfastapiからCORSMiddleware
を読み込んだあとに、URL別にアクセスできる権限を付与しています。
origins = []
の[]
の中に、通信するreactなどのアプリのURLを記載しましょう。最初はlocalとの通信をしたいので、http://localhost:3000
しか登録していませんが、後ほどフロントエンドのアプリをサーバーにデプロイした際には、URLを増やすことになると思います。
@app.get("/")
def Hello():
return {"Hello":"World!"}
最後に、このコードについて説明してきます。もし、Flaskを使用したことがある方は、見覚えがあるかもしれません。FastAPIはFlaskとだいぶ似ています。
@app.get("/")
このコードは、/
というURLにGetリクエスト来たら、という意味です。/
はデフォルトのURLです。
Getリクエストは、webのリクエストの一つで、主にデータを取得したいときにクライアントから送られます。この場合のクライアントは、フロントエンドのアプリです。
def Hello():
return {"Hello":"World!"}
ここでは、{"Hello":"World!"}
というjsonを返すように設定しています。このように、FastAPIでは、returnにjsonを書くだけで、json形式でレスポンスを送る事ができます。
4. ローカルサーバーを起動
では、ローカルサーバーを起動しましょう。当然ですが、サーバーを起動しないと、APIは作動しません。ここで、最初にインストールしたuvicorn
を使用します。
下記のコマンドを打ってください。
$ uvicorn main:app --reload
--reload
オプションをつけることで、コードを更新すると自動でサーバー側も更新してくれます。
それでは、http://127.0.0.1:8000/
にアクセスしてみましょう。
こんな画面が表示されたら成功です。 |
5. FastAPIの便利機能
これは付録みたいなものですが、FastAPIには便利な機能があるので紹介したいと思います。
サーバーを起動した状態で、http://127.0.0.1:8000/docs
にアクセスしてみましょう。
FastAPIが自動で生成 |
このように、FastAPI側が自動でAPIのリファレンスを作成してくれます。便利ですよね!
これでAPI側の処理は完成しました。あとは、フロントエンド側(React)でAPIを呼び出して見ましょう。
ReactからFastAPIを呼び出す
では、ReactからAPIを呼び出して見ましょう。
APIを呼び出すには、先程インストールしたaxiosを使います。
App.jsxを以下のように編集しましょう。
import React from "react";
import axios from "axios";
function App() {
const [data, setData] = React.useState();
const url = "http://127.0.0.1:8000";
const GetData = () => {
axios.get(url).then((res) => {
setData(res.data);
});
};
return (
<div>
<div>ここに処理を書いていきます</div>
{data ? <div>{data.Hello}</div> : <button onClick={GetData}>データを取得</button>}
</div>
);
}
export default App;
簡単にコードの説明をしていきます。
import axios from "axios";
ここで、axiosを読み込んでいます。
const [data, setData] = React.useState();
ReactのuseState()
を使用しています。
useState()って何?という方は、Reactの公式チュートリアルを参考にしてみてください。
axios.get(url).then((res) => {
setData(res.data);
})
axiosを利用して、urlにgetリクエストを送っています。今回は、uvicorn main:app --reload
で立ち上げたFastAPIにリクエストを送るため、http://localhost:8080
をurlに定数として代入しています。
thenって何?という方は、
JS Promise
と検索してみるとわかりやすい記事がたくさん有ります。
setData(res.data);
この部分で、stateであるdataを更新しています。この時点ではじめてdataに値が入ります。
どんな値が入るか考えてみましょう。
dataには、以下のようなjson形式のデータが入ります。
{"Hello":"World!"}
これは、FastAPIでこのようなレスポンスを返すように設定したからです。
このJson形式のデータは、"Hello"がキーで、"World!"が値と見ることができます。Javascriptでは、.
のあとにキー名を指定することで、そのキーのバリューを取得する事ができます。(Javascriptのオブジェクトと似ています)
<div>
<div>ここに処理を書いていきます</div>
{data ? <div>{data.Hello}</div> : <button onClick={GetData}>データを取得</button>}
</div>
ここが、実際にwebページに表示される部分です。
{data ? <div>{data.Hello}</div> : <button onClick={GetData}>データを取得</button>}
このコードは、三項演算子と呼ばれる記法を用いています。
{if文のような条件式 ? trueだった場合の処理 : falseだった場合の処理}
のように書きます。今回は、data
が存在する場合は、data.Hello
を表示し、ない場合は、データを取得するボタンを表示します。
では、ブラウザで見てみましょう。
yarn start
を打って、http://localhost:3000
を開きます。
フロントエンドのアプリを起動する際に、FastAPIも起動することを
忘れないようにしましょう
最初はこんな画面が表示されると思います。
では、データを取得ボタンをクリックしてみましょう。
このように、データを取得ボタンがWorld!
という文字に変わったら成功です!
本番環境にデプロイしてみよう
これまでの開発は、すべてローカルと呼ばれるいわゆる自分のパソコンの中だけで実装してきました。なので、あなた以外の人はあなたのアプリを操作したり開いたりすることができません。
あなた以外の人たちがアクセスできるようにするには、ローカルではなくサーバー上でアプリを動かす必要があります。
ですので、これからサーバー上にwebアプリを置きたいと思います。サーバーにローカルで開発したアプリを置くことを、デプロイといいます。
サーバーにデプロイするためには、当然サーバーが必要になります。しかし、自分でサーバーを持ってるよ、という方は少ないのでは無いでしょうか?
サーバーは高価なものなので、実際に購入しようとすると何百万~という値段がします。自前でサーバーを用意することを、オンプレミスでの開発といったりします。
高価なので、個人開発ではクラウドのサーバーを利用することが一般的です。
今回は、無料でクラウドのサーバーが使えるサービス、Herokuを用いてFastAPIをデプロイし、フロントエンドは無料で使えるVercelというサービスを用いてデプロイしたいと思います。
FastAPIをデプロイ
まずはじめに、FastAPIをデプロイしていきます。
Herokuの登録がまだの方は、アカウント登録しましょう。アプリの数が5個までのうちは無料なので、安心して下さい。
次に、Herokuにローカルのパソコンの環境からデプロイするために、2つのツールを導入します。
- Git
- Heroku CLI
Git
は、世界中で使われているコードのバージョン管理ツールで、アプリケーション開発をする上では必須になります。
Heroku CLI
は、Herokuをコマンドで操作できるツールです。
それでは、2つのツールをインストールします。
Git
まずは、ターミナルもしくはコマンドプロンプトを開いて、
git --version
と打ってみましょう。
git version 2.32.0
のように、git version ~
と出たら、Git
がパソコンにインストールされています。次に進みましょう。
それ以外の出力が表示された方は、Git
のインストールが住んでいないので、Gitをインストールしていきます。
下記の記事が非常に参考になります。
- Mac => gitのインストール方法(mac)
- Windows => gitのインストール方法(windows)
Heroku CLI
Heroku CLIのインストール方法は、公式が参考になります。
Macの方は、以下のコマンドをターミナルに打ち込みます。
brew tap heroku/brew && brew install heroku
Homebrewがはいっていることが前提になります。
Windowsの方は、先程の公式ページを開いて、公式ダウンローダーからインストールします。
デプロイ
では、FastAPIのコマンドを開いて、デプロイしていきます。
Herokuでは、mainのコードに加えて、以下のファイルが必須になります
requirements.txt
Procfile
requirements.txt
は、pip
でインストールしたpythonのライブラリを記載するファイルです。デプロイする際に、heroku側がこのファイルを見てライブラリをインストールし直します。
Procfile
は、herokuにデプロイしたあとに、サーバーを動かすコマンドを書くファイルです。ローカルでは、下記のコマンドを打ちましたが、
uvicorn main:app --reload
heroku側では、少し違ったコマンドを指定する必要があります。
uvicorn
ではなく、gunicorn
というライブラリを使用してサーバーを起動します。
gunicorn
はpythonのライブラリとしてimportします。
では、簡単に流れを説明します。
-
gunicorn
をpip
でインストール -
Procfile
を記述 -
requirements.txt
を作成 - Gitでプロジェクトを管理
- Heroku CLIを用いてHerokuにデプロイ
順番に解説します。
gunicorn
をpip
でインストール
1. まずは、gunicorn
をインストールします。
下記のコマンドを打ってください。
pip install gunicorn
これで、インストールすることができました。
Procfile
を記述
2. 次に、Procfile
を記述します。Procfile
には、Heroku側で実行するサーバーを起動するためのコマンドを打つのでしたね。
プロジェクトの直下の場所に(main.py
と同じ階層です)、Procfile
を作成します。拡張子はないので注意してください。中身を記述します。gunicorn
を用いてサーバーを起動するコマンドです。特に覚える必要はないと思います。
Procfile
web: gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app
これで大丈夫です。
requirements.txt
を作成
3. 次に、requirements.txt
を作成しますHeroku側がPythonのライブラリをインストールできるように、pip
でインストールしたライブラリを記載します。手動で書き込んでもいいのですが、pip
には便利なコマンドがあるので、これをターミナルに打ち込んでください。
requirements.txt
を作成する必要はありません。このコマンドを打つだけで自動で作成されます。
pip freeze > requirements.txt
これで、requirements.txt
が自動で作成されました。中身を見てみましょう。
requirements.txt
anyio==3.6.1
asgiref==3.5.2
click==8.1.3
fastapi==0.78.0
gunicorn==20.1.0
h11==0.13.0
idna==3.3
pydantic==1.9.1
sniffio==1.2.0
starlette==0.19.1
typing_extensions==4.2.0
uvicorn==0.17.6
このように、pip
を用いてインストールしたライブラリの一覧と、そのバージョンを自動で書き込むことができます。
これでrequirements.txt
は完成です。
4. Gitでプロジェクトを管理
次は、Gitを用いてプロジェクトの管理をしましょう。GitはHerokuにデプロイする上でも必要ですが、後にVercelにデプロイする際にも必要になってきます(VercelにデプロイするときにはGithubが必要なので)。
**Gitはどの言語で何をする上でも必ず必須になる便利なツールです。**一度基本的なコマンドを練習してある程度使いこなせるようになっておくのがベストです。今回は、Gitの講座ではないので、コマンドを逐一説明することはしません(今後Gitの講座もやろうと考えています)。
では、プロジェクトのターミナルで、以下のコマンドを上から順番に打ってください。
git init
git add .
git commit -m "initial commit"
この3つのコマンドを打ち終えたら、Gitの処理は終了です。
次は、いよいよ最後です。Herokuにデプロイしていきましょう。
5. Heroku CLIを用いてHerokuにデプロイ
最後に、Heroku CLIを用いてHerokuにデプロイしましょう。はじめての方は、Herokuにログインする必要があるので、ターミナルで以下のコマンドを打ちましょう。
heroku login
自動でブラウザが立ち上がると思うので、支持にしたがってログインしましょう。
すでにHeorku CLIを使ったことがある方は、このステップは飛ばして大丈夫です。
では、Herokuのアプリをコマンドから作成します。
heroku create
と打ってください。
そうすると、こんな出力がされると思います。
Creating app... done, epoita-itjei-29832
https://epoita-itjei-29832.heroku.app.com/ | https://git.heroku.com/epoita-itjei-29832.git
このような画面が出たらherokuで新しいアプリを作ることに成功しました。では、実際にこのherokuのアプリにローカルのアプリ(FastAPIで作成したAPI)をデプロイしましょう。
下記のコマンドを打ちましょう。
git push heroku master
このコマンドを打つと、自動でherokuのデプロイが始まります。長い長い出力の最後に、このような出力が表示されたら成功です。
remote: Verifying deploy... done.
To https://git.heroku.com/epoita-itjei-29832.git
592et3...95et74s master -> master
これで、ローカルのFastAPIのアプリを、Herokuにデプロイすることができました!
Reactアプリをデプロイ
Reactアプリは、Vercelという便利なサービスにデプロイします。Vercelは無料で使えるのでとてもおすすめです。
Githubと連携するのが一番効率的なので、Githubにリポジトリを作成し、pushします。
【手順】
git remote -v githubのレポジトリのURL
git push origin master
pushし終えたあとに、VercelでNew Project
を押します。
Import Git Repository
から先程作成したリポジトリをimportします。importしたあとに、deploy
を押すとデプロイが完了します。
Vercelを使用すると、なんとこれだけでデプロイが完了します!
あとは、Vercelでデプロイしたプロジェクトを開き、Visit
をクリックします。
そうすると、ローカルではなくパブリックなURLでwebアプリが表示されるのではないでしょうか?
これで、Reactアプリのデプロイは完了です!
注意
FastAPI、React共にデプロイできたと思います。しかし、Vercelからreactのアプリを起動し、データを取得
ボタンを押しても何も起こらないと思います。それは、URLが変わってしまっているからです。
ReactアプリのApp.jsx
を開いてください。
import React from "react";
import axios from "axios";
function App() {
const [data, setData] = React.useState();
const url = "http://127.0.0.1:8000";
const GetData = () => {
axios.get(url).then((res) => {
setData(res.data);
});
};
return (
<div>
<div>ここに処理を書いていきます</div>
{data ? <div>{data.Hello}</div> : <button onClick={GetData}>データを取得</button>}
</div>
);
}
export default App;
URLが変わっているため、
const url = "http://127.0.0.1:8000"
を変更する必要があります。HerokuのURLを参照して、各自変えましょう。
そして、FastAPI側でもURLを変える必要があります。
main.app
を開いてください。
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
origins = [
"http://localhost:3001",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/")
def Hello():
return {"Hello":"World!"}
ReactアプリのURLが変わっているため、
origins = [
"http://localhost:3001",
]
ここの、originsのリストに、VercelのURLを追加する必要があります。下記に、例を示します。
【例】
origins = [
"http://localhost:3001",
"https://test-app.vercel.com",
]
このように、URLが変わるとフロントエンドとAPI側の2つの箇所を変更する必要があります。
忘れがちになりやすいので、注意しましょう。
2箇所を無事に変更できたら、デプロイを更新しましょう。
Reactアプリの場合は、githubに変更をpushするだけで、Vercelが自動でデプロイを更新してくれます。便利ですよね!
FastAPIの場合は、Herokuにpushします。コマンドは以下のとおりです。
git push heroku master
これで、herokuもデプロイの更新が完了しました。
VercelでデプロイしたURLを開いてみましょう。
データを取得
ボタンを押したときに無事World!
とひょうじされていれば完成です!お疲れさまでした
終わりに
以上で、ReactとFastAPIを用いたモダンなwebアプリケーションを開発するための基礎を作り終えることができました。この流れをしっかり抑えたうえで、FastAPI側でAIを実装してみたり、ReactではなくNextJSを用いてみたりなど、応用を効かせてみると良いかもしれません。
それでは、おつかれ様でした!
Discussion
詳しい解説ありがとうございます。
ただ、WSL2+Ubuntuで実際に動かしてみたところ、エラーで通信できませんでした。
main.pyの
allow_origins=origins
を
allow_origins=["*"]
に変更することでエラーはなくなりました。