Vue.js(Vue3)とTypescriptで日記アプリを開発する。（②フロントエンド開発ver）

###### バックエンド開発verに続いて、フロントエンドを開発

バックエンドでの開発が一旦終了したので、今度はフロントエンドの開発を進めていきます。
構成としてはこのような感じです。

mori_pro/（プロジェクトのディレクトリ）
├── diary-api/       ← NestJS（APIサーバー）
└── diary-frontend/  ← Vue.js（フロント側）**★今回作成**

前回の記事までは、dairy-apiで作業をしていたので、今回から新しくdairy-frontendというプロジェクトを作成し、そこで作業をしていきます。

## Vueアプリ開発
<br>
#### STEP１：環境設定とプロジェクト作成
今回、Vue3 + TypeScript + Viteを使用して、フロントエンドを構築していきます。  
以下の手順で、環境構築を進めました。

##### ①プロジェクトの作成

```bash
$ pnpm create vue@latest
```
・Vue CLI（Command Line Interface） は、Vue.jsの公式ツールで、Vueアプリの作成や管理をコマンドで行うツール
・Vue3以降では Vite が推奨される。（Vue CLIはvue2時代の開発環境、Vue CLIでコマンドを書く場合は`$ vue create my-project`）
・Viteは「ビルドツール（Rollupでdistを作成）兼開発サーバー」（Vue CLIはwebpack）→どちらもモジュールバンドラ
・Webpackも、Webアプリをバンドル（ビルド）するためのツール（JSファイルをまとめたり）
・Rollupは、ESMに最適化されたバンドラー（ツリーシェイキング（不要なコード除去）で軽量）
<br>
→作成する中で、下記のような選択肢が出てきますので、それぞれ選択していきます。

---
###### 選択1: プロジェクト名（ディレクトリ名）

```
◇ Project name (target directory):
```
→ **「diary-frontend」** と入力。

---

###### 選択2: 使用する機能の選択

```
◇ Select features to include in your project: (↑/↓で選択、スペースで選択)
```

下記を選択。
- **TypeScript**：型安全な開発のため
- **Router (SPA development)**：ルーティングを利用するため（/homeとか/aboutとかのURL分け）
- **Pinia (state management)**：状態管理（ログインユーザ情報やカート情報の一元管理）
- **ESLint (error prevention)**：リンター。コード品質維持（let x == 1みたいな書き間違えを検出）
- **Prettier (code formatting)**：コードフォーマット整形（インデント、改行を統一）

・この選択はプラグイン。
・ちなみにLintという概念自体は、1978年にC言語向けに作られたツールが由来。

---

###### 選択3: Oxlintの導入（実験的）

```
◆ Install Oxlint for faster linting? (experimental)
```
→ **No** を選択。  
・Rust製の次世代高速Lintツール。
・ESLintよりも数倍速くLintをかけられるのがメリット
・ただしまだ実験的。
・安定性を優先し、標準のESLintで進める。

---
---

##### ②開発サーバの起動

ここまででプロジェクトが作成できたので、サーバの立ち上げに移っていきます。

---

###### githubと連携、ブランチの作成

その前に、githubと連携してpushできるように設定します。ブランチの設定もここで行います。

```bash
$ git init
$ git add -A
$ git commit -m "initial commit"
$ git checkout -b dev
$ git push -u origin dev
```

---

###### 依存パッケージのインストール〜サーバ起動
次に、先ほどのvueプロジェクトで作成した際に生成結果で出てきた指示通りに、コマンドを進めます。

```bush
$ cd diary-frontend
$ pnpm install
```
・package.json に書かれた依存パッケージをすべてインストール。
例）vue, vue-router, pinia, vite（開発サーバ）, eslint, prettier, typescript など
・これにより、**実際にコードを書いて動かすのに必要な「部品一式」** が node_modules に整います。

```bush
$ pnpm format
$ pnpm dev
```
・Prettierを使って、プロジェクト全体のコードを自動整形するコマンド

```bush
$ pnpm dev
```
・Viteの開発サーバーを起動するコマンド
・devはホットリロード用。
・本番環境の場合は`$ pnpm build`。生成されたdist/（distribution（配布物））をデプロイ。


ブラウザで `http://localhost:5173` にアクセスすると、**「You did it!」画面**が表示され、無事開発環境が整ったことが確認できます。

---

###### Axiosの導入

APIとの通信に使用するため、Axiosを追加します。

```bash
$ pnpm add axios
```
・バックエンドAPI（今回はNestJS）との通信を行うため
・JSには標準APIで、Fetch APIが標準装備されているが、エラーハンドリングやリクエストキャンセルなどが弱め。


これで**Vue3 + Vite + TypeScript + Pinia**による**フロントエンドの土台が完成**しました！  
次は、Axiosを使ってバックエンドAPI（NestJS）との通信処理を進めていきます🚀

<br><br>
#### STEP２：NestJS APIとの接続

##### ①APIエンドポイントの設定

プロジェクト直下に、.envをファイルを作成し、下記記述。

diary-frontend/
├── **.env**
├── package.json
├── src/
├── vite.config.ts
└── ...


```.env
VITE_API_URL=http://localhost:3000
```
・VITE_API_URLは、Vueアプリ側から見たNestJSのAPIサーバーのURL
・「VITE_ 」から始まる名前にすることで、Viteが自動的にビルド時に注入可能。

##### ②axios.tsを作成し、APIを呼び出す。

[axios.tsの作成]
src/配下に、utilsディレクトリを作成し、その直下にaxios.tsファイルを作成する。

diary-frontend/
├── src/
│   ├── assets/
│   ├── components/
│   ├── router/
│   ├── stores/
│   ├── views/
│   ├── utils/
│   │    └── **axios.ts**
│   ├── main.ts
│   └── ...
└── .env

```axios.ts
import axios from 'axios';

const apiClient = axios.create({
  baseURL: import.meta.env.VITE_API_URL,
  headers: {
    'Content-Type': 'application/json',
  },
});

export default apiClient;
```

[コンポーネントから使う]

```HomeView.vue
import apiClient from '@/utils/axios';

// API呼び出し例
const response = await apiClient.get('/diary-entry');
```

##### ③画面開発

・APIへ送信する処理を、フロント側で作っていきます。
```HomeView.vue
<template>
  <div>
    <h2>日記の登録</h2>
    <input v-model="key" placeholder="Key" />
    <input v-model="value" placeholder="Value" />
    <button @click="submitEntry">送信</button>

    <h2>日記一覧</h2>
    <ul>
      <li v-for="entry in entries" :key="entry.id">
        {{ entry.key }}: {{ entry.value }}
      </li>
    </ul>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue';
import apiClient from '@/utils/axios';

const key = ref('');
const value = ref('');
const entries = ref([]);

// 送信（POST）
const submitEntry = async () => {
  try {
    await apiClient.post('/diary-entry', {
      key: key.value,
      value: value.value,
    });
    console.log('送信成功');
    await fetchEntries(); // 再取得
  } catch (error) {
    console.error('送信エラー:', error);
  }
};

// 取得（GET）
const fetchEntries = async () => {
  try {
    const response = await apiClient.get('/diary-entry');
    entries.value = response.data;
  } catch (error) {
    console.error('取得エラー:', error);
  }
};

// 初期表示時に取得
onMounted(fetchEntries);
</script>
```

それとフロントの邪魔な部分を削除（非表示）にします。
```src.App.vue
<template>
  <!-- <header>
    <img alt="Vue logo" class="logo" src="@/assets/logo.svg" width="125" height="125" />

    <div class="wrapper">
      <HelloWorld msg="You did it!" />

      <nav>
        <RouterLink to="/">Home</RouterLink>
        <RouterLink to="/about">About</RouterLink>
      </nav>
    </div>
  </header> -->

  <RouterView />
</template>
```
・このままkey(就寝時間), value(23:00)などを入力して送信すると、CORS関連のエラーが出るため、API側の修正をしていきます。

例）こんな感じのエラーが出ます。
`Access to XMLHttpRequest at 'http://localhost:3000/diary-entry' from origin 'http://localhost:5173' has been blocked by CORS policy...`

・NestJS側でCROS許可の対応
（dairy-frontendではなく、dairy-apiで作業する）
```main.ts
import { NestFactory } from '@nestjs/core'; // NestJSアプリを生成するための関数
import { AppModule } from './app.module'; // ルートモジュールがAppModuleにある

// bootstrap関数
async function bootstrap() {
  // AppModuleでアプリを作成
  const app = await NestFactory.create(AppModule);

  // ここで、CORSを有効化（フロント5173→APIサーバ3000、別オリジンでの通信を許可）
  app.enableCors();

  // PORT設定があればそれを使用、なければ3000を使用
  await app.listen(process.env.PORT ?? 3000);
}
// アプリ立ち上げ
bootstrap();
```
<br><br>
#### STEP３：画面で送信し、データが受け取れているか確認

##### ①下記のような見た目になっているので、keyとvalueに任意の値（就寝時間, 23:00）を入力し、送信btnを押下する。
![スクリーンショット 2025-05-26 15.39.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3478895/3b670ca4-b12e-407c-ace4-b932991f843e.png)

##### ②送信が成功していると、日記一覧にデータが表示され、Consoleでも送信成功が表示される。
![スクリーンショット 2025-05-26 15.42.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3478895/56b00d68-7ea7-4508-b298-547b85f06f4d.png)

![スクリーンショット 2025-05-26 15.42.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3478895/123004f2-2242-4948-a0bc-fb0a151ba277.png)
<br><br>
#### STEP4：SQLiteにデータがある確認

##### ①VS Codeを開き、拡張機能からSQLiteをインストール。
![スクリーンショット 2025-05-26 15.44.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3478895/3fada9d0-658f-494d-ba2c-457e706de42a.png)

##### ②APIサーバを再起動
```bash
$ pnpm run start
```
##### ③VS CodeでDBを表示
・command+shift+pでコマンドパレットを起動させ、SQLite: Open Databaseを検索し押下。db.sqliteを選択。
![スクリーンショット 2025-05-26 15.55.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3478895/41626eb0-f406-4144-bc85-b78a7a0e07b4.png)

・エクスプローラの最下部に「SQLITE EXPLORER」が表示されるので、クリック。db.sqliteもクリックすると、dairy_entryテーブルが表示されるので、二本指でクリックしshow tableを選択。
![スクリーンショット 2025-05-26 15.57.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3478895/c2f65bd1-7420-46d7-8b2d-7094c74a5d3d.png)

・すると、VS Code内でtableを確認することができます。
![スクリーンショット 2025-05-26 15.59.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3478895/ff7678f2-985d-476d-b843-0047486c10b1.png)

<br><br>
#### STEP5：データの流れのまとめ
ーーーーーーーーーーーーーーーーーーーーーーー
①フロントエンド：Vueアプリ
（src/views/HomeView.vue）
　→ 画面表示・送信ボタンでAPIを呼ぶ（axios）

②フロント → APIサーバーへリクエスト
　→ 送信先は .env の VITE_API_URL → http://localhost:3000

③NestJSサーバー：main.ts
　→ bootstrap() でアプリ起動
　→ AppModule が「どの機能（モジュール）を使うか」決める

④具体的なAPI処理
DiaryEntryController が受け取る
↓
DiaryEntryService でDB保存
↓
SQLite（db.sqlite）にデータ保存

⑤APIのレスポンスをVueが受け取る
　→ entries に反映（画面に表示！）
ーーーーーーーーーーーーーーーーーーーーーーー
※AppModule の役割
DB接続設定（TypeOrmModule）
　→ DiaryEntryModule（日記管理API）を読み込む

<br><br>
#### STEP６：CSSでスタイリング＋機能追加（必須項目、バリデーションなど）

色々細々実装をしました。
詳細については、githubをご確認ください。
[フロント]
https://github.com/Toma-0205/diary-frontend.git
[バック]
https://github.com/Toma-0205/diary-api.git
[参考]
https://gyazo.com/3eadd71a7393df34e8c27e52e3861323


<br><br>

ローカル環境での主な作業は、ここまでです。

次はDBを本番環境用に移行し、本番サーバにWEBアプリを公開します。