Nuxt.js で静的ファイルの生成時に自動でサイトマップを生成する方法

commits4 min read読了の目安(約3900字

はじめに

Nuxt.js のプロジェクトで動的にサイトマップを生成する機会があったので、一通り試してまとめみました。静的ファイルを生成(nuxt generate コマンドを実行)するとエクスポートされたディレクトリに sitemap.xml を生成できます。

モジュールのインストール

今回は下記の公式が提供しているモジュールを使いました。

https://sitemap.nuxtjs.org/

基本的には、こちらのモジュールを読み込んで、細かい設定を nuxt.config.js に定義していくといった流れです。下記が雛形です。

$ yarn add @nuxtjs/sitemap
nuxt.config.js
export default {
  modules: [
    '@nuxtjs/axios',
+   '@nuxtjs/sitemap'
  ]
}

複数のモジュールを使用する場合は、上記のようにサイトマップのモジュールを最後に記述する必要があります。

あとは任意でカスタマイズしたい場合は設定を追加していくだけです。

nuxt.config.js
export default {
  modules: [
    '@nuxtjs/axios',
    '@nuxtjs/sitemap'
  ],
+  sitemap: {
+    // options: ここに追記していく
+  }
}

オプション

それでは続いてカスタマイズしたい項目について使ったものだけピックアップして紹介します。

hostname

サイトの URL を記載します。SPA, SSG では指定が必須となっているので忘れずに定義しましょう。

nuxt.config.js
export default {
  sitemap: {
+   hostname: 'https://example.com'
  }
}

dotenv モジュールなどを利用して環境変数から値を取得できる状態になっていれば、ベタ書きするよりも process.env.BASE_URL としておいた方が良いでしょう。

path

続いては、サイトマップを吐き出すパスを指定します。デフォルトだと ./sitemap.xml になっているのでそのままでいい場合は特に設定する必要はありません。

nuxt.config.js
export default {
  sitemap: {
    hostname: 'https://example.com'
+   path: 'custom-sitemap.xml'
  }
}

defaults

サイトマップの設定値のデフォルトとなるパラメータを定義します。複数のサイトマップを生成したい場合などはここにまとめることができるので非常に便利です。

設定できるパラメータについて詳しく知りたい方は、下記に詳細なパラメータがリストアップされているのでそちらをご覧ください。

https://github.com/ekalinin/sitemap.js/blob/4.1.1/README.md#sitemap-item-options

今回は、サイトマップの最終更新日時(lastmod)や更新頻度(changefreq)を設定してみました。

nuxt.config.js
export default {
  sitemap: {
    hostname: 'https://example.com'
    path: 'custom-sitemap.xml',
+   defaults: {
+     lastmod: new Date(),
+     changefreq: 'daily'
+   }
  }
}

exclude

サイトマップから除外したいパスを定義します。良くあるケースとしては、管理者ページなどのログイン後のページについては除外したいことが多いのではないでしょうか。

nuxt.config.js
export default {
  sitemap: {
    hostname: 'https://example.com'
    path: 'custom-sitemap.xml',
    defaults: {},
+   exclude: ['/admin/**', '/tmp']
  }
}

routes

配列、あるいはオブジェクトで定義します。明示的にパスを指定したい場合は、このオプションを使用します。

nuxt.config.js
export default {
  sitemap: {
    hostname: 'https://example.com'
    path: 'custom-sitemap.xml',
+   routes: ['first', 'second', 'third']
  }
}

また、記事詳細(/articles/:id)などの動的なファイルパスは生成されないので API などを使って取得する必要があります。その場合もこのオプションが役に立ちます。

以下は、/v1/articles というエンドポイントで記事の一覧が取得できる API からデータを取得した場合の例です。

nuxt.config.js
+ import axios from 'axios'

export default {
  sitemap: {
    hostname: 'https://example.com'
    path: 'custom-sitemap.xml',
+   routes: async() => {
+     const { data } = await axios.get('api.example.com/v1/articles')
+     return data.map((article) => `/articles/${article.id}`)
+   }
}

ユースケース

複数のサイトマップを生成したい場合

sitemaps というオプションを使って配列で複数のサイトマップを定義できます。

nuxt.config.js
export default {
  sitemap: {
    hostname: 'https://example.com'
    path: 'custom-sitemap.xml',
+   sitemaps: [
+     { path: 'first.xml, routes: ['first'] },
+     { path: 'second.xml, routes: ['second'] }
+   ]
  }
}

複数の API を叩いてデータを取得したい場合

API からのデータ取得は routes オプションを使うと良いと前述しましたが、複数のエンドポイントを対象にした場合も同様です。

下記のように Promise.all を使って全ての Promise が返されるまで待機するようにすると実現できます。

nuxt.config.js
+ import axios from 'axios'

export default {
  sitemap: {
    hostname: 'https://example.com'
    path: 'custom-sitemap.xml',
+   routes() {
+     return Promise.all([
+       axios.get('api.example.com/v1/articles'),
+       axios.get('api.example.com/v1/tags')
+     ]).then(([articles, tags]) => {
+       const urls = []
+       articles.map((article) => urls.push(`/articles/${article.id}`))
+       tags.map((tag) => urls.push(`/articles/tags/${tag.id}`))
+       return urls
+     })
+   }
}

まとめ

サイトマップを自動で生成するための方法についてまとめてみました。URL のパスには id や名前などの動的なデータを使っている場合があるので、それにも対応できるように試してみました。Jamstack なサイトだったり、API をバックエンドに持った静的サイトの場合は今後も重宝する気がしています。