1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

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

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

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

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

Vueアプリ開発


#### STEP1:環境設定とプロジェクト作成 今回、Vue3 + TypeScript + Viteを使用して、フロントエンドを構築していきます。 以下の手順で、環境構築を進めました。
①プロジェクトの作成
$ 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に最適化されたバンドラー(ツリーシェイキング(不要なコード除去)で軽量)


→作成する中で、下記のような選択肢が出てきますので、それぞれ選択していきます。


選択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できるように設定します。ブランチの設定もここで行います。

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

依存パッケージのインストール〜サーバ起動

次に、先ほどのvueプロジェクトで作成した際に生成結果で出てきた指示通りに、コマンドを進めます。

$ cd diary-frontend
$ pnpm install

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

$ pnpm format
$ pnpm dev

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

$ pnpm dev

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

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


Axiosの導入

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

$ pnpm add axios

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

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



STEP2: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();



STEP3:画面で送信し、データが受け取れているか確認

①下記のような見た目になっているので、keyとvalueに任意の値(就寝時間, 23:00)を入力し、送信btnを押下する。

スクリーンショット 2025-05-26 15.39.50.png

②送信が成功していると、日記一覧にデータが表示され、Consoleでも送信成功が表示される。

スクリーンショット 2025-05-26 15.42.01.png

スクリーンショット 2025-05-26 15.42.53.png


STEP4:SQLiteにデータがある確認

①VS Codeを開き、拡張機能からSQLiteをインストール。

スクリーンショット 2025-05-26 15.44.14.png

②APIサーバを再起動
$ pnpm run start
③VS CodeでDBを表示

・command+shift+pでコマンドパレットを起動させ、SQLite: Open Databaseを検索し押下。db.sqliteを選択。
スクリーンショット 2025-05-26 15.55.04.png

・エクスプローラの最下部に「SQLITE EXPLORER」が表示されるので、クリック。db.sqliteもクリックすると、dairy_entryテーブルが表示されるので、二本指でクリックしshow tableを選択。
スクリーンショット 2025-05-26 15.57.56.png

・すると、VS Code内でtableを確認することができます。
スクリーンショット 2025-05-26 15.59.27.png



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)を読み込む



STEP6:CSSでスタイリング+機能追加(必須項目、バリデーションなど)

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



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

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

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?