ビルド時にAPIを静的化するジェネレータを自作しましたので、ご紹介です。(コード有りです。)
Nuxtのジェネレータを自作中...。
— 新田聡一郎 (@soichiro_nitta) 2019年2月11日
・Airtableでマークダウン
・Nuxtビルド時にJSON生成
・link rel="prefetch"にjson追加
・ルート生成
・コンポーネントからは/_nuxt/xxx.jsonにリクエスト
って感じで出来たんだけど、爆速なんだが! pic.twitter.com/DvJL5hucGq
最近はやりのヘッドレスCMSをやっていこうと思ったのですが、APIのリクエスト制限きびしいんですよね...。
現状だとNuxtは静的generateモードでも、ページ遷移時にリクエストが発生してしまうので、完全に静的化してしまう必要がありました。
以下のような流れになります。
- Nuxtビルド時にJSONを生成
-
<link rel="prefetch">
にJSONを追加 - ルート生成
- コンポーネントからは
/_nuxt/articles/xxx.json
にリクエスト
(<link rel="prefetch">
の指定で、生成したJSONは前もって準備するようにしています。)
ジェネレータの中身は以下。
import axios from 'axios'
module.exports = function generateModule(moduleOptions) {
this.nuxt.hook('build:before', async ({ app }) => {
// 全データを取得
const { data } = await axios.get('/hogehoge')
const posts = data
// JSONを生成
this.options.build.plugins.push({
apply(compiler) {
compiler.plugin('emit', (compilation, cb) => {
posts.forEach(post => {
compilation.assets[`articles/${post.slug}.json`] = {
source: () => JSON.stringify(post),
size: () => {}
}
})
cb()
})
}
})
// link rel="prefetch"にJSONを追加
const url = this.options.dev ? '' : 'https://xxx'
this.options.head.link = [
...this.options.head.link,
...posts.map(post => ({
rel: 'prefetch',
href: `${url}/_nuxt/articles/${post.slug}.json`
}))
]
if (this.options.dev) return
// ルート生成
this.options.generate.routes = posts.map(post => `/${post.slug}`)
})
}
こんな感じにモジュールを書いて、nuxt.config.js
で設定します。
module.exports = {
// ジェネレータ内で開発orプロダクションの書き分けに使用しています
dev: process.env.NODE_ENV !== 'production',
// モジュールを指定
modules: ['~/modules/generator'],
...
}
コンポーネントからは以下のようにデータを取得します。
<script>
export default {
async asyncData({ app, params }) {
const url = process.env.NODE_ENV === 'development' ? '' : 'https://xxx'
const { data } = await app.$axios.get(
`${url}/_nuxt/articles/${params.id}.json`
)
return { article: data }
}
}
</script>
これで表示・遷移時ともにサーバーへデータ取得のリクエストを送らずにすむようになりました😙
こちらの情報を参考にさせていただきました。
Firebase、Flamelink、Nuxt、Netlify、PWAを使ってJAMstackなブログを作る