「SSRと規約だけ」の勘違いを解く、 Nuxt.js をプロジェクトで採用すべき理由

back check 事業部に業務委託でコミットしているフロントエンドエンジニアの potato4d です。

ROXX では、 v1.0 が出る前から、プロダクト、コーポレートサイト、ランディングページ、メディアなど、多くのシーンにて、 Nuxt.js が採用されています。

Nuxt.js は多くの人に愛される一方で、最近は Vue 3.0 の話もあり、多少評価が落ち着いてきた印象があります。

この記事では、十分に普及した今だからこそ、 Nuxt.js の本当の優位性と、どういったときに使うべきか。あるいは使うべきでないかを再度言語化できればと思います。

SSRとルールだけ」という勘違い

まずは Nuxt.js の採用についてです。多くの場合、「Vue か Nuxt か」という問いには、いかが判断基準として使われます。

  • SSR 今必要かどうか
  • Nuxt.js の組み込みのルールをチームに適用したいかどうか

これは確かに Nuxt.js を採用する一つの理由ではありますが、実際にはこれだけではありません。

Nuxt.js は、 Vue.js の延長ではなく、 Vue.js の機能をよりよいアプローチで提供しているフレームワークとして、機能面でいくつかの大きな価値があります。

これから順を追って紹介していきますが、それらの判断軸について考えた上で、全てが不要な場合に限り Nuxt.js を利用しない選択肢が出てくるのではないかと思います。

Vue.js プロジェクトにおける Nuxt.js 選定の基準

SSR が今必要なのかどうか、Nuxt.js のいわゆる「規約」について採用したいかどうかは既に知られていると思うので、それ以外について言及します。

プロジェクトが将来的に SSR エンジンを利用する可能性があるか

まずは言及される「SSRするかどうか」。です。

SSRをするときにのみ Nuxt.js をすべき」という言説について、一部は正しいですが、一部は誤りがあります。

例えば「個人個人のデータを扱うアプリみたいな Web サービスだから必要ない」といった場合などです。ここで伝えたいのは、 SSR の是非を考えるさい、多くの場合は「開発開始時点の要件」で考えられがちということです。

しかし、実際は後から必要になることも多くあります。

例えば

  • 「サービスのトップにおいて、初回の応答速度を可能な限り高めたい」
  • 「求人の URL を貼ると API のデータを基に OGP とページタイトルがプレビューされてほしい」
  • 「個人のワークスペースを持つメモアプリだけど URL での限定共有がほしい」

などが上げられます。こういったシチュエーションにおいて、開発開始時点での要件だけをみると、 SSR は不要には見えるのではないでしょうか。しかし、実際にはこういったケースは頻発します。

このようなシチュエーションにおいて、あとから SSR をするのは非常にコストの高い作業となります。

簡単なものでいうと、暗黙的に window オブジェクトに依存したコードがある。ライフサイクルフックの選定をサボって全てが mounted になっている。というのは既存プロジェクトの SSR 対応を担当したことがあるかたは経験したことがあるはずです。

現代では、SSRを要求されるシチュエーションは非常に多くなっているため、Universal なコードであることを前提とした上で、本番環境を SSR するかどうかという判断軸を持つことが重要です。

一方で、「そのユーザーのログインコンテキストに依存して外部に絶対に何もでないアプリケーション」みたいなものがあれば、それは SPA 前提で問題ありません。

例えば社内向けの管理画面は、ログイン画面などのごく一部を除き、ログインが不要なエンドポイントは現実的に存在し得ないため、SSR は不要といえます。

なお、nuxt generate についても、こちらは内部的に SSR を行っておりますので、「最終的には静的サイトなので SPA モードで問題ない」というわけではないことをご留意ください。

Node.js サーバーの運用が可能かどうか

また余談として、Node.js サーバーが立ち上がるということもしっかりと認識しておくべきです。

これは SSR する場合に付随してくるほか、Nuxt.js の serverMiddleware や Node.js からの Nuxt.js 利用が発生する場合に考慮すべき事項です。

SSR というとサーバーが必要でランニングコストがかかるという部分はフロントエンドエンジニアの多くの共通認識になっています。しかし、運用という観点は忘れられがちではないでしょうか?

Nuxt.js を利用していると、SSR は勿論、その他でも Node.js 上で動かすことがそれなりに発生します。ただコンピューティングリソースを利用するというだけでなく、例えば以下のような問題にも対処が必要であるという認識を持った上で、自分たちが Node.js サーバーを運用できるかを考える必要があります。

  • Node.js ランタイムの追従 (常に LTS に追従できるか?1,2年サイクルでメジャーバージョンをあげられるか)
  • セキュリティ問題への対処 (脆弱性のあるパッケージがより無視できない問題となる)
  • メモリリーク・サーバースケーリングへの対処

これらを意識するのが難しい場合、Nuxt.js を採用する場合であっても SSR については忘れることを推奨します。

Context / Inject によってコードをクリーンに保ちたいか

あまり話に挙がりづらいですが、 Nuxt.js が独自のプラグイン構造を持っていること、そしてそれが強力であることも認識する必要があります。

Nuxt.js には、 Plugin という概念が存在します。これは、これまで Vue.js プロジェクトにおいて、自分たちで作っていた Vue.use を吸収するレイヤーによく似ています。例えば Bootstrap Vue や Element UI を import して Vue.use していたような層がここにあたります。

しかし、 Nuxt.js の Plugin の価値はそれだけにとどまりません。Nuxt.js の Plugin は、 Vue.js の Provider / Inject をうまく隠蔽し、 Context として活用できるという大きな優位性があります。

聞き慣れないワードも多いかもしれませんが、身近な例としては、 Axios Module が this.$axiosapp.$axios で呼び出せるあの機能です。

Axios Module の抽象化粒度が良いかどうかは諸説ありますが、「コンポーネントやストアから特定の外部依存を切り出せる」ということには、大きな価値があります。

具体的には、コンポーネントのテストを書く場合のシチュエーションなどにおいて、以下のように記述できるという利点があります。

import TheUserEditForm from '~/src/components/TheUserEditForm.vu'
import { shallowMount } from 'vue-test-utils'

const $axios = {
  async get() {
    return {
      data: {
        foo: 'bar'
      }
    }
  }
}

describe('~/src/components/TheUserEditForm.vue', () => {

  test('Submit form', () => {
    const wrapper = shallowMount(TheUserEditForm, {
      mocks: {
        $axios
      }
    })
    // Code
  })
})

多くの場合こういった記述が全く不要というわけではないので、Nuxt.js を利用したほうがシンプルに取り回せます。

反対に、こういった優位性が不要なシンプルな Web サイトの場合、同様に静的サイト出力が可能な Gridsome などが選択肢に上がってくる可能性もあります。

ここも判断軸として加えると良いでしょう。

選定にあたってあまり重要ではないこと

Routes の自動生成と layout

Nuxt.js の大きな特徴として、ファイルシステムと密接に紐付いた Routes が挙げられます。

これは、非常に便利な機能ではありますが、 Nuxt.js のみが唯一もつというわけではありません。Nuxt.js スタイルの Routes について、 Vue CLI v3.x or higher が利用可能なvue-auto-routing というパッケージにて代替が可能となっています。

これは日本人の Vue.js コアチームメンバーの ktsn によって開発されており、今もアップデートが続いています。

この機能自体は便利ですが、意思決定に関わるようなものではありません。

Vuex 連携

これも非常に便利な機能ですが、 Single Source of Truth への評価が落ち着いてきた現代においては、大きなポイントとはならないのではないでしょうか。

実際に ROXX では、新規でのコードにおいては Vuex を利用しないケースも多くなっていきています。

このあたりは現場にあわせて効果が変わる部分であるため、あまり大きな要因とは言えません。

おわりに

Vue 3.0 が既にインストール可能となり、 TypeScript との親和性や Composition API による新記法などに期待と注目が集まっています。

その大きな変化をうけて、 Nuxt.js がどうなっていくか、単純な Vue.js プロジェクトで十分となるかは非常に気になるトピックではあります。

しかし、Nuxt.js には、目先の生産性やSSRだけではなく、高品質なプロジェクトの基盤を持っていること、そして、より高品質な基盤を自分たちで作り上げていくための土壌が存在しているという大きな価値があります。

この記事が現場における Nuxt.js の妥当性について再度考えるきっかけとなれば幸いです。