Skip to content

Commit 65e0304

Browse files
committed
フロントエンドとバックエンドの連携とデプロイの節を追加
1 parent cceb0dd commit 65e0304

File tree

1 file changed

+188
-0
lines changed

1 file changed

+188
-0
lines changed
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
---
2+
title: フロントエンドとバックエンドの連携とデプロイ
3+
---
4+
5+
## フロントエンドとバックエンドを連携する
6+
7+
Reactによって作成されたブラウザ上で動くアプリケーションと、Node.jsによって作成されたサーバー上で動くアプリケーションを接続する方法について学びましょう。
8+
9+
### 全体構成
10+
11+
フロントエンドとバックエンドの開発用サーバーをそれぞれ起動し、フロントエンドからバックエンドにFetch APIを用いてHTTPリクエストを送信します。
12+
13+
14+
15+
### バックエンドを準備する
16+
17+
まずは、バックエンドを作成しましょう。
18+
19+
[データーベースの節](/docs/web-servers/database/)で行ったように、次のコマンドを実行してExpressとPrismaの環境を用意します。
20+
21+
```shell
22+
$ npm init
23+
$ npm install express
24+
$ npx tsc --init
25+
$ npx prisma init
26+
```
27+
28+
さらに、次のパッケージをインストールして、TypeScriptの環境を用意します。
29+
30+
```shell
31+
npm install -D typescript @types/express
32+
```
33+
34+
また、CORSを設定する必要があるため、次のパッケージをインストールします。
35+
36+
```shell
37+
npm install cors @types/cors
38+
```
39+
40+
`main.mts`を次のように用意します。8行目以外は、[データベースの節](/docs/web-servers/database/)の内容と同じです。
41+
42+
フロントエンドとバックエンドが異なるため、CORSの設定を追加する必要があります。ここでは、フロントエンドの開発用サーバーのみからのアクセスのみを許すようにします。バックエンドのURLは開発環境と本番環境で異なるため、環境変数を使用して切り替えられるようにします。`.env`ファイルに`WEB_ORIGIN=http://localhost:5173`と書くことで、環境変数`WEB_ORIGIN`の値をViteの開発用サーバーのURLに設定します。Node.jsでは、`process.env`を使用することで環境変数にアクセスできるため、8行目のように`app.use(cors({ origin: process.env.WEB_ORIGIN }));`とすることで、`WEB_ORIGIN`に設定したURLからのアクセスのみを許可するようにしています。
43+
44+
```tsx showLineNumbers
45+
import express from "express";
46+
import cors from "cors";
47+
import { PrismaClient } from "./generated/prisma/index.js";
48+
49+
const app = express();
50+
const client = new PrismaClient();
51+
52+
app.use(cors({ origin: process.env.WEB_ORIGIN }));
53+
54+
app.use(express.json());
55+
56+
app.get("/messages", async (request, response) => {
57+
response.json(await client.message.findMany());
58+
});
59+
60+
app.post("/send", async (request, response) => {
61+
await client.message.create({ data: { content: request.body.content } });
62+
response.send();
63+
});
64+
65+
app.listen(3000);
66+
```
67+
68+
Prismaファイルは、[データベースの節](/docs/web-servers/database/)と同様に次のようにします。
69+
70+
```prisma
71+
// This is your Prisma schema file,
72+
// learn more about it in the docs: https://pris.ly/d/prisma-schema
73+
74+
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
75+
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
76+
77+
generator client {
78+
provider = "prisma-client-js"
79+
output = "../generated/prisma"
80+
}
81+
82+
datasource db {
83+
provider = "postgresql"
84+
url = env("DATABASE_URL")
85+
}
86+
87+
model Message {
88+
id Int @id @default(autoincrement())
89+
content String
90+
}
91+
```
92+
93+
`npx prisma db push`コマンドを実行することで、データベースにテーブルを作成するのを忘れないようにしましょう。
94+
95+
今までは、`tsc`コマンドでTypeScriptファイルをJavaScriptファイルにトランスパイルしてから`node`コマンドで実行していましたが、ここでは`tsx`コマンドを使用すると、TypeScriptファイルを直接実行することができ便利です。次のようにして`tsx`をインストールしてください。
96+
97+
```shell
98+
npm install tsx
99+
```
100+
101+
`package.json``scripts`プロパティに`"dev": "tsx main.mts"`を追加して、`npm run dev`でバックエンドの開発用サーバーを起動できるようにしましょう。
102+
103+
### フロントエンドから通信する
104+
105+
次に、Reactを用いたプロジェクトを作成して、`App.tsx`の中身を次のようにしてください。
106+
107+
データを送信するには、`fetch`関数を使用します。今までは、`fetch`関数の第一引数は`/messages`としていましたが、ここではバックエンドのURLを指定する必要があります。バックエンドのURLは開発環境と本番環境で異なるため、環境変数を使用して切り替えられるようにします。Viteでは、`VITE_`で始まる環境変数を`import.meta.env`から参照できるため、これを利用します。`.env`ファイルを作成し、その中は`VITE_API_ENDPOINT=http://localhost:3000`のように設定することで、環境変数`VITE_API_ENDPOINT`の値をバックエンドのURLに設定します。`App.tsx`では、`fetch`関数の第一引数を`${import.meta.env.VITE_API_ENDPOINT}/send`のようにすることで、環境変数からバックエンドのURLを取得しています。
108+
109+
データを取得する際にも、`fetch`関数を使用します。ただし、これはコンポーネント読み込み時に一度だけ実行したいため、`useEffect`フックを使用して実装します。
110+
111+
```tsx
112+
import { useEffect, useState } from "react";
113+
114+
const getMessagesApi = `${import.meta.env.VITE_API_ENDPOINT}/messages`;
115+
const postMessageApi = `${import.meta.env.VITE_API_ENDPOINT}/send`;
116+
117+
type Message = { id: number; content: string };
118+
119+
function App() {
120+
const [messages, setMessages] = useState<Message[]>([]);
121+
const [newMessageContent, setNewMessageContent] = useState("");
122+
123+
useEffect(() => {
124+
const timerId = setInterval(async () => {
125+
const response = await fetch(getMessagesApi);
126+
setMessages(await response.json());
127+
}, 1000 * 5);
128+
129+
// useEffectフックに指定した関数の戻り値に指定した関数はコンポーネントの破棄時に実行される
130+
return () => {
131+
clearInterval(timerId);
132+
};
133+
}, []);
134+
135+
return (
136+
<>
137+
<ul>
138+
{messages.map((message) => (
139+
<li key={message.id}>{message.content}</li>
140+
))}
141+
</ul>
142+
<input
143+
value={newMessageContent}
144+
onChange={(e) => {
145+
setNewMessageContent(e.target.value);
146+
}}
147+
/>
148+
<button
149+
type="button"
150+
onClick={async () => {
151+
await fetch(postMessageApi, {
152+
method: "POST",
153+
headers: { "Content-Type": "application/json" },
154+
body: JSON.stringify({ content: newMessageContent }),
155+
});
156+
}}
157+
>
158+
送信
159+
</button>
160+
</>
161+
);
162+
}
163+
164+
export default App;
165+
```
166+
167+
### 開発環境で動作を確認する
168+
169+
バックエンドでは、`npm run dev`でWebサーバーを起動します。
170+
171+
フロントエンドでは、`npm run dev`でViteの開発用サーバーを起動します。
172+
173+
これで、フロントエンドとバックエンドが接続されました。メッセージの送信と取得ができることを確認してください。
174+
175+
## デプロイする
176+
177+
### 本番ビルドを確認する
178+
179+
`outDir`オプションを`./dist`にしてトランスパイル結果が`/backend/dist`に入るようにしましょう。`allowJs`オプションを`true`にしてPrismaが生成したJavaScriptファイルをトランスパイル結果に含めるようにしましょう。`npm run build`コマンドと`npm start`コマンドを用意します。`npm run build``npm start`コマンドを実行し、ローカル環境でバックエンドが動作することを確認しましょう。
180+
181+
フロントエンドでも`npm run build`コマンドと`npm run preview`コマンドを実行し、ローカル環境でフロントエンドが動作することを確認しましょう。
182+
183+
実際に、メッセージの送信と取得ができることを確認してください。
184+
185+
### Renderにデプロイする
186+
187+
README通り
188+

0 commit comments

Comments
 (0)