111
102

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2019-06-25

ビルド時に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なブログを作る

111
102
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
111
102

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?