nuxt generateの動的なルーティングの書き出し
VueNuxt.js の動的なルーティングの静的ページ書き出しというか、
routes()
がいまいちよくわかってなかったのでメモ。
サンプルページでは "/fruits/" 配下に "_item.vue" を設置して、動的なルーティングにした。
その中で "/fruits/apple/", "/fruits/orange/", "/fruits/banana" の 3 つを静的ページとして新たに書き出し、直接アクセスできるようにした。
また、404 ページも作成した。
静的書き出し
Nuxt.js には nuxt generate
コマンドがあって、pages 配下に置いた ".vue" ファイルを、静的なコンテンツとして出力してくれる。
でも、動的なルーティングは無視してしまう。
吐き出された index.html から、nuxt-link
を通して動的なルーティングにアクセスすることは可能だけど、それらは index.html から切り替えたものなので、 "fruits/orange/" などに直接アクセスしようとしても、index ページが存在しないためアクセスできない。
routes()について
書き出しの設定は、"nuxt.config.js" 内にある generate
で行うことができる。
その中で、動的なルーティングを書き出すための設定もある。
ルート / のみが Nuxt.js によって生成されます。動的なパラメーターを用いたルートを生成させたい場合は、動的なルーティングの配列をセットする必要があります。
動的なルーティングの配列は、routes
という項目に追加する。
"/fruits/apple/", "/fruits/orange/", "/fruits/banana" の 3 つを生成する場合、
nuxt.config.js
const fruitsList = require('./data/fruitsList.json')
// 〜〜〜 省略 〜〜〜
generate: {
routes() {
return fruitsList.items.map(item => {
return `fruits/${item.id}`
})
}
}
アイテム一覧を json
などから取得し、ページ名とパスをくっつけて格納した配列を作成するだけ。
APIから取得する
Headless CMS などで、API から取得する場合も同じ。
例えば Contentful API(と SDK)を用いて、 "/pages/posts/_slug.vue" の動的なルーティングを書き出しする際の設定はこんな感じになる。
nuxt.config.js
generate: {
routes() {
return client.getEntries({
'content_type': 'blog',
}).then(entries => {
return entries.items.map(entry => {
return `posts/${entry.fields.slug}`
})
})
}
},
でもこの方法には問題がある。
「API から叩いた値を配列に入れる」のと、「"/pages/posts/_slug.vue" で値を参照して API を叩く」で同じ API を何度も叩くことになるため。
そこで、entry の値を payload として一緒に返す。
nuxt.config.js
generate: {
routes() {
return client.getEntries({
'content_type': 'blog',
}).then(entries => {
return entries.items.map(entry => {
return {
route: `posts/${entry.fields.slug}`,
payload: entry
}
})
})
}
},
すると、書き出し時、"/posts/_slug.vue" に payload が渡される。 あとは asyncData の引数に「payload」を追加すれば OK。 静的書き出し時のみに渡されるので、ある時とない時で処理を分ける必要がある。
pages/page.vue
async asyncData({ route, app, store, payload }) {
if (payload) {
const item = payload // entryの値が入ってる
return item
}
/* 以下、静的書き出しじゃない時の処理 */
}
404ページを出力
Nuxt.js は、layouts フォルダに "error.vue" を作成することでエラーページが作れる。
そのファイルは静的書き出しの時に "200.html" として生成されるけど、generates オプションの fallback
を true か "404.html" にすることで、かわりに "404.html" を生成できる。
nuxt.config.js
generate: {
fallback: true,
routes() { // 以下略
firebase のデフォルトは "404.html" なので、これを一緒にデプロイすれば、無効なルーティングでもリダイレクトされるようになる。