Nuxt.jsでサイトマップを動的に設定する方法

Nuxt.jsでSSR対応のWebアプリケーションを作ったわいいが、サイトマップどうするん、しかも動的にルーティングしてる場合はと考えていたら、しっかりNuxt.js用のsitemapモジュールありましたね。

[sitemap-module](https://github.com/nuxt-community/sitemap-module)

今回はこれを使った動的なサイトマップを生成したときの話をします。

## 1．インストール

対象のNuxtフォルダにインストールしましょう

```bash
yarn add @nuxtjs/sitemap
```

## 2.　nuxt.config.jsの設定

インストールができたらnuxt.config.jsの設定をしていきます。
まずはmodulesに追加

```js:nuxt.config.js
modules: [
    '@nuxtjs/sitemap'
]
```

ここまではドキュメントと一緒ですね。

次にsitemapの設定をしていきます。

結論からいうとこういう設定にしました。

```js:nuxt.config.js
modules: [
    '@nuxtjs/sitemap'
],
sitemap: {
    path: '/sitemap.xml',
    hostname: 'https://example.jp',
    cacheTime: 1000 * 60 * 15,
    gzip: true,
    generate: false,
    exclude: [
      '/terms',
      '/contact/complete',
      '/register/complete',
      '/privacy-policy',
      '/mypage',
      '/admin',
      '/mypage/**',
      '/admin/**'
    ],
    routes() {
      return Promise.all([
        axios.get('https://example.jp/api/posts'),
        axios.get('https://example.jp/api/columns')
      ])
        .then(([posts, columns]) => {
          let exp01 = posts.data.map(contact => '/posts/' + contact.slug)
          let exp02 = columns.data.map(contact => '/columns/' + contact.slug)
          let array = [exp01, exp02]
          let flattened = array.reduce(
            (accumulator, currentValue) => accumulator.concat(currentValue),
            []
          )
          return flattened
        })
    }
}
```

オプションについてドキュメントから抜粋

## 3.　オプション

### path

サイトマップを生成する場所と名前の設定ができる

### hostname

サイトマップを置くサイトのルートドメインを設置する

### cacheTime

サイトマップの更新頻度を設定する

### gzip

gzip形式のsitemapを生成するかどうか

### generate

nuxt generateするときに静的なサイトマップを生成するかどうか

### exclude

除外ディレクトリの設定

/**を付けるとそのディレクトリ下を除外することが可能

ここから動的に設定した方法を説明していきます。

今回はNuxtおなじみのaxiosを使ってルーティングをしていきます。

nuxt.config.jsにaxiosを読み込みます。

```js:nuxt.config.js
const axios = require('axios')
module.exports = {
  mode: 'universal',
  ...
}
```

読み込んだら、routesを設定していきます。

```js:nuxt.config.js
routes() {
    return Promise.all([
        axios.get('https://example.jp/api/posts'),
        axios.get('https://example.jp/api/columns')
    ])
    .then(([posts, columns]) => {
        const exp01 = posts.data.map(contact => '/posts/' + contact.slug)
        const exp02 = columns.data.map(contact => '/columns/' + contact.slug)
        const array = [exp01, exp02]
        const flattened = array.reduce(
        (accumulator, currentValue) => accumulator.concat(currentValue),
        []
        )
        return flattened
    })
}
```

今回Rest apiからaxiosでゲットしています。
それぞれ、id,slugなどルーティングの仕方は様々だと思うのですが、今回はslugでのルーティングです。

```json
// post
[
    { id: 0, slug: 'post01' },
    { id: 1, slug: 'post02' },
    { id: 2, slug: 'post03' }
]
// column
[
    { id: 0, slug: 'column01' },
    { id: 1, slug: 'column02' },
    { id: 2, slug: 'column03' }
]
```

こんな配列をgetしました。

これを今度はルーティングの設定に合わせるために整形していきます。

```js
// /posts下を動的にサイトマップを生成したい
let exp01 = posts.data.map(contact => '/posts/' + contact.slug)
// columns下を動的にサイトマップを生成したい
let exp02 = columns.data.map(contact => '/columns/' + contact.slug)
```

これでさきほどの配列がこうなります。

```json
// posts/
[
    '/posts/post01',
    '/posts/post02',
    '/posts/post03'
]
// columns/
[
    '/columns/column01',
    '/columns/column02',
    '/columns/column03'
]
```

ここからこの二つの配列を結合します。

```js
const array = [exp01, exp02]
const flattened = array.reduce(
    (accumulator, currentValue) => accumulator.concat(currentValue),
    []
)
```

これでこうなります。

```json
[
    '/posts/post01',
    '/posts/post02',
    '/posts/post03',
    '/columns/column01',
    '/columns/column02',
    '/columns/column03'
]
```

あとはreturnをして出力すれば完了です。
これで動的にルーティングがされます。

## まとめ

自動的に動的にルーティングしてくれたら最高なのに

今回nuxt.config.jsに直接ルーティングの処理を設定したが、storeとかで管理してもいいと思いました。

他にもっといい方法があると思うので、別方法も教えてください。

【参考にした記事】

[Nuxt.jsで静的ファイル生成時にサイトマップも自動生成する方法](https://qiita.com/bucchi49/items/d271c4010a3f6c900926)