爆速Nuxt3導入

# はじめに
プロジェクトでNuxt3を採用することになったため、とりあえず開発できるように使いそうな機能等をメモ
理解編は別で投稿するかも

# 前提
- SSR
- 静的ファイルはAWS S3 + CloudFront, バックエンドはAWS Lambda, DBはRDS(postgresql)
- デプロイはCodeCommit + CodeBuild + AWS CLIでやるので、Serverless Frameworkは使用しない(今後検討するかも)

# インストール
```bash
npx nuxi@latest init <project-name>
cd <project-name>
npm i
npm run dev # 初期状態で開発サーバー起動
npm run build # ビルド
```

# 設定変更
AWS Lambda用に変更
```diff_typescript:nuxt.config.ts
export default defineNuxtConfig({
- devtools: { enabled: true }
+ nitro: {
+   preset: 'aws-lambda'
+ }
})
```

# ディレクトリ構成
```plaintext
/
 ├─ .output/      -- build時に出力されるファイル
 ├─ assets/       -- 共通のCSSなどを置く
 ├─ components/   -- 画面のパーツなどを配置するファイル
 ├─ layouts/      -- レイアウトを指定する
 ├─ pages/        -- ページを配置する これがあるとルーティングが有効になる
 ├─ public/       -- 静的ファイルを配置
 ├─ server/       -- バックエンドコードを配置
 ├─ app.vue
 ├─ buildspec.yml -- CodeBuildでデプロイする際の設定ファイル
 └─ nuxt.config.ts
```

# フロント側

## app.vue
`layout`、`pages`ディレクトリを使う場合は以下に変更する
```diff_vue
<template>
  <div>
-   <NuxtWelcome />
+   <NuxtLayout>
+     <NuxtPage />
+   </NuxtLayout>
  </div>
</template>

```

## カスタムコンポーネントの双方向バインディング
昔のVue3を少し触ってたことがあり、その頃から変わっていたので戸惑った
昔は`v-model` == `:value + @input`(※書き方による)だったが、
今は`v-model` == `:model-value + @update:model-value`


## Auto-imports
Nuxtでは、よく使いそうなNuxt APIやVue APIは自動でインポートされるので、import文を書かなくて良い

https://nuxt.com/docs/guide/concepts/auto-imports

## Composition API
NuxtというよりVue側の仕様
`<script setup>`と書くといい感じにしてくれる
変数や関数がバインドされ、`<template>`内で使用できる
ボイラープレートがめちゃくちゃ減ってHappy

## リアクティブ
`ref()`で変数に格納する
`ref()`はVueの機能で、これもNuxtでauto importされている

```vue
<template>
<div>
  <button @click="count++">+</button>
  {{ count }}
  <button @click="count--">-</button>
</div>
<template>

<script setup>
const count = ref(0)
</script>
```

`reactive()`もある(違いは未調査)

## ルーティング
Nuxtはファイルベースルーティング
pages以下に配置したファイルがそのままパスになる

<details><summary>ルーティング例</summary>

---
以下のようなディレクトリ構成にすると、
```plaintext
pages
 ├─ index.vue
 ├─ help.vue
 └─ details/
     ├─ detail1.vue
     └─ detail2.vue
```

以下のようなルーティングになる
```plaintext
/
/help
/details/detail1
/details/detail2
```
---

</details>

UIでルーティングする方法は主に2つ
1.`NuxtLink`を使う(nuxtっぽい方法)
```vue
<template>
<NuxtLink to="/hoge">to hoge</NuxtLink>
</template>
```
2.`navigateTo`を使う(vueっぽい方法)
```vue
<template>
<button @click="navigate">プログラムでページ遷移</button>
<button @click="() => navigateTo({path: '/fuga'})">遷移処理だけなら直接書いても良い</button>
</template>

<script setup lang="ts">
const navigate = () => navigateTo({path: '/hoge'});
</script>
```
NuxtLinkはデフォルトではリンクっぽい見た目になる
ボタンっぽい見た目の遷移UIを作りたいならnavigateToの方が楽かも？
(NuxtLinkをCSSでカスタマイズしてもいいかもしれないが)

### ページ遷移時の値の受け渡し
paramsを使いたかったがうまくいかなかった
一旦queryを使う

```vue
navigateTo({path: '', query: {id: 1}})
```

後で調べるメモ：キャッチオールルート、pages/404.vue

# バックエンド側
## API
`/server/api`ディレクトリに`hoge.ts`ファイルを置くと、`/api/hoge`にルーティングが割り当てられる
そうしたくない場合は、`/server/routes`ディレクトリに`hoge.ts`ファイルを置くことで`/hoge`にルーティングが割り当てられる
tsファイルは`defineEventHandler()`か`eventHandler()`を`export default`する必要がある
POSTのbodyを受け取る場合は以下

```typescript
export default defineEventHandler(async (event) => {
  const body = await readBody(event);
  console.log(body);
});
```

API側はダイナミックルーティングには対応していないが、ファイル名に`[]`をつけることで変数として受け取ることは可能？
つまり、`/server/routes/hoge[id]/fuga.vue`はできないが、`/server/routes/hoge/[id].vue`は可能？(要確認)

### APIの呼び出し(クライアント側)
`<script setup>`直下では`useFetch`を使う
ボタンクリック時のメソッド内など、レンダリング後に実行されるAPIは`$fetch`を使う
(理由はまだ調べてない。メソッド内で`useFetch`を使ったら開発者ツールのコンソールにwarningが出ていた)

### AWSにデプロイ後にPOSTメソッドで403になる
CloudFrontのビヘイビアでPOSTも許可する

### APIのレスが遅い
デフォルトのLambdaだとメモリが128MBで足りてない
512MBぐらいにすると許容範囲ぐらいになる
上げすぎても意味ない？

## DB接続
検証中

# その他
## ~~biome~~ Prettier / ESLint
biome使いたかったけど、まだvue対応してなかった...orz
Prettier / ESLint使います
~~linter兼formatter
※`npm i`時は`biome`じゃなくて`@biomejs/biome`を指定すること
　(`biome`は別のパッケージ)~~
```bash
npm i --save-dev @biomejs/biome
npx biome init # 設定ファイル生成
```

~~設定等はこちらを参照~~

~~https://zenn.dev/collabostyle/articles/86477d39be3a2e~~

~~同じPCで別プロジェクトもやっておりそちらはESLint/Prettierを使用している
使い分けは、VS Codeでワークスペース単位の設定をし、本プロジェクトではbiomeを使用するように設定
やり方はこちらを参照~~

~~https://blog.logical.co.jp/entry/2022/07/25/130000~~

# テスト
nodeは最新バージョンに上げること
古いの(v16.x)を使ってたせいで導入がうまくいかなくて時間を食ってしまった

前は公式が準備中みたいだったが、今はちゃんと書かれているのでこれに従う

https://nuxt.com/docs/getting-started/testing

https://vitest.dev/config/#exclude

## その他、未検証事項
今後更新するか、別の記事にしたい

### 状態管理(未検討)
爆速導入時点では考えなくてもいいかな...？

### バリデーション
v-text-field の props に rules を渡すことでバリデーションを実装できる？
zod入れる？
→zod入れる予定

### 認証
NuxtAuthを使う予定