Nuxtでビルド時にAPIを静的化して、完全にサーバーへのリクエストをなくすト

ビルド時にAPIを静的化するジェネレータを自作しましたので、ご紹介です。(コード有りです。)

最近はやりのヘッドレスCMSをやっていこうと思ったのですが、APIのリクエスト制限きびしいんですよね...。

現状だとNuxtは静的generateモードでも、ページ遷移時にリクエストが発生してしまうので、完全に静的化してしまう必要がありました。

以下のような流れになります。


  • Nuxtビルド時にJSONを生成


  • <link rel="prefetch"> にJSONを追加

  • ルート生成

  • コンポーネントからは /_nuxt/articles/xxx.json にリクエスト

<link rel="prefetch"> の指定で、生成したJSONは前もって準備するようにしています。)

ジェネレータの中身は以下。


modules/generator.js

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 で設定します。


nuxt.config.js

module.exports = {

// ジェネレータ内で開発orプロダクションの書き分けに使用しています
dev: process.env.NODE_ENV !== 'production',

// モジュールを指定
modules: ['~/modules/generator'],

...
}


コンポーネントからは以下のようにデータを取得します。


pages/_id.vue

<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なブログを作る