【Nuxt.js2】入門してみたまとめ 📝

Nuxtのインストール方法は省略します。[公式](https://develop365.gitlab.io/nuxtjs-2.8.X-doc/ja/guide/installation/)を参考にしてください。
`create-nuxt-app`を叩いて、質問される内容に答えていく形です。

## フォルダ構成

|フォルダ名|概要|
|-|-|
.nuxt|ビルドフォルダ（自動生成）|
components|コンポーネント用|
dist|ビルド後のフォルダ|
node_modules|各種ライブラリ|
pages|ページ（自動ルーティング）|
static|robots.txtやfaviconなど|
store|Vuex用|
nuxt.config.js|Nuxt設定ファイル|
package.json|npm設定ファイル|

## オートインポート機能

Nuxt v2.13から追加されたcomponentを自動でimportする機能。
nuxt.config.js内の`components: true`の場合、componentsフォルダ内のvueファイルが自動でインポートされる。
v2.15からcomponentsフォルダ内にフォルダがある場合、フォルダも記載する。

例)
components
└ base
　　└ Header.vue

`<BaseHeader />`でコンポーネントを呼び出せる

フォルダ名を省略する場合はnuxt.config.jsを下記のように編集すると省略できる

```nuxt.config.js
components: {
    dirs: [
        '~/components', 
        '~/components/base'
    ],
},
```

`<Header />`でコンポーネントを呼び出せる

## レイアウトのカスタマイズ

`$ npm run dev`を走らせて、コンパイルすると.nuxtフォルダが生成される。
.nuxtフォルダにlayouts/default.vueがあり`<Nuxt />`で/pagesで作成するファイルが描画されている。

```.nuxt/layouts/default.vue
<template>
 <Nuxt />
</template>
```

レイアウトを編集したい場合は、プロジェクト直下にlayouts/default.vueを作成することで、それがデフォルトレイアウトとして/pages配下の全ページで読み込まれる。

```default.vue
<template>
  <div>
    <hr />
    defaultのレイアウトだよ
    <hr />
    <Nuxt />
  </div>
</template>
```
![スクリーンショット 2022-11-12 17.48.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/5ea47904-ae6a-1b84-bb15-7ef5307d3423.png)

ページによって別のレイアウトを使用したい場合は、layouts内でdefault.vueとは別で新しくvueファイルを作成し、呼び出したい/pagesファイルでそのlayoutsファイルをexport内で指定する。

例)
layouts
├ default.vue
└ blog.vue　→ 追加
```layouts/default.vue
<template>
  <div>
    <hr />
    ブログ用のレイアウトファイルで作成してるよ
    <!-- 下記Nuxtコンポーネントの記述は必須 -->
    <hr />
    <Nuxt />
  </div>
</template>
```

pages
├ index.vue
└ blog.vue　→ 追加

```pages/blog.vue
<template>
  <div>ブログページ</div>
</template>

<script>
export default {
  layout: 'blog', // layoutsディレクトリ直下のファイル名を記述してレイアウトの指定
}
</script>
```

blogページでのみ、指定したlayoutsファイルが読み込まれる
![スクリーンショット 2022-11-12 18.01.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/fe64c718-c4cc-61be-42d7-7ccec0a29e47.png)

## ライフサイクル（asyncData,fetch）

vueと比較し、render以前のタイミングで何個かフックが追加されている。
大きな変更としてasyncData,fetchが挙げられるがfetchが引数の有無によって実行されるタイミングが変わりわかりづらかったので、取り上げる。

画像は[Nuxt.jsビギナーズガイド](https://lab.astamuse.co.jp/entry/2019/05/29/114500)から拝借 👏🏻
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/2e822c31-0d4d-efc3-2c29-0c1c92900df3.png)

それぞれの実行タイミング

```js
export default {
  asyncData() {
    console.log('asyncData')
  },
  created() {
    console.log('created')
  },
  fetch() {
    console.log('fetch')
  }
}
```

![スクリーンショット 2022-11-12 18.27.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/3bdc86e7-fb31-3052-4217-27174e5eee9e.png)

fetch()に引数を入れた場合
```js
export default {
  asyncData() {
    console.log('asyncData')
  },
  created() {
    console.log('created')
  },
  fetch(context) {
    console.log('fetch')
    console.log(context.route)
  },
}
```

下記の通り、fetch()で引数があった場合の実行タイミングはcreated()より前 👀
![スクリーンショット 2022-11-12 18.37.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/a1e87bd7-6f2c-ef93-616b-862bf73caa9b.png)

## context
contextはNuxtで用意されている引数で様々な情報が格納されているオブジェクト。
公式にある通り、Nuxt ライフサイクル内で使用できる。
[公式：context](https://nuxtjs.org/ja/docs/internals-glossary/context/)

> context は、Nuxt から Vue コンポーネントに追加のオブジェクト/パラメータを提供し、asyncData 、fetch 、plugins 、middleware そして nuxtServerInit のような特別な Nuxt ライフサイクル内で使用できます。

分割代入でも使用できる。

```js
export default {
  fetch({ route }) {
    console.log('fetch')
    console.log(route)
  },
}
```

route以外にもstore,redirect,quety,app,$axiosなど様々なキーがあるので、適宜必要なものだけ分割して使用すれば良さそう。

## Middleware

[公式:ミドルウェアディレクトリ](https://nuxtjs.org/ja/docs/directory-structure/middleware)

>middleware ディレクトリには、アプリケーションミドルウェアが含まれています。ミドルウェアを使用すると、ページまたはページのグループ（レイアウト）をレンダリングする前に実行できる、カスタム関数を定義できます。

ページが表示される前に実行される処理を記述できる機能。
ログイン済みのユーザーかどうか確認する、といった際によく使用される。
contextオブジェクトを使用できる。

プロジェクトルート直下にmiddleware/*.jsを作成することでNuxt側で自動的に解釈してくれる。
全てのページで使う場合は、nuxt.config.jsにmiddlewareを追記。
一部のページで使う場合は、そのページファイル内に`middleware: 'ミドルウェア名'`を記載。
呼び出し順はnuxt.config.js → layouts → pages

例) 全ページで使用
middleware
└ middlewareCheck.js　→ 追加

```middlewareCheck.js
export default function ({ route }) {
  console.log('middlewareCheck')
  console.log('middleware:', route.name)
}
```

nuxt.config.jsにミドルウェア追加
```nuxt.config.js
export default {
  ~~略~~
  router: {
    middleware: 'middlewareCheck',
  },
  ~~略~~
}

```

asyncData()などよりも前に実行される。
nuxt.config.jsに記載したので、全ページで発火している。

![スクリーンショット 2022-11-12 22.13.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/1aa67ccb-5cd3-1d5f-dc93-30e858a759ef.png)

例) 任意のページで使用。sampleとして/pages/blogで読み込んでみる。
layouts
├ default.vue
└ blog.vue　→ ミドルウェア追記

```blog.vue
<template>
 ~~略~~
</template>

<script>
export default {
  middleware: 'middlewareCheck', // 追記
}
</script>
```

blogページでのコンソール。
nuxt.config.jsにも記載してあるまま +  /pages/blog.vueで追記しているので2回コンソールされている。
![スクリーンショット 2022-11-12 22.22.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/aa92200d-a79a-a9f1-1a18-0b3a7e2890c3.png)

ログインしていないとリダイレクトさせる、といった時のコード例
```middleware/auth.js
export default function({redirect, store, route}) {
  const user = store.state.user
  if(!user && route.path !== '/login') {
    redirect('/login')
  }
}
```

## plugins(dayjs)

その名の通り、様々な機能を追加して使える機能。
プロジェクトルート直下にplugins/*.jsを作成することでNuxt側で自動的に解釈してくれる。
nuxt.config.jsの`plugins: []`に追記していくことで、そのプラグインが使用できるようになる。
サンプルとして[dayjs(日付を表示)](https://day.js.org/docs/en/installation/node-js)というライブラリを使用してみる。
プロジェクトルートで`$ npm install dayjs --save `
インストールが終わるとpackage.jsonの中にdayjsが追加される。

![スクリーンショット 2022-11-12 22.40.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/bf0249dd-6b65-771e-f29a-e87a19cbe802.png)

/node_modulesにもdayjsディレクトリが追加されている。
今回は日本時間に合わせるので、/node_modules/dayjs/locale/ja.jsを使用する。
![スクリーンショット 2022-11-12 22.42.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/4415d796-7b7c-f2e5-f930-c007763c25ee.png)

[公式：プラグインディレクトリ](https://nuxtjs.org/ja/docs/directory-structure/plugins)

> $root とコンテキストの挿入
ときどき、アプリケーション内で関数や値を利用できるようにしたい場合があります。これらの変数を Vue インスタンス（クライアントサイド）、コンテキスト（サーバーサイド）、さらには Vuex ストアに挿入できます。これらの関数の前に $ を付けるのが慣例です。
Nuxt はこれを簡単に行うための inject（key、value メソッドを提供します。関数をエクスポートするとき、2 番目のパラメーターとして Inject が指定されます。$ は、キーの先頭に自動的に追加されます。

公式のサンプルコードを参考に今回のdayjsを置き換えてみる。

例）
plugins
└ day.js　→ 追加

```day.js
import 'dayjs/locale/ja'  // 今回使用する日本時間をnode_modulesから読み込み
import dayjs from 'dayjs' // dayjs本体の読み込み

dayjs.locale('ja') // 日本時間に設定

export default ({ app }, inject) => {
  inject('dayjs', (string) => dayjs(string)) // injectの第一引数は$接頭辞で使えるようになる引数名を記載
}

```

nuxt.config.jsにプラグイン追加し使える状態になる
```nuxt.config.js
export default {
  ~~略~~
  plugins: ['@/plugins/dayjs'],
  ~~略~~
}

```

/pages/index.vueでdayjsプラグイン使用してみる。
```index.vue
<template>
  <div>
    <BaseHeader />
    {{ now }}
  </div>
</template>

<script>
export default {
  data() {
    return {
      now: null,
    }
  },
  mounted() {
    this.now = this.$dayjs().format('YYYY-MM-DD HH:mm:ss')
  },
}
</script>
```
![スクリーンショット 2022-11-12 23.08.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/0a6528cd-9410-cd72-6cc5-36bc4de96fee.png)

## modules

Nuxt起動時に呼び出される。ビルド時に読み込んだり、ビルドの動きを変えたい場合に使用。
Pluginsとの比較として、Pluginsは$rootやcontextから呼び出して使用するのに対して、
modulesはNuxt起動時に呼び出されるので、Nuxt全体に影響を与える。

[Explore Nuxt Modules](https://modules.nuxtjs.org/)をみるとNuxtで使用できるモジュールがたくさんあることがわかる。

他の機能と同様に、プロジェクトルート直下にmodules/*.jsを作成しnuxt.config.jsに追記することで使用できる。
nuxt.config.jsでは二箇所記載できる箇所があり、都度使い分ける。
```nuxt.config.js
export default {
  // 開発限定拡張機能はbuildModulesに記載。
  buildModules: [],
  // 本番環境でも実行する機能はmodulesに記載。
  modules: [],
}
```

実際にmodules追加してみる。
例)
modules
└ example.js　→ 追加

```example.js
export default function () {
  console.log('moduleのテスト')

  this.nuxt.hook('ready', async (nuxt) => {
    console.log('Nuxt is ready')
  })
}

```

nuxt.configにmodules追記
```nuxt.config.js
export default {

  buildModules: [
    ~~略~~
    '@/modules/example', // 追記
  ],
  modules: [
    '@nuxtjs/axios',
  ],

}
```
ターミナルで、`$ npm run dev`で起動してみると
readyフックによって、Listeningの前に実行されていることがわかる。
![スクリーンショット 2022-11-12 23.28.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/24065e4a-86aa-2681-b7ca-6fb73880ebfc.png)

modulesのフックはたくさんあり、今回はNuxtの準備完了時に実行されるreadyを使用しているが、[公式:モジュールディレクトリ](https://nuxtjs.org/ja/docs/directory-structure/modules)から確認して適宜必要なフックを使い分ける。

> Ready : Nuxt は動作する準備ができています（ModuleContainer とレンダラの準備ができます）。

modulesの中で使用されるthisは少し役割が違うらしい 🤔

> this: モジュールのコンテキストです。すべてのモジュールは、ModuleContainer インスタンスのコンテキスト内で呼び出されます。

## assets

画像やcssを置いておくディレクトリ。

例)
assets
├ images
　　└ xxx.jpg
└ css
　　└ style.css

上記ディレクトリ構造での画像呼び出し例
`<img src="~/assets/image/xxx.jpg">`

cssを使用する場合はnuxt.config.jsに追記する
```nuxt.config.js
export default {
    css: ['@/assets/css/style.css'],
}
```

## まとめ

Nuxtに入門した際の基本的なポイントをまとめてみました✍🏻
modulesに関しては使用するイメージがあまりできなかったですが、割と上級者向けの機能だという認識で頭の片隅に置いておきます..。
今回は基本的な内容になっていますが、実務で実際に自分が躓いたポイントなど、継続的に更新していきたいと思います🫡