Viteを使ったVue.jsの一般的なファイル構造について

# はじめに
以下はViteを使ったVue.jsプロジェクトの一般的なファイル構造とその役割についてのメモになります

## Vue.js（ビュー・ジェイエス）とは
ウェブサイトやアプリケーションの見た目（ユーザーインターフェース）を作るためのツールです。

- ウェブページの動きを作ったり、情報を表示するために使います。たとえば、ボタンをクリックしたときに何かが起こる、フォームに入力したデータを表示する、などの機能を簡単に作ることができます。
- Vue.jsを使うと、ページの一部だけを更新することができます。これにより、ページ全体を再読み込みせずに、スムーズな操作が可能です。

## Vite（ヴィート） とは
Vue.jsやその他のツールを使うときに便利な「開発サーバー」と「ビルドツール」を提供するツールです。

- コードを素早く反映させたり、最終的にウェブサイトを作るための準備をします。開発中に変更をすぐにブラウザで確認できるようにしてくれます。
- Viteを使うと、コードを書いたときにすぐに結果を確認できるので、作業がスムーズに進みます。また、最終的なファイルを軽くして、パフォーマンスを向上させるために、いくつかの最適化も行います。

## Vue.js と Vite の関係
`Vue.js`
ウェブページやアプリケーションの見た目を作るためのツール。

`Vite`
Vue.jsのようなツールを使うときに、開発を助けるためのツール。

### 例
`Vue.jsの場合` 
ウェブページに「こんにちは、世界！」と表示させる機能を作る。
`Vite` 
「こんにちは、世界！」を早くブラウザで確認できるようにして、最終的に良いパフォーマンスで表示できるようにする。

## Viteにアクセスがあった場合の動き

### 1. ブラウザからのリクエスト
ユーザーがウェブサイトにアクセスすると、ブラウザが「このウェブサイトを表示してほしい」とViteにリクエストを送ります。

### 2. `index.html`の読み込み
Viteはプロジェクトのルートにある`index.html`というファイルを探します。これはウェブサイトの「トップページ」にあたるファイルです。

### 3. `index.html`の中身を表示
`index.html`の中には、ウェブページに表示するための「基本的な設計図」が書かれています。この中で、どの「部品」（Vueコンポーネントなど）を使うかが指定されています。

### 4. `main.js`の読み込み
`index.html`には、`main.js`というファイルが含まれていることが多いです。`main.js`は、ページに表示する「部品」や「内容」をまとめて管理する役割を持っています。
例えば、`main.js`では、Vueの「アプリ」や「コンポーネント」をブラウザに表示させるための指示が書かれています。

### 5. Vueコンポーネントの表示
`main.js`の指示に従って、Vueの「部品」（Vueコンポーネント）がページに組み込まれます。これにより、ユーザーがウェブページで見ることができる「内容」が作られます。

### 6. ブラウザに表示
最終的に、ブラウザが`index.html`と`main.js`の指示に従って、ユーザーにウェブページを表示します。
 

## ファイル構造図

```php

プロジェクトのルートディレクトリ
  ├── index.html
  ├── package-lock.json
  ├── package.json
  ├── public
  │ └── favicon.ico
  └── src
  ├── App.vue
  ├── assets
  │ └── logo.png
  ├── components
  │ └── HelloWorld.vue
  ├── index.css
  └── main.js
```

## Vue.jsの基本的な使い方(概要）

### ① index.html 
このファイルは、ウェブブラウザに表示されるページの基本を設定します。Vue.jsでは、ウェブブラウザに最初に表示されるページであり、index.htmlを基に他の「ページ」や「部分」は、コンポーネント（部品）やルーティングを使って管理します。

```index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>ApplyMaster Frontend</title>
</head>
<body>
  <div id="app"></div>
  <script type="module" src="/src/main.js"></script>
</body>
</html>

```
### ② main.js
どのコンポーネントをページに表示するかを決める役割を持ち、ブラウザはその指示に従って、画面に実際に表示する内容を作ります。

```main.js
import { createApp } from 'vue';  // Vueをインポート
import App from './App.vue';      // App.vueというファイルをインポート

// Vueアプリを作成し、Appコンポーネントを画面に表示
createApp(App).mount('#app');
```

### ③ App.vue
アプリケーションを構築するメインの部品になります。ここから他のコンポーネントを組み合わせて、アプリケーションの画面を構築することができApp.vueは通常、3つの主要な部分で構成されています

```App.vue
<!-- ① HTMLのようなマークアップを記述します -->
<!-- 画面に表示される内容を定義します-->
<template>
  <div id="app">
    <!-- ここに他のコンポーネントやHTMLを追加します -->
  </div>
</template>


<!-- ② JavaScriptのコードを書きます-->
<!-- データやアプリケーションの動作を定義します -->

<script>
export default {
  name: 'App',
  components: {
    // ここに他のコンポーネントをインポートします
  }
}
</script>


<!-- ③ CSSのコードを書きます。アプリケーションの見た目を整えます。-->
<style>
#app {
  /* スタイルをここに追加します */
}
</style>
```

### ④ componentに格納されているファイル

以下はバックエンド側のプロジェクトにリクエストを送り、メッセージを取得して表示させるコンポーネントの例です

※別途バックエンド側のプロジェクトが必要です
```ExampleComponent.vue
<template>
  <!-- HTMLテンプレート部分 -->
  <div>
    <!-- データプロパティ 'message' を表示 -->
    <h1>{{ message }}</h1>

    <!-- ボタンがクリックされた時に fetchData メソッドを呼び出す -->
    <button @click="fetchData">Fetch Data</button>

    <div>
      <!-- 'items' 配列の中身をリスト表示 -->
      <ul>
        <li v-for="item in items" :key="item.id">{{ item.name }}</li>
      </ul>
    </div>
  </div>
</template>

<script>
  // axiosというライブラリを使ってAPIからデータを取得します
  import axios from 'axios';

  export default {
    // データプロパティを定義する部分
    data() {
      return {
        message: '',  // メッセージを格納するための空の文字列
        items: []     // アイテムのリストを格納するための空の配列
      };
    },
    methods: {
      // 非同期でデータを取得するメソッド
      async fetchData() {
        try {
          // APIからメッセージを取得するリクエスト
          const response = await axios.get('http://localhost:8000/api/data');
          // 取得したメッセージを 'message' データプロパティに設定
          this.message = response.data.message;

          // APIからアイテムリストを取得するリクエスト
          const itemsResponse = await axios.get('http://localhost:8000/api/items');
          // 取得したアイテムリストを 'items' データプロパティに設定
          this.items = itemsResponse.data;
        } catch (error) {
          // エラーが発生した場合はコンソールにエラーメッセージを表示
          console.error('Error fetching data:', error);
        }
      }
    }
  };
</script>

<style scoped>
  /* スタイルをここに追加 */
  /* ここにCSSスタイルを記述して、このコンポーネントにのみ適用される */
</style>
```

#### コメントの説明

```vue
<template>
  <!-- ここにはHTMLの構造が記述されています。Vueコンポーネントの表示内容を決める部分です。 -->
  <h1>{{ message }}</h1>
  
  <!-- messageという変数の内容がここに表示されます。{{ message }}という書き方で、Vueが自動的に値を埋め込んでくれます。 -->
  <button @click="fetchData">Fetch Data</button>

  <!-- このボタンがクリックされた時に、fetchDataというメソッドが呼ばれます。@clickはクリックイベントを指定するためのVueの書き方です。 -->
  <ul>
    <li v-for="item in items" :key="item.id">{{ item.name }}</li>
  </ul>
  
  <!-- itemsという配列の中の各アイテムをリストとして表示します。v-forは配列の要素を繰り返して表示するためのVueの指示です。:keyはリストの各要素に一意の識別子を与えるために使います。 -->
</template>

<script>
  import axios from 'axios';

  <!-- axiosというライブラリを使って、APIからデータを取得するための準備です。 -->
  export default {
    data() {
      return {
        message: '',  <!-- この関数はコンポーネントが持つデータを返します。ここでは、表示するメッセージやアイテムのリストを初期化しています。 -->
        items: []     <!-- items データプロパティを追加 -->
      };
    },
    methods: {
      async fetchData() {
        try {
          <!-- fetchDataという名前のメソッドで、APIからデータを非同期で取得します。asyncキーワードを使うことで、データを待つ間に他の処理をブロックしないようにします。 -->
          const response = await axios.get('http://localhost:8000/api/data');
          this.message = response.data.message;
          
          <!-- APIからアイテムリストを取得するリクエスト -->
          const itemsResponse = await axios.get('http://localhost:8000/api/items');
          this.items = itemsResponse.data;
        } catch (error) {
          <!-- データを取得する処理でエラーが発生した場合に備えて、エラーハンドリングをしています。エラーが発生した場合は、コンソールにエラーメッセージを表示します。 -->
          console.error('Error fetching data:', error);
        }
      }
    }
  };
</script>

<style scoped>
  <!-- この部分には、このコンポーネント専用のCSSスタイルを記述します。scopedを使うことで、このコンポーネントだけにスタイルが適用されます。 -->
</style>

```


## フォルダ（ディレクトリ）について

### `public`
静的ファイル（画像、アイコンなど）を置くためのディレクトリです。ここに置いたファイルは、URLから直接アクセス可能ができ例えば、public/images/example.jpg という画像ファイルが存在する場合、ブラウザでURLにアクセスすると、その画像が表示されます。よってpublicディレクトリ以下にあるファイルやディレクトリは、URLを介して直接アクセス可能であり、セキュリティ上公開しても問題ないファイルのみを配置することが推奨されます。

### `components`
部品（コンポーネント）を配置するディレクトリです。例えば、「ナビゲーションバー」や「お知らせ」などの部品を作成することで、部品を組み合わせて、index.htmlのページを元に様々なページを構成することができます


### `src`
アプリケーションのソースコードが置かれる場所です。Vueコンポーネントやスタイルシート、JavaScriptファイルなど、アプリケーションのメイン部分が含まれます。

### `assets`
publicディレクトリと同じく静的ファイル（画像、アイコンなど）を置くためのディレクトリです。ただし、開発中の段階でプロジェクトが参照するためのファイルという認識のファイルを置く場所であり、最終的にはビルドツールが名前を変更したりして public ディレクトリにコピーして使用します

## 環境の設定ファイルについて

### package.json
プロジェクトで使うツールやライブラリのリストを記録します。これを使うことで、他の人が同じプロジェクトを始めるとき、同じツールやライブラリを簡単にインストールできるようになります。
例えば、「このプロジェクトではVue.jsというツールが必要です」といった情報がここに書かれます。

```json
{
  "name": "applymaster-front",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "serve": "vite preview",
    "lint": "eslint ."
  },
  "dependencies": {
    "axios": "^1.7.7",
    "core-js": "^3.8.3",
    "vue": "^3.2.13"
  },
  "devDependencies": {
    "@babel/core": "^7.12.16",
    "@babel/eslint-parser": "^7.12.16",
    "@vitejs/plugin-vue": "^5.1.3",
    "eslint": "^7.32.0",
    "eslint-plugin-vue": "^8.0.3",
    "vite": "^5.4.3"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/vue3-essential",
      "eslint:recommended"
    ],
    "parserOptions": {
      "parser": "@babel/eslint-parser"
    },
    "rules": {}
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead",
    "not ie 11"
  ]
}


```

### package-lock.json

こちらもプロジェクトで使っているツールやライブラリの「正確なバージョン」や「ダウンロード元」を記録しています。これにより、プロジェクトを他の人と共有するときや、後で自分が作業を再開するときに、全員が同じ道具を使って同じ結果が得られるようになります。

例えば、このファイルを「料理レシピのメモ」と考えた場合
package.json が「どんな材料が必要か」を教えてくれるなら、package-lock.json は「このスーパーでこのブランドのこのサイズの材料を買った」といった細かいメモです。このメモがあると、誰が料理をしても同じ味が出せるようになります。

package.json と package-lock.json は、必ずセットで使用されるものではありませんが、一緒に使われることが一般的です。

```json
{
  "name": "applymaster-front",
  "version": "0.1.0",
  "lockfileVersion": 2,
  "requires": true,
  "packages": {
    "": {
      "name": "applymaster-front",
      "version": "0.1.0",
      "dependencies": {
        "axios": "^1.7.7",
        "core-js": "^3.8.3",
        "vue": "^3.2.13"
      },
      "devDependencies": {
        "@babel/core": "^7.12.16",
        "@babel/eslint-parser": "^7.12.16",
        "@vitejs/plugin-vue": "^5.1.3",
        "eslint": "^7.32.0",
        "eslint-plugin-vue": "^8.0.3",
        "vite": "^5.4.3"
      }
    },

    以下省略...
```

## Vue.jsからHTTPリクエストを送信する方法

Vue.jsでHTTPリクエストを送信するために、axios というライブラリを使うのが一般的です。axiosは、リクエストを送信したり、レスポンスを受け取ったりするのが簡単にできます。

### axiosとは

JavaScriptでHTTPリクエストを簡単に送信するためのライブラリです。APIと通信したり、サーバーからデータを取得したりするのに役立ちます

axiosを使うと、HTTPリクエストを簡単に送ることができます。主に次の3つのリクエストメソッドがあります：

- GETリクエスト：サーバーからデータを取得する
- POSTリクエスト：サーバーにデータを送信する
- PUTリクエスト：サーバー上のデータを更新する
- DELETEリクエスト：サーバー上のデータを削除する

### axios（ライブラリ）を追加するコマンド
以下のコマンドを実行することで`axios`というライブラリがプロジェクトに追加されます。

```bash
npm install axios
```

### axiosをインポートしてAPIにリクエストを送信する（例）

```vue
<template>
  <div>
    <h1>{{ message }}</h1>
    <button @click="fetchData">Fetch Data</button>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      message: ''
    };
  },
  methods: {
    async fetchData() {
      try {
        // APIのURLにリクエストを送信
        const response = await axios.get('http://example.com/api/data');
        
        // APIから返ってきたデータをmessageにセット
        this.message = response.data.message;
      } catch (error) {
        console.error('Error fetching data:', error);
      }
    }
  }
};
</script>

<style scoped>
/* スタイルをここに追加 */
</style>
```


### axios についての解説
```php
import axios from 'axios';

// axiosライブラリをインポートして、コンポーネントで使えるようにします。

axios.get('http://example.com/api/data');

// axiosを使って、指定したURL
//（ここではhttp://example.com/api/data）にGETリクエストを送信します。
// GETリクエストは、データを取得するためのリクエストです。

this.message = response.data.message;

// APIから返ってきたデータを message に保存して、ページに表示します。

try { ... } catch (error) { ... }

// リクエスト中にエラーが発生した場合に備えて、
// エラーハンドリングを行います。
// エラーが発生した場合は、コンソールにエラーメッセージを表示します。
```