nuxt-composition-apiを使えるようにする
2020-07-13
azblob://2022/11/11/eyecatch/2020-07-13-nuxt-composition-api-000.jpg

「Nuxt.jsはいいぞ」って画像です。

完全に個人的な話ですが、Kingdom Hearts Union χ Dark Roadがリリースされ、キングダムハーツが咽び泣くほど好きな僕はめちゃめちゃ楽しんでいます。社会人になって、お金を学生の頃より自由に使えることと、短い時間でも楽しめ、放置もできるソシャゲのありがたさに感激しています。

でもスマホがえげつないくらい熱を持つので、いつか爆発するんじゃないかと思っています。あと、最近クイズの勉強もしていないですね……。

そんな個人の近況は置いといて、今日はみんな大好きNuxt.jsの話です。

Nuxt.jsのロゴ。真ん中の三角形(?)があまり好きじゃない。

前置き

Class APIがVue3.0で採用されない代わりに、Composition APIが採用されましたね。これの利点は、関数としてロジックを切り出せるために再利用しやすくなったり、ロジックごとにデータやメソッドをまとめられたりすることですね。

さて、Vue3.0がそのような方針になるにあたって、当然Nuxt.jsでもComposition APIが使えます。もちろん、@vue/composition-apiを使うのもいいのですが、Nuxtのv2.13.0のリリースノート

Also don't miss nuxt/content and nuxt-composition-api ;)

https://github.com/nuxt/nuxt.js/releases/tag/v2.13.0

とあるのですから、nuxt-composition-api を使ってみようではありませんか(nuxt/contentの記事も書きたいですね)。なお、Composition APIそのものの機能については今回の記事では解説していません(別記事を書く予定です)。

nuxt-composition-apiの中身を見る(フロントエンド開発者向け)

ごめんなさい、使ってみようとか言った矢先ですが、まず @vue/composition-api と何が違うのかを見ていきましょう。というのも、なぜ@vue/composition-api ではダメなのか? となるからです。その肝心の中身は、

export {
  computed,
  createComponent,
  createElement,

  ...

  unref,
  watch,
  watchEffect,
} from '@vue/composition-api'

となっています。ほとんどは @vue/composition-api からの流用になっていますね。このexport分の上部で、nuxt-composition-api 独自の部分として、

export { useAsync } from './async'
export { defineComponent } from './component'
export { useContext, withContext } from './context'
export { useFetch } from './fetch'
export { globalPlugin, onGlobalSetup } from './hooks'
export { useMeta } from './meta'
export { ssrRef, shallowSsrRef, setSSRContext, ssrPromise } from './ssr-ref'
export { useStatic } from './static'

をexportしています。例えば useAsync は、従来のNuxt.jsでいうところの asyncData みたいな使い方ができます。defineComponent@vue/composition-api でできることに加えて、vue-meta も含まれており、head() を使ってメタ情報を記述することができます。

import { defineComponent, useAsync } from "nuxt-composition-api"
import axios from "axios"

export default defineComponent({
  // defineComponentがhead()をサポートしている
  head() {
    title: "Sample title"
  },
  setup() {
    // useAsyncを使うと、レンダリングされる前にデータをフェッチできる
    const authors = useAsync(() => axios.get("/api/author"))

    return { authors }
  }
})

Vue.jsにはなく、従来のNuxt.js(Options API)での記法をComposition APIで使うためにも、nuxt-composition-api を利用することは必須ですね(型情報も@vue/composition-api からexportされています)。

さくっと使うための環境を構築しよう

まず適当なディレクトリを作成し、npx create-nuxt-app をします。この時点でnuxt-composition-api は入っていないので、npm i nuxt-composition-api をしてインストールします。

これだけだと怒られるので、nuxt.config.js のほうに

{
  buildModules: [
    "nuxt-composition-api"
  ]
}

を追記します(buildModulesはデフォルトであると思います)。

これで npm run dev をしても怒られません! 早速してみましょう(今回名前は TechBlog.Environment.NuxtCompositionApi という長い名前になっています)。

Documentation と GitHub があまりにも小さい。

後は試しに、index.vue をこんな感じにいじってみましょう。

<template>
  <div class="container">
    <p>{{ info.text }}</p>
    <button @click="onClicked">ボタン</button>
  </div>
</template>

<script lang="ts">
import { defineComponent, reactive } from "nuxt-composition-api"

export default defineComponent({
  head: {
    title: "Sample"
  },
  setup() {
    /*
      data() {
        return {
          text: ""
        }
      }
    */
    const info = reactive({
      text: ""
    })

    /*
      created() {
        this.text = "まだ押されていません"
      }
    */
    info.text = "まだ押されていません"

    /*
      methods: {
        onClicked() {
          this.text = "押されたよ!"
        }
      }
    */
    const onClicked = () => {
      info.text = "押されたよ!"
    }

    return { info, onClicked }
  }
})
</script>
押すとテキストが変わるというシンプルなもの

これで Nuxt.js でも Composition API を使った開発ができるようになりました。やったね!

終わりに

Class-basedなNuxt.jsも悪くないのですが、やっぱり従来の書き方に近いComposition APIのほうが個人的には好きですね。ただ自由度が高くなった分、「Reactで良くね?」「Vueの良さをつぶしてる」などといった意見もあります。

どっちにしても、大規模開発に(ReactやAngularほど)向いていないといわれていたVue・Nuxtがタフになったので、Vue愛好家としては嬉しい限りです。

それではまた!