Nuxt.jsの始め方

Nuxt.jsを始めたい方に向けて、導入の仕方をまとめます。
ライフサイクルなど細かい内容は公式ドキュメントをご確認ください。

# 前提条件
- npmの5.2.0以降のバージョンがインストールされていること

# インストール
プロジェクトディレクトリの作成

```shell
$ mkdir test && cd $_
```

Nuxt.jsフレームワークのインストール

```shell
$ npx create-nuxt-app
```

# 開発
開発サーバーを起動

```shell
$ npm run dev
```

# デプロイ

SSRモードでサーバーを起動

```shell
$ npm run build && npm run start
```

静的HTML生成

```shell
$ npm run generate
```

# その他

## pug/stylusの導入

### pug
pugのモジュールをインストール

```shell
$ npm i --save pug pug-loader pug-plain-loader
```

全*.vueファイルの`template`タグに`lang="pug"`を追加する

```html:*.vue
<!-- <template> -->

<template lang="pug">
```

### stylus
stylusのモジュールをインストール

```shell
$ npm i --save stylus stylus-loader
```

全*.vueファイルの`style`タグに`lang="stylus"`を追加する
ここの内容を他のスタイルに影響させたくない場合は`scoped`も追加する

```html:*.vue
<!-- <style> -->

<style lang="stylus" scoped>
```

## グローバルCSS（stylus）の導入

リソース用モジュールをインストール

```shell
$ npm i --save stylus stylus-loader @nuxtjs/style-resources
```

stylファイルの作成

```shell
$ mkdir assets/style && touch assets/style/reset.styl assets/style/variables.styl
```

nuxt.config.jsでモジュールの読み込み、stylファイルの読み込みを記述

```javascript:nuxt.config.js
module.exports = {
  modules: [
    '@nuxtjs/style-resources'
  ],
  css: ['~/assets/style/reset.styl'],
  styleResources: {
    stylus: ['~/assets/style/variables.styl']
  }
}
```

リセットスタイルを定義

```css:reset.styl
*
*:before
*:after
  box-sizing border-box
  margin 0
```

変数を定義

```css:variables.styl
textColor = #f00
```

*vueファイルで変数を使用する

```html:*.vue
<style lang="stylus">
div
  color textColor
</style>
```

## storeの導入

### データ定義
store用のファイルを作成

```shell
$ touch store/index.js
```

保持しておきたいデータをstate内に`counter`という名前で定義
state内の`counter`の数値を1ずつ増やす`increment`メソッドを定義

```javascript:store/index.js
export const state = () => ({
  counter: 0
})

export const mutations = {
  increment (state) {
    state.counter++
  }
}
```

### データへのアクセス
state内のcounterの値を取得

```javascript
this.$store.state.counter
```

出力結果

```javascript
0
```

### データの変更
mutations内のincrementメソッドを実行

```javascript
this.$store.commit('increment')
```

## transitionタグ
### html（pug）の定義
`transition`タグを追加して、子要素は`v-if`などで存在確認をさせる

```html
transition
  p(v-if="show") Hello world!
```

### css（stylus）の定義
`v-enter`と`v-leave-to`で最初（出現時）と最後（消失時）の`style`を定義
そのスタイルにどういう`transition`をかけるか`v-enter-active`と`v-leave-active`で定義

```css
.v-enter-active
.v-leave-active
  transition opacity .5s

.v-enter
.v-leave-to
  opacity 0
```

## ページ遷移transition
### html（pug）の定義
`nuxt-link`タグを追加する

```html
nuxt-link(to="/test/") go to test!
```

### css（stylus）の定義
`page-enter`と`page-leave-to`で最初（出現時）と最後（消失時）の`style`を定義
そのスタイルにどういう`transition`をかけるか`page-enter-active`と`page-leave-active`で定義

```css
.page-enter-active
.page-leave-active
  transition opacity .5s

.page-enter
.page-leave-to
  opacity 0
```

## ページ読み込み時のLoading表示
Loading用のファイルを作成

```shell
$ mkdir components/Loading && touch components/Loading/index.vue
```

```html:components/Loading/index.vue
<template lang="pug">
.loading-page(v-if="loading")
  p Loading...
</template>

<script>
export default {
  data: () => ({
    loading: false
  }),
  methods: {
    start () {
      this.loading = true
    },
    finish () {
      setTimeout(() => {
        this.loading = false
      }, 3000)
    }
  }
}
</script>

<style lang="stylus" scoped></style>
```

```javascript:nuxt.config.js
module.exports = {
  loading: '~/components/Loading/index.vue' // 追記
}
```

## テンプレートレイアウト変更
テンプレート用のファイルを作成

```shell
$ touch layouts/another.vue
```

```html:layouts/another.vue
<template lang="pug">
.l-another
  nuxt
</template>

<script>
export default {}
</script>

<style lang="stylus" scoped></style>
```

```javascript:*.vue
export default {
  layout: 'another', // 追記
}
```

## エラーページ
エラー用のファイルを作成

```shell
$ touch layouts/error.vue
```

```html:layouts/error.vue
<template lang="pug">
.container
  h1(v-if="error.statusCode === 404") ページが見つかりません
  h1(v-else) エラーが発生しました
  nuxt-link(to="/") ホーム
</template>

<script>
export default {
  props: {
    error: {
      type: Object,
      default: null
    }
  }
}
</script>

<style lang="stylus" scoped></style>
```

## コンソールの削除
build内にdrop_consoleの記述を追加

```javascript:nuxt.config.js
module.exports = {
  build: {
    terser: {
      terserOptions: {
        compress: { drop_console: true }
      }
    }
  }
}
```

## 作業ディレクトリをまとめる
作業ディレクトリの作成、移動

```shell
$ mkdir src && mv assets components layouts pages plugins static store middleware src/
```

```javascript:nuxt.config.js
module.exports = {
  srcDir: 'src/', // 追記
}
```

# 参考文献

この記事は以下の情報を参考にして執筆しました。

- [Nuxt.js](https://ja.nuxtjs.org/)