Nuxt 2系 → 3系?　Nuxt Bridgeとは？

Vueに続いて、Nuxtも3系がリリースされましたね。

VueがだんだんReactっぽくなっていっている気がしてなりません。
Vue3系はtsとの相性が良くなったと聞くのにいまだにts触れていません...
Vueすら3系に上げてないのに、Nuxtなんでまだ調べられていないよ、という人！
一緒に確認していきましょう！


### 既存のNuxt 2 プロジェクトについて

既存のNuxt 2 プロジェクトに関しては、Nuxt Bridgeを経由してNuxt 3 にUpgradeすることを公式が強く推奨しています。また、動作に関してもNuxt 3 よりもNuxt Bridgeの方が安定していることを公式が発表しています。（2021-12-15 現在）

ですので、既存のNuxt 2 プロジェクトに関しては、Nuxt Bridgeで動作を確認しながら、Nuxt 3系が安定してきたらUpgradeするのが良いかもしれませんね。

### Nuxt Bridgeとは？

Nuxt Bridgeとは、Nuxt 3 の準備をするversionのようなものです。
Nuxt Bridgeでは Vue 2系を使用することができ、なおかつNuxt 3 で搭載されたNitro Engineを使用することができます。下記の表にあるように最小の変更でNuxt 3 の新機能の恩恵を受けることが出来ます。



![スクリーンショット 2021-12-15 21.28.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608770/af867fa7-d4df-8a7e-7bde-5bda18850578.png)


### Nuxt 3 の新機能について !!

ようやくここからNuxt 3 で新搭載された機能や、Nuxt 3 で推奨されている使い方について書いていきたいと思います。

#### Nitro Engineによる軽量化と高速化、Nuxt 内部での API 作成

サーバーエンジンであるNitro Engineの開発によって、Nuxt 3 はNuxt 2　に比べて、最大75倍？1/75？の軽量化に成功したそうです。また、h3 を使用し、サーバーミドルウェアを読み取ることでサーバーAPIを作成できるようになりました。（server/api, server/middleware）
そして、本番環境ではbuildする際にアプリとサーバーを１つの./outputディレクトリに書き出され、軽快に動作します。

#### Vue 3 とTypeScript

Nuxt 2 まではVue 2 でしたが、Nuxt 3 はVue 3 をサポートしており、JavaScriptではなく、TypeScriptが推奨されております。デフォルトでアプリを作成した際もTypeScriptが採用されています。


#### ディレクトリ構成

![スクリーンショット 2021-12-15 22.04.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608770/e6269f4f-d2da-6b07-9274-b92e9b917a16.png)


ディレクトリ構成は上記の画像の通りです。ご覧の通り、デフォルトでTypeScriptが採用されています。Nuxt 2 から変更があった主な点は以下です。

・static フォルダが public フォルダに変更
・内部 API 実装用として server ディレクトリが新しく追加
・Composition API 用のコンポジション関数(Composition Function)を格納するフォルダとしてcomposables フォルダが新しく追加


#### API関連で追加された２つのメソッド

Nuxt 3では下記の２つのメソッドが追加されました。
これらのメソッドはsetup関数内、もしくはLifecycle Hooks内で動作します。

・useAsyncData
・useFetch

1つずつ見ていきましょう。


#### useAsyncData

useAsyncDataはNuxt 3 から実装されたNuxt内部に作られたAPIを非同期で呼び出す際に使用するメソッドです。

```js
const {
  data: Ref<DataT>,
  pending: Ref<boolean>,
  refresh: (force?: boolean) => Promise<void>,
  error?: any
} = useAsyncData(
  key: string,
  fn: () => Object,
  options?: { lazy: boolean, server: boolean }
)
```

引数は、

・key：データ取得がリクエスト間で適切に重複しないようにするための固有キー
・fn：値を返す非同期関数
・options
　　・default：非同期関数が解決する前に、データのデフォルト値を設定するファクトリ関数
　　・server：サーバーサイドでデータを取得するかどうか。デフォルトはtrue
　　・transform：解決後のfnの結果を変更するために使用できる関数
　　・pick：fnの結果から、この配列の指定されたキーのみを取り出す
　　・lazy：ナビゲーションをブロックするのではなく、ルートをロードした後に非同期関数を解決するかどうか。デフォルトはfalse

ーー　公式　ーー
lazy: falseは、データがフェッチされる前にルートのロードをブロックするために使用します。lazy: trueより迅速なユーザーエクスペリエンスのために、代わりに読み込み状態を使用して実装することを検討してください。
ーーーーーーーー
とのことですので、spinner等を用いてLoadingであることを明示的にすることが必要になってきます。


一方、戻り値は、

data（非同期関数の結果）
pending（データがまだフェッチされているかどうかを示すbool値）
refresh（データの更新を強制的に行うために使用できる関数）
error（データの取得に失敗した場合に返される）


下記はテストコードです。


```js:server/api/count.ts
let counter = 0
export default () => {
  counter++
  return JSON.stringify(counter)
}
```


```js:app.vue
<script setup>
const { data } = await useAsyncData('count', () => $fetch('/api/count'))
</script>
 
<template>
  Page visits: {{ data }}
</template>
```

#### useFetch
ページ、コンポーネント、プラグインでは、useFetchを使用して任意のURLからデータを取得できます。基本的には外部APIを呼ぶために使用されます。

```js
const {
  data: Ref<DataT>,
  pending: Ref<boolean>,
  refresh: (force?: boolean) => Promise<void>,
  error?: any
} = useFetch(url: string, options?)
```

利用可能なオプションは$fetchのオプションとKeyです。

key：カスタムキーを提供する
ohmyfetch（$fetch: https://github.com/unjs/ohmyfetch ）のオプション
　　・method：リクエストメソッド
　　・params：クエリパラメータ
　　・headers：リクエストヘッダー
　　・baseURL：リクエストのベースURL

下記はテストコードです。

```js:app.vue
<script setup>
const { data } = await useFetch('/api/count')
</script>

<template>
  Page visits: {{ data.count }}
</template>
```


### まとめ

Nuxt 2 と比べると大幅に変更している分、Nuxt Bridgeがあって助かったという印象です。
Vue 3＆Composition API, TypeScriptがネイティブサポートされ、Nuxt 2 を使ってきた人にとっては学習することが多くなりがちですが、TypeScriptでの型指定やComposition APIでcomposableディレクトリを用いて分割しながらコードを書いていくことで、コードの読みやすさ等の向上、チーム開発のスピードアップになるかなと思います。

まずは、Nuxt 2 のプロジェクトをNuxt BridgeにUpgradeしてNitro Engineを体感してみたいと思います。



#### 参考

・https://v3.nuxtjs.org/
・https://re-engines.com/2021/11/22/nuxt-3-beta/