Nuxt.jsについて学習したことメモ

## 目次
1. Nuxt.jsとは
2. Nuxt.jsの基本

## 今回の学習のゴール
- Nuxt.jsとは何か、何ができるかを知る
- 実際の使い方について知る

## 1. Nuxt.jsとは

> NuxtはVueの公式ガイドラインに沿って強力なアーキテクチャを提供するように設計されたフレームワークです。
[はじめに - NuxtJS](https://ja.nuxtjs.org/guide/)

- Vue.jsのパワーアップ版とも言える
- 特徴 / 機能
    - Vueファイル(`*.vue`)で記述できる
    - サーバーサイドレンダリング(SSR)
        - Vue SSRというサーバーサイドレンダリングライブラリが組み込まれており、サーバー側で表示をレンダリングしてクライアントに送ることができる
        - シンプルに構成されたシングルページアプリケーション(SPA)では、サーバーはファイルを配信するだけで、画面を組み上げるための処理はクライアント側で行う
    - データ管理
        - [Vuex](https://vuex.vuejs.org/ja/)というVue.jsのデータ管理ライブラリが組み込まれており、アプリケーション全体のデータやそのデータを利用した処理を管理できる
        - それぞれが独立しているコンポーネントのデータを一元管理できる
    - ルート管理
        - Vue Routerというルート管理ライブラリが組み込まれており、アドレスが割り当てられた新たなページを簡単に作成し追加できる

## 2. Nuxt.jsの基本

### プロジェクトの作成

```console
$ npx create-nuxt-app nuxt-app    # nuxt-appというプロジェクトを作成

# 以下の質問に回答する
? Use a custom server framework    # サーバーサイドのフレームワークを選択
? Use a custom UI framework    # UIフレームワークを選択
? Use a custom test framework    # テスティングフレームワークを選択
? Choose rendering mode     # Universal（サーバーサイドレンダリング）またはSPAを選択
? Use axios module    # HTTPリクエストを簡単に行うためのモジュールの有無を選択
? Use eslint    # 保存時にJavaScriptのコードをチェックするためのツールの有無を選択
? Use prettier    # 保存時にJavaScriptのコードを整形するツールの有無を選択

$ npm run dev    # 開発環境でプロジェクトを実行すると「http://localhost:3000」でアプリケーションが起動する
```

### ディレクトリ構造
- プロジェクトの実行によって生成されたnuxt-appフォルダの中身はざっと以下の通り
    - フォルダ
        - assets : アプリケーションで使うスタイルシートやJavaScriptファイルなどを配置する
        - components : コンポーネントファイルをまとめる（コンポーネントで asyncDataやfetchを使用できない）
        - layouts : レイアウトファイルを格納する（ex. サイドバー）
        -  middleware : ミドルウェアと呼ばれるプログラムを配置する（ミドルウェアを使って、ページやレイアウトをレンダリングするよりも前に実行されるカスタム関数を定義できる）
        -  static : 変更されない可能性の高いファイルを格納する（ex. favicon）
        -  node_modules : プロジェクトで使用するパッケージ類がまとめられている
        -  pages : 各ページ用のファイルをまとめる
        -  static : イメージファイルなどを保管する
        -  store : Vuexストア（データを管理するためのファイル）を格納する
    - ファイル  
        - .editorconfig : エディターの設定情報
        - nuxt_config.json : Nuxt.jsのカスタム設定を記述（headプロパティにはメタタグを定義すr）
        - package.json : npmのパッケージを管理する
        - package-lock.json : npmが利用するファイル
        - README.md

### レイアウト
- 画面全体の基本的なレイアウトは、layoutsディレクトリで管理
- レイアウトをベースにして、この中に各ページのコンテンツが組み込まれている
- プロジェクトを作成するとデフォルトで`default.vue`が作られる

```vue:layouts/example.vue
<template>
  <nuxt />    <!-- コンポーネントをレンダリング(Nuxt.jsのコンテンツ表示に関する部分) -->
</template>

<style>
/* 省略 */
</style>
```

### ページ
- アプリケーションの各ページのコンテンツは、pagesディレクトリ内にまとめられており、ファイル名（`*.vue`） がそのままアドレスのパスになる
- プロジェクトを作成するとデフォルトでトップページ`pages/index.vue`が作られる

```vue:pages/example.vue
<template>
  <section class="container">
    <div>
      <logo />
      <h1>{{title}}</h1>
      <p>{{message}}</p>

      <!-- 省略 -->
    
    </div>
  </section>
</template>

<script>
import Logo from '~/components/Logo.vue'

export default {
  components: {
    Logo
  },
  data: function(){
    return {
      title: 'Hello NuxtJS!',
      message: 'this is message'
    }
  }
}
```

### ルーティング
- pagesディレクトリ内のVueファイルの木構造に沿って、自動的にvue-routerが設定される

```
pages/
--| user/
-----| index.vue
-----| one.vue
--| index.vue
```
```
router: {
  routes: [
    {
      name: "index",
      path: "/",
      component: 'pages/index.vue'
    },
    {
      name: "user",
      path: "/user",
      component: "pages/user/index.vue"
    },
    {
      name: "user-one",
      path: "/user/one",
      component: "pages/user/one.vue"
    }
  ]
}
```

### 非同期なデータ
- asyncDataメソッド
    - SSRを実装するためのNuxt.js独自のメソッド
    - コンポーネントがローディングされる前に`asyncData`が呼び出され非同期の処理を行う
    - サーバーサイドでは1回だけ（Nuxt アプリへの最初のリクエスト）呼び出され、クライアントサイドではページ遷移をするたびに呼び出される
    - Promiseを返す方法とasync/awaitを使用する方法がある
        - async/awaitを使用する方法では、axiosを使用する
        - axiosとは
            - ブラウザおよびnode.js用のPromiseベースのHTTPクライアントのこと
            - HTTP通信を行うためのJavaScriptのライブラリである
            - APIを使う必要があるときなどにaxiosを使用すると便利に実装することができる
            - Nuxt.jsでは簡単にaxiosを導入できるaxios-moduleがある

```vue:Promiseを返す方法
<template>
  <h1>{{ title }}</h1>
</template>

<script>
export default {
  asyncData ({ params }) {
    return axios.get(`https://my-api/posts/${params.id}`)    // axios.getでAPIを呼び出す
      .then((res) => {    // thenメソッドは、Promiseのインスタンスの状態がfulfilled（処理が成功）となったときに実行する関数を登録する
        return { title: res.data.title }    // axios.getで取得したデータがdataに格納される
      })
  }
}
</script>
```
```vue:async/awaitを使用する方法
<template>
  <h1>{{ title }}</h1>
</template>

<script>
import axios from "axios"

export default {
  async asyncData ({ params }) {
    const { data } = await axios.get(`https://my-api/posts/${params.id}`)    // awaitは、asyncData関数の実行を一時停止し、Promiseの処理結果が返ってくるまで待つ
    return { title: data.title }    // axios.getでAPIを呼び出し取得したデータがdataに格納される
  }
}
</script>
```

### モジュール
- コア機能を簡単に拡張できるようにするため、モジュールシステムが導入されている
- 関数をnpmモジュールとしてパッケージングしたり、プロジェクトのソースコードに直接インクルードする（別のファイルに記述された内容を追加する）ことができる
- `nuxt.config.js`でプロジェクトで特定のモジュールをロードする設定（以下は例）

```vuejs:nuxt.config.js
export default {
  modules: [
    // Doc: https://bootstrap-vue.js.org
    "bootstrap-vue/nuxt",
    // Doc: https://axios.nuxtjs.org/usage
    "@nuxtjs/axios"
  ]
}
```

### コマンド
- package.jsonに以下のような記述しておくことで`npm run <command>`経由でNuxt.jsのコマンドを実行することができる
    - ex. `npm run test`

```json:package.json
{
  "scripts": {
    "dev": "nuxt",
    "build": "nuxt build",
    "start": "nuxt start",
    "generate": "nuxt generate",
    "test": "jest",
    "prettier": "prettier --write ./{components,layouts,middleware,pages,plugins,store,test}/**/*.{js,vue}"
  }
}
```


## 参照
- [はじめに - NuxtJS](https://ja.nuxtjs.org/guide/)
- 『Vue.js&Nuxt.js超入門』秀和システム