---
# System prepended metadata

title: "前端環境 \U0001F440 無用的知識增加了"
tags: [環境相關]

---

# 前端環境 👀 無用的知識增加了

---

## 什麼時候建立這些檔案與資料夾

| 項目                | 什麼時候建立？              | 說明                 |
| ----------------- | -------------------- | ------------------ |
| `.env`            | 建立 server/index.js 前 | 用於設定 PORT、API\_KEY |
| `router/index.js` | 安裝 `vue-router` 後    | 控制前端路由             |
| `src/services/`   | 要與 API 互動時           | 放 axios 相關邏輯       |
| `store/`          | 需要全域狀態時              | 使用 pinia 管理        |


---

## main.js PrimeVue

在 main.js 註冊 PrimeVue
打開 src/main.js，加入以下內容（✨整合版）：

```
import { createApp } from 'vue'
import App from './App.vue'

// PrimeVue 核心 & 主題樣式
import PrimeVue from 'primevue/config'
import 'primevue/resources/themes/lara-light-blue/theme.css' // 主題
import 'primevue/resources/primevue.min.css'                 // 元件樣式
import 'primeicons/primeicons.css'                           // 圖示庫
import 'primeflex/primeflex.css'                             // 排版工具

const app = createApp(App)
app.use(PrimeVue)
app.mount('#app')
```



### 逐行解釋



Vue 的初始化設定

```
import { createApp } from 'vue'
import App from './App.vue'
```

🔹 createApp：從 Vue 套件裡拿出來的功能，用來建立整個 Vue App（Vue 3 的寫法）
🔹 App.vue：你專案的「主畫面元件」，等於是整個網站的入口頁

---

PrimeVue 的初始化設定

```
import PrimeVue from 'primevue/config'
```

🔸 這是把 PrimeVue 這個 UI 元件庫的設定引進來，後面會 .use() 用到
🔸 這樣你才能在每個頁面使用 `<Button>`, `<Dialog>` 等元件

---

🎨 匯入主題樣式

```
import 'primevue/resources/themes/lara-light-blue/theme.css'
```

這是你網頁的「整體配色與風格」，例如按鈕長什麼樣、背景色、陰影等等
你可以換成其他主題（像 lara-dark-indigo），一行換風格。

---

📦 匯入 PrimeVue 所有元件的基本樣式庫

```
import 'primevue/resources/primevue.min.css'
```
這是必要的。
就像衣服的基本材質，有這行你才能看到按鈕長出外型。

---

🔠 匯入圖示庫（Icons）

```
import 'primeicons/primeicons.css'
```

使用範例
```
<i class="pi pi-check"></i>  ← ✅ 圖示
```

---

🧱 匯入 PrimeVue 的 CSS 工具集

```
import 'primeflex/primeflex.css'
```

使用範例
```
<div class="flex justify-content-between align-items-center">...</div>
```

---

把前面所有東西「組起來並啟動」

```
const app = createApp(App)
app.use(PrimeVue)
app.mount('#app')
```

| 步驟               | 說明                                        |
| ---------------- | ----------------------------------------- |
| `createApp(App)` | 建立整個 Vue App                              |
| `.use(PrimeVue)` | 啟用 PrimeVue 元件系統                          |
| `.mount('#app')` | 把整個網站掛在 `index.html` 的 `<div id="app">` 裡 |

🧩 小提醒：這段只做「主程式初始化 + UI 套件載入」
之後你還需要在每個要用元件的 .vue 檔中個別匯入元件才能使用。

### PrimeVue 元件使用方式小提醒

很多 UI 套件需要註冊個別元件，例如：

```
import Button from 'primevue/button'
app.component('Button', Button)
```

 元件註冊方式的兩種策略：
 * 單一註冊（個別引入）→ 效能佳
 * 全域註冊（註冊所有常用元件）→ 開發快速

可搭配：

```
// plugins/primevue.js
import Button from 'primevue/button'
app.component('Button', Button)
```

可以集中管理註冊過的元件。


---

## 誰規定了什麼 Vue / Vite / UI框架

🧠 一次釐清：誰規定了什麼？
| 語句                                                 | 誰規定的         | 為什麼要這樣寫                                     |
| -------------------------------------------------- | ------------ | ------------------------------------------- |
| `import { createApp } from 'vue'`                  | ✅ Vue        | Vue 3 官方的 App 初始化方式（Vue 2 是用 `new Vue()`）   |
| `import App from './App.vue'`                      | ✅ Vue + Vite | Vue 支援 `.vue` 檔案語法，Vite 幫忙處理這類 import       |
| `import PrimeVue from 'primevue/config'`           | ✅ PrimeVue   | 這是 PrimeVue 定義的初始化方法，要先 `.use(PrimeVue)`    |
| `import 'primevue/resources/themes/xxx/theme.css'` | ✅ PrimeVue   | 每個主題的 CSS 都被獨立放在這個資料夾下                      |
| `import 'primevue/resources/primevue.min.css'`     | ✅ PrimeVue   | 所有元件都共用的「基本樣式表」                             |
| `import 'primeicons/primeicons.css'`               | ✅ PrimeIcons | PrimeVue 圖示庫是獨立的套件，必須自己引入                   |
| `import 'primeflex/primeflex.css'`                 | ✅ PrimeFlex  | CSS 工具集，像 Tailwind 一樣需要你手動引入                |
| `app.use(PrimeVue)`                                | ✅ Vue（設計模式）  | Vue plugin 設計規定，要用 `.use()` 方式註冊第三方功能       |
| `app.mount('#app')`                                | ✅ Vue        | Vue 的啟動規則，將 app 掛在 HTML 中的 `<div id="app">` |


🔍 各角色負責什麼？
🟦 Vue
* 定義了 createApp()、.use()、.mount() 等生命週期方法
* 決定你怎麼寫 .vue 檔案
* 你在 .vue 中用的 `<template>`、`<script>`、`<style>` 都是 Vue 定的

🟨 Vite
* 處理 import 行為，讓你可以直接寫 .vue / .css / 第三方元件
* 支援熱更新（Hot Reload）、打包、開發伺服器等
* 負責讓你開啟 `http://localhost:????` 就能看到畫面

🟩 PrimeVue
* 提供元件（Button、Dialog、Table...）
* 規定你要如何引入元件（import）、初始化（`PrimeVue from 'primevue/config'`）
* 自家設計的主題與圖示庫要自己引入

---

🧩 總結一口氣記住：
| 領域                      | 誰決定的？    | 代表規則                   |
| ----------------------- | -------- | ---------------------- |
| 應用啟動方式（createApp、mount） | Vue      | App 怎麼啟動、掛載            |
| 組件設計與 .vue 語法           | Vue      | `<template>` 怎麼寫       |
| `import` / 模組處理         | Vite     | 支援 CSS/圖示/vue 組件匯入     |
| UI 元件、主題、class 名稱       | PrimeVue | 要怎麼寫 `<Button>`、要引哪些樣式 |

三者關係
Vue（主導架構） ← Vite（打包與開發助手） ← PrimeVue（元件 UI 借給你用）


---

## 常駐工具型功能款總整理（LIST）

- HTTP 請求：`axios`
- 表單驗證：`vee-validate`, `yup`
- 狀態管理：`pinia`
- 狀態儲存：`pinia-plugin-persistedstate`
- Icon 擴充：`@iconify/vue`
- 日期處理：`dayjs`

---

HTTP 請求
axios
向 API 取資料、送表單用

```
npm i axios
```

---

vee-validate + yup
表單驗證
預設表單驗證搭配。前端專案幾乎都會有表單

```
npm i vee-validate yup
```

---

pinia
狀態管理
Vue 官方推薦的 state 管理工具（新版 Vuex）
```
npm i pinia
```

---

pinia-plugin-persistedstate
狀態儲存
狀態資料存到 localStorage，記住登入等狀態

```
npm install pinia-plugin-persistedstate
```

---

@iconify/vue
Icon 額外擴充

```
npm install @iconify/vue
```

---

dayjs（或 date-fns）
日期處理
處理日期字串、轉格式、相對時間等
```
npm install dayjs
```

---

## pinia 註冊方式補充（main.js）

註冊方式：
```
// main.js 中加上
import { createPinia } from 'pinia'
const pinia = createPinia()
app.use(pinia)
```

---

## pinia-plugin-persistedstate 的使用方式補充

註冊方式：
```
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

pinia.use(piniaPluginPersistedstate)
```

---

## unplugin-auto-import

`unplugin-auto-import` 是在 **Vite / Vue / Nuxt / Rollup / Webpack** 等環境中常用的 **自動引入套件**，以下是它的介紹與用法整理 👇

### 📦 `unplugin-auto-import` 是什麼？

它是一個 **自動幫你引入 import 的工具**。

#### 🧠 背後動機：

開發 Vue 或其他框架時，常常會重複寫這種東西：

```js
import { ref, computed } from 'vue'
```

這種語法重複又容易忘記，加上 IDE 有時會提示但不自動補全，所以這個套件就是：
👉 **讓你用 `ref()` 就好，不用手動 import `ref`**

### 🔧 安裝方式（以 Vite 為例）

```bash
npm i -D unplugin-auto-import
```

### ⚙️ 在 Vite 設定中使用（vite.config.js）

```js
import AutoImport from 'unplugin-auto-import/vite'

export default {
  plugins: [
    AutoImport({
      // 📚 常用的自動引入來源
      imports: [
        'vue',          // ref, reactive, computed...
        'vue-router',   // useRoute, useRouter...
        'pinia',        // defineStore...
      ],
      dts: 'src/auto-imports.d.ts', // 👉 自動產生的 TypeScript 提示檔
    }),
  ]
}
```

### ✅ 自動引入範例

你可以直接寫：

```js
const count = ref(0)
const doubled = computed(() => count.value * 2)
```

不需要手動 import！

### 📘 支援什麼？

你可以自定義要引入的內容，例如：

```js
AutoImport({
  imports: [
    {
      axios: [
        ['default', 'axios']  // 讓你可以直接寫 axios()
      ]
    }
  ]
})
```

還可以配合：

* `eslint` 的全域變數自動註冊
* 自動引入 `api/` 或 `composables/` 裡的函式（進階用法）

### ⚠️ 注意事項

* 如果你使用的是 Vue + `<script setup>`，其實也可以用 `<script setup>` 的自動解構，但 `unplugin-auto-import` 更廣泛且跨框架
* 要搭配 TypeScript 的話，記得開啟 `dts` 來讓編輯器支援提示

---

---

## unplugin-vue-components

`unplugin-vue-components` 是 Vue 開發中常見的 **自動註冊元件套件**，常跟 `unplugin-auto-import` 搭配使用，下面我幫你整理一份實用說明 👇

### 📦 `unplugin-vue-components` 是什麼？

> 🔧 讓你**不用手動 import 與註冊 Vue 元件**，就能直接使用元件！

### 🧠 使用動機

通常我們在 Vue 專案中這樣引入元件：

```js
import MyButton from '@/components/MyButton.vue'

export default {
  components: {
    MyButton
  }
}
```

但隨著專案變大，這些 import 與註冊會變得很繁瑣，
這個套件讓你直接在 `.vue` 裡寫 `<MyButton />`，它會幫你自動載入與註冊。

### 🚀 安裝

```bash
npm i -D unplugin-vue-components
```

### ⚙️ 基本設定（Vite）

在 `vite.config.js` 中加入：

```js
import Components from 'unplugin-vue-components/vite'

export default {
  plugins: [
    Components({
      // 🔍 掃描目錄（預設就是 'src/components'）
      dirs: ['src/components'],

      // 產生 TypeScript 自動提示
      dts: 'src/components.d.ts'
    })
  ]
}
```

### ✅ 用法範例

專案中有個 `src/components/MyButton.vue`：

```vue
<!-- 你可以直接用，不需 import -->
<template>
  <MyButton />
</template>
```

### 🌟 支援 UI 框架自動引入（超方便）

如果你使用 PrimeVue、Vuetify、Element Plus、Ant Design Vue 等元件庫，
可以加上 `resolvers` 自動引入樣式與註冊元件！

#### 例如 PrimeVue 設定：

```bash
npm i -D unplugin-vue-components
npm i -D unplugin-auto-import
npm i -D unplugin-vue-components/resolvers
```

```js
import Components from 'unplugin-vue-components/vite'
import { PrimeVueResolver } from 'unplugin-vue-components/resolvers'

export default {
  plugins: [
    Components({
      resolvers: [PrimeVueResolver()],
      dts: 'src/components.d.ts',
    }),
  ]
}
```

### 🛠️ 進階用法

可以掃描多個元件目錄：

```js
dirs: ['src/components', 'src/base-components']
```

### ⚠️ 注意事項

* 不支援 **動態元件名稱**（如 `<component :is="compName" />`）→ 要自己 import
* 自動掃描元件可能會略影響編譯速度（大量元件時）
* `components.d.ts` 記得加進 `.gitignore` 或 version control 依情況決定

---

---

## unplugin-vue-router

`unplugin-vue-router` 是 Vue 3 開發中**新一代的路由自動生成工具**，如果你覺得 `vue-router` 的手動寫法很囉唆，這個套件可以幫你**自動根據檔案結構產生路由**，邏輯有點像 Nuxt.js / Next.js 的檔案式路由，但保有完全客製彈性 ✨


### 📦 `unplugin-vue-router` 是什麼？

> ⛩ 自動根據 `/src/pages` 資料夾產生 `vue-router` 路由表，
> 不用自己寫 `routes = [...]` 陣列啦！


### 🧠 為什麼使用它？

#### 傳統 vue-router 的痛點：

```js
const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About },
  ...
]
```

重複寫很累，還要手動 import 元件 🤯
👉 `unplugin-vue-router` 幫你「**掃描檔案 → 自動生成路由 → 支援型別推論**」。


### 🛠️ 安裝

```bash
npm i -D unplugin-vue-router
```


### ⚙️ 基本設定（Vite）

```js
// vite.config.js
import VueRouter from 'unplugin-vue-router/vite'

export default {
  plugins: [
    VueRouter({
      routesFolder: 'src/pages', // 預設掃描頁面元件的資料夾
      dts: 'src/typed-router.d.ts', // TypeScript 推論
    })
  ]
}
```


### 📂 檔案式路由結構範例

```
src/
├─ pages/
│  ├─ index.vue         -> 路由：/
│  ├─ about.vue         -> 路由：/about
│  └─ blog/
│     ├─ [id].vue       -> 路由：/blog/:id
```


### 🧩 如何使用？

在 `main.js` 裡改用它產生的 router：

```js
import { createApp } from 'vue'
import App from './App.vue'

// ↓ 使用這個 router 替代 vue-router 自己寫的
import { createRouter, createWebHistory } from 'vue-router/auto'

const app = createApp(App)

const router = createRouter({
  history: createWebHistory(),
})

app.use(router)
app.mount('#app')
```


### 🧠 額外強項

* 支援 `definePageMeta()` → 可在元件中自訂 `meta`
* 支援 TypeScript 推論所有路由
* 支援中間層資料夾作為 Layout（像 Nuxt）
* 可客製擴充：你還是能手動新增路由或混合使用


### 📌 VS 傳統 vue-router

| 功能           | 傳統 vue-router | unplugin-vue-router |
| ------------ | ------------- | ------------------- |
| 自動產生路由       | ❌             | ✅                   |
| 檔案路由         | ❌             | ✅                   |
| 支援型別提示       | 部分            | ✅                   |
| 中間 layout 支援 | ❌             | ✅                   |
| Nuxt/Next 風格 | ❌             | ✅                   |


### ⚠️ 注意事項

* 你仍需使用 `vue-router@4`，這是它底層的核心。
* 如果你使用 `<script setup>` 可以搭配 `useRoute()`、`useRouter()`，同樣能支援推論。
* `src/pages` 是它預設掃描的資料夾，**不能亂放**頁面元件。
* 有些情境仍需要 `definePageMeta()` 或手動 route 擴充（例如設定 `meta.requiresAuth`）


如果你有使用 `unplugin-auto-import` 的話，可以一起補上：

```js
import AutoImport from 'unplugin-auto-import/vite'

AutoImport({
  imports: [
    'vue',
    'vue-router/auto', // 自動引入 useRoute / useRouter 且支援 typed router
  ],
  dts: 'src/auto-imports.d.ts',
})
```

---

---

## vite-plugin-vue-layouts-next

`vite-plugin-vue-layouts-next`，這是 Vue 3 + Vite 專案中，**用來實現「多版型（多 Layout）」功能的套件**，非常適合搭配像 `unplugin-vue-router` 這種自動路由系統使用。

---

### 📦 `vite-plugin-vue-layouts-next` 是什麼？

> 幫你實現「版型管理系統」，例如：
>
> * 登入頁使用 `AuthLayout.vue`
> * 管理後台頁使用 `AdminLayout.vue`
> * 一般使用者頁使用 `DefaultLayout.vue`

它會依據你在頁面元件中設定的 layout 名稱，自動套用對應的版型。

---

### 🧠 解決什麼問題？

在大型 Vue 專案中，不同頁面常常有不同外觀：

* 有些頁面有 sidebar、有些沒有
* 有些頁面是全畫面，有些有 header/footer

自己用 `v-if` 切換 layout 很麻煩，這套件幫你自動搞定。

---

### 🛠️ 安裝

```bash
npm i -D vite-plugin-vue-layouts-next
```

---

### ⚙️ 基本設定（vite.config.js）

```js
import VueLayouts from 'vite-plugin-vue-layouts-next'

export default {
  plugins: [
    VueLayouts({
      layoutsDirs: 'src/layouts',       // 預設 layouts 放這裡
      defaultLayout: 'default',         // 沒寫的話就用 default.vue
    })
  ]
}
```

---

### 🧩 使用方式

#### 1. 建立 Layouts 結構（在 `src/layouts`）

```
src/
├─ layouts/
│  ├─ default.vue
│  ├─ auth.vue
│  └─ admin.vue
```

每個 Layout 都是一個元件，像這樣 👇

```vue
<!-- src/layouts/default.vue -->
<template>
  <div>
    <Header />
    <main>
      <slot />
    </main>
    <Footer />
  </div>
</template>
```

---

#### 2. 頁面元件設定 Layout

在 `src/pages/` 裡的某個頁面元件：

```vue
<!-- src/pages/dashboard.vue -->
<script setup>
definePageMeta({
  layout: 'admin'   // 🔁 這頁會套用 admin.vue
})
</script>

<template>
  <h1>後台頁面</h1>
</template>
```

---

### 📦 常搭配組合

| 功能          | 套件                             |
| ----------- | ------------------------------ |
| 自動產生路由      | `unplugin-vue-router`          |
| 自動註冊 Layout | `vite-plugin-vue-layouts-next` |
| 自動註冊元件      | `unplugin-vue-components`      |
| 自動引入常用函式    | `unplugin-auto-import`         |

---

### 📌 完整搭配範例流程

```bash
npm i vue-router@4
npm i -D unplugin-vue-router vite-plugin-vue-layouts-next
```

接著搭配如下：

#### `vite.config.js`

```js
import VueRouter from 'unplugin-vue-router/vite'
import VueLayouts from 'vite-plugin-vue-layouts-next'

export default {
  plugins: [
    VueRouter({}),
    VueLayouts({})
  ]
}
```

#### `main.js`

```js
import { createApp } from 'vue'
import App from './App.vue'
import { createRouter, createWebHistory } from 'vue-router/auto'
import { setupLayouts } from 'virtual:generated-layouts'

const router = createRouter({
  history: createWebHistory(),
  extendRoutes: setupLayouts, // 🚨 這句很重要！自動套 layout
})

const app = createApp(App)
app.use(router)
app.mount('#app')
```

---

### ⚠️ 注意事項

* Layout 檔案的檔名不要用大寫開頭（可能會抓不到）
* 必須搭配 `vue-router` 使用（尤其建議搭配 `unplugin-vue-router`）
* `definePageMeta()` 是由 `unplugin-vue-router` 提供的 → 所以這兩個通常一起用

---

## unplugin-fonts
這是一個非常實用的小工具，尤其適合懶得手動搞 Google Fonts 的人

### 🎯 `unplugin-fonts` 是什麼？

> 👉 它是一個 **自動幫你載入 Web 字型**（通常是 Google Fonts）的 Vite 插件，
> 讓你不需要在 HTML 裡加 `<link>`，也不必自己下載字型檔。

---

### ✅ 使用動機

原本你得這樣手動在 `index.html` 裡寫：

```html
<link href="https://fonts.googleapis.com/css2?family=Roboto&display=swap" rel="stylesheet">
```

但這很麻煩，而且不同字型、不同字重、不同語系還要手動拼 URL 😩

👉 裝了 `unplugin-fonts` 後，只要在 `vite.config.js` 裡設定：

```js
Fonts({
  google: {
    families: ['Roboto']
  }
})
```

它就會幫你：

* 自動載入 Google Fonts
* 幫你生成正確的 font-face、權重參數
* 自動注入 `<link>` 到頁面（或用 CSS import）

---

### 🛠️ 安裝方式

```bash
npm i -D unplugin-fonts
```

---

### ⚙️ 基本設定範例

```js
import Fonts from 'unplugin-fonts/vite'

export default defineConfig({
  plugins: [
    Fonts({
      google: {
        families: [
          {
            name: 'Roboto',
            styles: 'wght@100;300;400;500;700;900',
          },
          {
            name: 'Noto Sans TC', // 支援繁體中文
            styles: 'wght@400;700',
          },
        ]
      }
    })
  ]
})
```

---

### 🤔 它做了什麼？

| 功能                     | 說明                    |
| ---------------------- | --------------------- |
| ✅ 自動產生 Google Fonts 連結 | 幫你拼好網址                |
| ✅ 注入 HTML              | 自動幫你加進 `<head>` 裡     |
| ✅ 支援多個字型與權重            | `wght@400;700` 等      |
| ✅ 支援自訂 provider        | 預設是 Google，也可自訂或切換成本地 |

---

### ⚠️ 注意事項

* 這是**開發用超方便工具**，但在**正式專案中**建議還是針對字型做更精細的優化（例如自行下載、使用 subset）
* 預設是載入 Google Fonts，如果你想切成 CDN / 自架字型，也可以設定 `custom` provider
* 不會自動把字型套用到你專案，還是要自己在 `main.css` 或 `App.vue` 裡加：

```css
body {
  font-family: 'Roboto', sans-serif;
}
```

---

### ✅ 是否通用？

完全通用 ✔️

| 使用框架                     | 是否支援                    |
| ------------------------ | ----------------------- |
| Vue + Vite               | ✅                       |
| React + Vite             | ✅                       |
| Nuxt / Astro / SvelteKit | ⚠️ 不一定支援，需手動整合          |
| Webpack                  | ❌ 官方只提供 Vite/ESBuild 入口 |

---

### 🧾 小結

| 問題            | 答案                                |
| ------------- | --------------------------------- |
| 是做什麼的？        | 幫你自動載入 Google Fonts，不用寫 `<link>`  |
| 推不推薦？         | ✅ 如果你用 Google Fonts 且想省事，這套件超讚    |
| 可以拿掉嗎？        | 可以，如果你改成手動載入或不需要字型了               |
| 能跟 UI 套件一起用嗎？ | ✅ 可以補上字型搭配主題（如 Roboto 配 PrimeVue） |

---

## 後端初始化

server/index.js

```
// server/index.js（最小 Express 範例）
import express from 'express'
import dotenv from 'dotenv'

dotenv.config()

const app = express()
const port = process.env.PORT || 3000

app.get('/api/hello', (req, res) => {
  res.json({ message: 'Hello from backend!' })
})

app.listen(port, () => {
  console.log(`Server is running on http://localhost:${port}`)
})
```

搭配 .env

```
PORT=3000
```

---


---

## Vite → Proxy

🧭 問題背景：為什麼需要 proxy？
當跑 Vite 前端時，會開在：

```
http://localhost:5173
```
而跑後端 Express 時，會開在：

```
http://localhost:3000
```

這時候如果在前端裡寫：

```
axios.get('http://localhost:3000/api/hello')
```

就會遇到這個錯誤：

>` ❌ Access to fetch at 'http://localhost:3000/api/hello' from origin 'http://localhost:5173' has been blocked by CORS policy`

原因：
因為前後端「不同源」（不同 port），瀏覽器預設禁止跨域請求。


✅ 解法：用 Vite 的 proxy 幫你偷偷轉送請求

前端這樣寫：

```
axios.get('/api/hello') // 沒有寫 http://localhost:3000
```

然後在 Vite 設定中這樣寫：
（vite.config.js）

```
// vite.config.js
export default {
  server: {
    proxy: {
      '/api': 'http://localhost:3000'
    }
  }
}
```

意思是：

> ❗「當你請求 /api/xxx，我會幫你偷偷轉送到 `http://localhost:3000/api/xxx`」

這樣前端看起來就像自己處理，但實際上請求是送給後端的。

📌 什麼時候要用 Vite proxy？
| 使用時機                       | 原因                    |
| -------------------------- | --------------------- |
| 前後端開發分開時（不同 port）          | 避免跨域錯誤（CORS）          |
| 想要前端 axios 寫簡單 `/api/...` | 保持代碼環境一致，方便日後部署       |
| 後端是自己寫的（express）           | 你可以控制本地 port，也能接收這些請求 |

✅ 一個完整範例流程
1. 後端：Express 設一個 API

```
// server/index.js
app.get('/api/hello', (req, res) => {
  res.json({ message: 'hello from server' })
})
```

2. 前端：Vue 組件中使用 axios

```
axios.get('/api/hello')
  .then(res => console.log(res.data.message))
```

3. Vite 設定 proxy：

```
// vite.config.js
export default {
  server: {
    proxy: {
      '/api': 'http://localhost:3000'
    }
  }
}
```

✅ 成功！你不需要處理 CORS、也不用寫死 IP，前端開發乾乾淨淨。

---

## axios 的 baseURL 設定方式 .env 變數範例

.env

```
VITE_API_BASE_URL=http://localhost:3000
```

axios 寫法

```
const baseURL = import.meta.env.VITE_API_BASE_URL
```

---

---

## 寫的順序跟實際上跳轉的順序

🎯 情境設定
>🔧 專案使用 Vite（Vue）為前端、Express 為後端，有 .env 檔、可能有 API 溝通。

🛠 該從哪裡開始寫？
| 起手區塊                | 說明                           | 路徑建議                         |
| ------------------- | ---------------------------- | ---------------------------- |
| ✅ `server/index.js` | 後端 API 入口                    | `/server/index.js`           |
| ✅ `client/`         | Vite + Vue 前端專案              | `/client/` 是完整前端資料夾（像你現在的專案） |
| ✅ `.env`            | 後端的機密設定（例如 PORT、API KEY）     | 放在根目錄 `/`                    |
| ✅ `.gitignore`      | 忽略 `.env` / `node_modules` 等 | 放根目錄                         |

可以先寫後端伺服器（server/index.js）→ 確保能回傳資料 → 再寫前端來抓資料

🔁 前後端程式運作順序圖（超重要！）

```
[瀏覽器開啟網頁]
        ↓
[前端：Vite 伺服器] ← Vue 負責畫面
        ↓ （向後端請求資料）
[後端：Express 伺服器] ← 接收請求、回應 JSON
        ↓
[傳資料回前端]
        ↓
[Vue 畫出資料]
```

✅ 所以前端主要負責：
* 畫畫面（Vue + PrimeVue）
* 抓資料（axios 去 call Express API）
後端主要負責：
* 接收前端請求（用 app.get()、app.post()）
* 回應資料（資料庫 or 假資料）

✏️ 實際檔案撰寫順序（最推薦）
1. 先寫後端` server/index.js`：
> 建 Express app
> 建一個測試 API，例如 /api/hello
> 用 nodemon 跑起來測試能不能回應資料

2. 再寫前端 `client/` 專案（你已經建立好了）
> 加 axios
> 在 Vue 組件中去 GET /api/hello
> 顯示回傳資料

3. 加 .env 設定 `port（ex: 3000）`：

```
PORT=3000
```

4. 在前端 `vite.config.js` 加上 proxy，讓 `/api/` 轉向後端：

```
// vite.config.js
export default defineConfig({
  server: {
    proxy: {
      '/api': 'http://localhost:3000'
    }
  }
})
```

所以整個 `vite.config.js` 的完整範本

```
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  server: {
    proxy: {
      '/api': 'http://localhost:3000'
    }
  }
})
```

🧩 總結
```
📁 server/
　└─ index.js ← 🥇 從這開始寫（提供 API）

📁 client/
　└─ 已建好（Vite + Vue）← 🥈 接著寫這邊，抓 API

📄 .env
　→ 提供後端參數

📄 vite.config.js
　→ 幫前端 proxy 到後端
```
❓你現在可以問自己：
* 我想要前端從哪裡「抓資料」？（→ 後端 API 要先寫）
* 我要不要測試前後端能不能對話成功？（→ 用 axios call /api/hello 看看）
* 我的 .env 有提供後端啟動資訊嗎？（→ 設定 PORT）

---

## vite.config.js 的簡單用途

如果有些套件需要設定 alias（像 @/views/...）：

```
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import 
from 'path'

export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src')
    }
  }
})
```

多環境處理補充
後來有 dev / staging / production 時，可以補充這段

```
// vite.config.js
const isDev = process.env.NODE_ENV === 'development'
proxy: {
  '/api': isDev
    ? 'http://localhost:3000'
    : 'https://my-prod-api.com'
}
```

---

## axios 封裝 service 範例（加強 /services/ 用法）

🔁 axios 攔截器（interceptors）：可在每次發送/接收請求前統一處理資料，例如自動加上 Authorization token，或是統一處理錯誤訊息。

例如：建立 /services/userService.js

```
import axios from 'axios'

const baseURL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:3000'

export const login = (formData) => axios.post(`${baseURL}/login`, formData)
export const fetchUser = (id) => axios.get(`${baseURL}/user/${id}`)
```

> ☑ 用途：集中處理後端 API 的路徑與格式

error 處理建議

```
export const fetchUser = async (id) => {
  try {
    const res = await axios.get(`${baseURL}/user/${id}`)
    return res.data
  } catch (error) {
    console.error('❌ 無法取得使用者資料', error)
    throw error
  }
}
```


---

## App.vue 裡預設的 router-view（路由出口）

```
<template>
  <router-view />
</template>
```

> ☑ 用途：Vue Router 的畫面顯示容器，對應你設定的 routes

---

## 每個資料夾負責什麼

> Vue 專案的資料夾結構會因人而異，但在實務開發中，已經發展出一套非常清楚的責任分工慣例

🗂 Vue 專案中每個資料夾的常見用途（建議使用習慣）
| 資料夾名稱                    | 📦 責任類型  | 🧠 負責什麼事                                           | 範例與說明                                          |
| ------------------------ | -------- | -------------------------------------------------- | ---------------------------------------------- |
| `📁 assets/`             | 📁 靜態資源  | 存放圖片、音效、影片、樣式檔（SCSS、CSS）                           | 不經 JavaScript 處理，可直接在 `<img src>` 中用           |
| `📁 components/`         | 🧩 共用元件  | 放「可重複使用」的小元件（按鈕、卡片、標籤等）                            | 通常會配合 `props` 與 `slots` 提高彈性                   |
| `📁 views/`              | 🧱 頁面元件  | 放「對應路由」的大畫面（像首頁、商品頁、表單頁）                           | 一頁一個 `.vue`，對應 `router` 裡的 path                |
| `📁 router/`             | 🚦 路由控制  | 放 Vue Router 設定檔（定義頁面對應路徑）                         | 最常見是 `router/index.js` 或 `router.js`           |
| `📁 store/`              | 🧠 狀態管理  | 管理應用程式的共用資料（如登入狀態、購物車）                             | 若用 `pinia`，這裡放 `userStore.js`、`cartStore.js` 等 |
| `📁 services/`           | 🔁 後端互動  | 負責 API 請求的封裝（如 axios 請求）                           | 像是 `api.js`、`userService.js`、`orderService.js` |
| `📁 composables/`        | 🧩 可組合邏輯 | 放 `useXXX()` 型的邏輯抽取函式（Vue 3 的 `setup()` 工具）        | e.g. `useAuth.js`, `useScroll.js`              |
| `📁 plugins/`            | 🔌 插件註冊  | 放第三方套件註冊（ex: vee-validate、i18n）                    | 在 `main.js` 中集中註冊與初始化                          |
| `📁 layouts/`            | 🏗 結構外殼  | 若有使用 layout 機制（像 Nuxt），可放固定結構模板（如 navbar + footer） | 有時會搭配 slot 與動態內容                               |
| `📁 utils/` 或 `helpers/` | 🧮 工具函式  | 存放純邏輯工具（格式轉換、計算、字串處理）                              | 不牽涉 Vue，只處理資料                                  |
| `📁 constants/`          | 📑 常數資料  | 存放靜態字典、分類表、選項清單                                    | 例如地區列表、狀態對照表                                   |

🧩 小提醒：幾個常見易混淆的區塊
| 比較項目 | `components/`                 | `views/`                       |
| ---- | ----------------------------- | ------------------------------ |
| 用途   | 可重用的組件                        | 對應頁面的單位                        |
| 尺寸   | 小顆、模組化                        | 大顆、可能包多個組件                     |
| 例子   | `MyButton.vue`、`UserCard.vue` | `HomeView.vue`、`LoginPage.vue` |

📦 如果你要做分頁專案或多人開發，建議你也這樣設計：

```
📁 src/
│
├── 📁 assets/        # 靜態圖像與樣式
├── 📁 constants/     # 常數資料
├── 📁 components/    # 可重用 UI 元件
├── 📁 plugins/       # 套件註冊
├── 📁 layouts/       # 版型
├── 📁 pages/         # 頁面元件（對應路由）
├── 📁 router/        # 路由設定
├── 📁 services/      # API 請求封裝
├── 📁 store/         # 狀態管理（pinia）
├── 📁 composables/   # Vue Composition API 用的自訂邏輯
├── 📁 utils/         # 輔助函式
└── main.js           # 入口程式
```

🧰 資料夾命名慣例對照表

| 概念     | 常見命名                | 備註              |
| ------ | ------------------- | --------------- |
| 狀態管理   | `store` / `pinia`   | 建議統一，避免混用       |
| API 請求 | `services` / `api`  | `services` 比較通用 |
| 工具函式   | `utils` / `helpers` | 視團隊習慣而定         |


---

## 📁 Vue 資料夾 × 功能對照表

| 資料夾名稱          | 功能角色                   | 負責任務說明                                               |
| -------------- | ---------------------- | ---------------------------------------------------- |
| `src/`         | 專案主體根目錄                | 所有 Vue 程式碼都放這，以下皆為此目錄下的子資料夾                          |
| `views/`       | 📺 頁面元件                | 一個頁面一個 `.vue`，對應到路由設定（如首頁、登入頁、訂單頁）                   |
| `components/`  | 🧩 可重用元件               | 可在多頁共用的小單位（如按鈕、modal、navbar、表單欄位）                    |
| `router/`      | 🚦 頁面路由設定              | Vue Router 註冊點，定義網址對應哪些頁面元件（`index.js`）              |
| `pinia/`       | 🧠 全域狀態管理              | Vue 的狀態儲存區（如登入狀態、購物車內容等），內含 store 模組                 |
| `services/`    | 🔁 API 請求模組            | axios 請求封裝區，統一集中管理 API 呼叫（如 `/api/order.js`）         |
| `assets/`      | 🖼 圖片 / CSS 等靜態資源      | 存放樣式檔、圖片、字型等靜態素材                                     |
| `layouts/`     | 📐 頁面共用框架（選用）          | 若你有 header/sidebar 等重複區塊，可抽出來放這裡（非必要，視專案規模決定）        |
| `composables/` | 🪝 自定義組合函式（選用）         | Vue 3 中用 `setup()` 時常會寫的 `useXXX()` 模組，可集中寫重複邏輯      |
| `store/`       | ✅ 同 `pinia/`，若你寫成這樣也可以 | `store/` 是常見 pinia 資料夾名稱，也有些人寫成 `stores/`，建議你選一種寫法統一 |
| `constants/`   | 📑 常數定義區（選用）           | 放不會變動的資料（如 API baseURL、表單選項清單、錯誤訊息對照）                |
| `utils/`       | 🛠 小工具函式（選用）           | 處理資料轉換、日期處理、字串轉換等通用函式（跟 services 最大差異是：不會打 API）      |

public/：放「不經過 Vite 處理、會直接放到打包輸出」的靜態檔案，如 favicon、robots.txt、Google 驗證檔等。

---

## 所有常見初始化組合

### .vue 組件結構補充（模板 / 腳本 / 樣式）

```
<template>
  <div>{{ msg }}</div>
</template>

<script setup>
const msg = 'Hello World'
</script>

<style scoped>
div {
  color: red;
}
</style>
```

### vite.config.js 初始化範例

需要加 `@vitejs/plugin-vue` 才能解析 `.vue`

```
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
plugins: \[vue()],
resolve: {
alias: {
'@': path.resolve(\_\_dirname, './src')
}
},
server: {
proxy: {
'/api': '[http://localhost:3000](http://localhost:3000)'
}
}
})
````

### `main.js` 中的 `vue-router` 與 `pinia` 初始化流程


```
import router from './router' // 假設你 router 設在 src/router/index.js
app.use(router)
```

### `.env` 與 `import.meta.env` 的更多範例

```
VITE_APP_TITLE=我的專案
VITE_API_BASE_URL=http://localhost:3000
```

* 所有以 `VITE_` 開頭的變數才會被 Vite 匯入前端使用。
* `import.meta.env.VITE_APP_TITLE` 在 Vue 組件內也可以用（例如設定標題）

---

## `.gitkeep` 小知識

`.gitkeep` 是為了讓空資料夾能被 Git 追蹤（因 Git 不會記錄空資料夾）

---

## 部屬小記

> * Vite + Vue 前端 → Netlify / Vercel
> * Express 後端 → Render / Railway

| 部署平台    | 適合用途          | 備註                   |
| ------- | ------------- | -------------------- |
| Netlify | 前端專案          | 免伺服器、適合 Vite、單頁應用    |
| Vercel  | 前端（支援 Nuxt）   | 支援 SSR、也能跑 Vue       |
| Render  | 後端 Express 專案 | 支援 Node.js + 資料庫整合部署 |


---

## package.json 的角色簡介

package.json：記錄目前專案的「套件清單、版本、執行指令、開發資訊」等，幾乎是專案的身份證。

---

## process.env.NODE_ENV 的用途

在後端 / Vite 開發中，常用來區分 dev / prod，例如：

```
if (process.env.NODE_ENV === 'development') {
  console.log('你在開發環境中');
}
```

---

## 常見 VSCode 套件

* Vetur 或 Volar（Vue 支援）
* Prettier - Code formatter
* ESLint
* Path Intellisense
* Auto Import
* Iconify IntelliSense（若使用 @iconify/vue）

---

## 專案結構總覽圖

```
📁 專案結構總覽（建議格式）：

vite-project/
├── public/
├── src/
│   ├── assets/
│   ├── components/
│   ├── plugins/
│   ├── styles/
│   ├── pages/ (搭配 unplugin-vue-router)
│   ├── layouts/ (搭配 vite-plugin-vue-layouts-next)
│   ├── router/
│   ├── composables
│   ├── utils （或 helpers/）
│   ├── services/
│   ├── store/ （或 pinia/）
│   ├── app.vue
│   └── main.js
├── .env
├── .gitignore
├── vite.config.js
├── package.json
└── index.js

```

---

## 常見 FAQ / 小提醒

| 主題                          | 建議補充內容                                                |
| --------------------------- | ----------------------------------------------------- |
| PrimeVue 表單搭配方式             | 你提到 `vee-validate`，可以簡列 `InputText` + `yup` 整合方式範例    |
| 環境變數 `.env`                 | 補充 `.env` 無法被前端讀取時可能是沒加 `VITE_` prefix                |
| `axios.defaults.baseURL` 寫法 | 補充「全局設定 baseURL」與「每次呼叫補上 baseURL」差異與時機                |
| pinia vs vuex 的簡略對照         | 若讀者背景是從 Vue2 來的話會常問                                   |
| 如何部署到 Vercel / Render       | 你最後雖有提，但可補個 1～2 句：「Netlify 適合純前端，Render 可接後端 Express」 |

---

## 常見錯誤對照表

| 錯誤訊息                       | 可能原因              | 解法                          |
| -------------------------- | ----------------- | --------------------------- |
| `CORS blocked`             | 前後端不同源            | 加 Vite proxy                |
| `Cannot find module 'vue'` | 沒有安裝 Vue          | `npm i vue`                 |
| `Cannot GET /api/...`      | Express 沒接收到      | 確認 app.get() 有設定、server 有啟動 |
| `404: router-view 沒顯示`     | 路由沒設好或 router 未註冊 | 確認 router 有 `.use()`        |

| 錯誤訊息                     | 原因                | 解法                        |
| ------------------------ | ----------------- | ------------------------- |
| CORS blocked             | 前後端不同 port        | 加 Vite Proxy              |
| Cannot find module 'vue' | vue 沒裝            | `npm i vue`               |
| router-view 沒顯示          | router 未註冊、路徑錯誤   | 確認 router 有 `.use()`、檔案存在 |
| .env 無效                  | 未加 `VITE_` prefix | 改為 `VITE_API_KEY=...`     |

---
