Vue.js & Nuxt.js から React & Next.js へ移行した理由

nuxt-to-next

はじめに

2021 年から React ベースのフレームワークである Next.js を本格的に学び始めました。
昨年 2020 年は Vue.js ベースのフレームワークである Nuxt.js にどっぷりと使った1年であり、昨年リリースした キカガク (kikagaku.ai) など、本運用に乗せるところまでプロダクト開発チームで学びながら進めていきました。
その昨年に1年間もかけて知見を貯めた Vue.js & Nuxt.js を離れて、React & Next.js へ移行した背景を紹介します。

TL;DR

まず結論からお伝えすると、Vue/Nuxt と比較して React/Next には、以下2つの大きな利点がありました。
  • React 系のライブラリや Vercel といったエコシステムの成熟度の高さ
  • 個人開発を超えたレベルの内容に対する技術記事の豊富さ
ただし、ここで早まらずに興味を持っていただければ、この記事を最後まで読んでみてください。
今回の結論はあくまで『将来のキカガクにとって』のものであり、個別に最適化された結論は異なるはずです。
個人としての開発体験では React/Next の方が圧倒的に良いのですが、チームの開発体制から変えないといけません。
こういった現実的な制約条件を考えると、キカガクも Nuxt → Next へと体制を移行していくためにも最低でも1年以上の期間が必要であり、それらを学べる環境の整備など多くの労力が必要となります。
その間に新しい選択肢が登場するかも知れません。
技術選定というものは、このような複数の要因を検討して意思決定しないといけません。
そのため、今回は結論よりも、その技術選定の意思決定の決め手になった要因をストーリー仕立てでの背景と理由付きで紹介していきます。
多くの方の正しい意思決定のヒントや判断材料になれば幸いです。

移行したチームの体制

この記事のタイトルでは Vue.js / Nuxt.js => React/ Next.js に移行したように書いていますが、厳密にはチームの開発体制も含めて大幅に変更しています。
これまでの体制
  • プログラミング言語:JavaScript / TypeScript
  • UI ライブラリ:Vue.js
  • フレームワーク:Nuxt.js
  • ホスティング:Firebase Hosting
  • バックエンド一式:Firebase
  • 外注:デザイン、HTML/CSS/JavaScript のフロント箇所コーディング
  • CSS:通常の CSS(外注)
これからの体制(変更点太字)
  • プログラミング言語:JavaScript / TypeScript
  • UI ライブラリ:React
  • フレームワーク:Next.js
  • ホスティング:Vercel
  • バックエンド一式:Microsoft Azure
  • 外注:デザインのみ
  • CSS:Tailwind CSS

Vue.js / Nuxt.js

調査編

まずは、Vue/Nuxt を採用していた背景です。
創業してから3年が経つ、2019 年までキカガクとしてはプロダクトを一切持っていませんでした。
技術の会社である以上、プロダクトを作りたいのは山々でしたが、プロダクトを持つビジネスモデルは資本力との関係性が強く、ある程度の資本力を持てるようになるまではやりたい気持ちを抑えると決めていました。 そんな中、順調に3年間成長をすることができ、ついにチャレンジしていこうと動き始めました。
まず、初めのアイディアは KIKAGAKU でした。
KIKAGAKU | AI を無料で学べる学習サイト
最先端の AI 技術を最短距離で学べるキカガク運営の学習サイトです。
URL:https://free.kikagaku.ai/
プロダクト開発のノウハウが乏しい中、いきなりビジネス化は踏み込みすぎだと感じ、まずは無料で学べるチュートリアルサイトを作るといったマイルストーンから始めました。
当時、Web アプリケーションを作るとなると PythonDjango や、RubyRuby on Rails といった バックエンド(サーバーサイド) で実行するプログラミング言語を採用した方法しかノウハウがありませんでした。
調べてみると、最近では JavaScript を中心にしたエコシステムが出来上がっており、JavaScript も 2015 年に刷新されて、JavaScript にを追加で定義できる TypeScript と組み合わさってからは、本格的な開発に十分利用可能という結論が出ました。
2019 年後半のネットの記事を見ても Vue/Nuxt にバックエンドとして Firebase を採用した個人開発の記事が多く、確かにこっちがトレンドだなと感じます。
その一方で、Vue.js が普及するよりもっと前から普及していた React はどうか?と当然調べます。
しかし、調べてみると、React の書き方がなにか無駄に複雑そうに感じます。
今でこそ、実際に書いて慣れてみればそんなことはないのですが、React 系の記事は JSX と呼ばれる記法を採用しているために、初学者にはちょっと見慣れないものになってしまいます。
いま思えばの一言
Visual Studio Code (VSCode)ESLintPrettier を導入すれば、全然気になることもなくなるのですが...と当時の私に教えてあげたいです...。
見た目の親和性を気にしていたということもあり、実際に Vue.js ベースと React ベースのコードを比較してみました。
Python や Ruby などバックエンドでの書き方に慣れているキカガクチームにとっては、HTML, CSS, JavaScript の 3 つがしっかり分離されている Vue.js ベースの方が親和性が高く、これは Vue.js 一択だなと思いました。
逆に、React ベースの全てが混在している書き方は絶望的だと感じましていました(今となっては心地よいの一言)。
React は私が本格的に Ruby on Rails で Web アプリケーション開発をしていた 2016 年から、すでに浸透していたのに対して、Vue.js はそれ以降から注目を集めているという点では React ベースの悪いところを改善したものに違いない(実際そうです)と思い、新しい物を使うことに対して、特に抵抗はありませんでした。
いま思えばの一言
React も React Hooks の登場で新しい書き方に刷新され、昔知っている React よりも遥かに良くなっていることに気づきませんでした。
このようにこれまで学んできた書き方との親和性が決め手になり、Vue.js を JavaScript の UI ライブラリとして、Nuxt.js を Web アプリケーションフレームワークとして採用することになりました。

JavaScript の学び直しから

Vue.js の本で学ぼうとし始めたのですが、JavaScript の知識が古すぎて、Vue.js がわからないのか JavaScript がわからないのかが早々に行方不明になってしまいます。
そこで、まずは JavaScript の学び直しからです。
JavaScript は ECMAScript として 2015 年に大幅なアップデートが行われており、ちょっと前の JavaScript で止まったままの人も多いかも知れません。
簡単な違いでいうと、定数に const、変数に let を使用して、変数の var は基本的に使わなくなりました。
今でも var が使われている記事に遭遇するため、そういった記事は少し古いものと認識するのがひとつの目安かも知れません(あくまで目安です)。 また、クラスが追加されたり、よく使うものとしてはアロー関数が登場しています。
この辺りの時点でつまづいた場合は、以下の記事が簡単にまとまっており、すぐにキャッチアップできるので、この記事の後に読んでみてください。
最初こそ新しい書き方などに戸惑ったものの、分かりやすい資料を見つけて手を動かしていけば、実用に持っていくまでは、そこまで時間がかかりませんでした。
1〜2日程度で大体のキャッチアップが完了しました。
その後、以下の本で Vue.js の基礎に関してキャッチアップしました。
しっかりと基本を押さえられるようにたくさん書いてあるのですが、実践する前に多くの機能を押さえてもあまり学びの効率が良くありません。
体験談として、繰り返し (for)条件分岐 (if) の書き方さえ押さえれば、あとは参考書を片手に小さく実践した方が良かったなと反省しています。
以下の参考書であれば最初の 20% ぐらいで終えられる内容です。

簡単なところから実践しよう

これは Vue/Nuxt にせよ React/Next にせよ、新しく学び始めた人におすすめの学び方ですが、小さな Web サイトをそれぞれの Web アプリケーションフレームワークに置き換えてみることです。
ちょうどその頃にキカガクのホームページの刷新も手がけており、外注している凄腕デザイナーの方にデザインだけでなく、HTML, CSS, JavaScript の見た目に関するコーディングを行っていただいていました。
ここを Vue/Nuxt ベースに少し変更するだけの簡単な作業でしたが、初めての経験であるため意外とたくさん躓き、良い経験となりました。
Nuxt ではコンポーネント単位で分けることができるため、1枚のページになっている Web ページは修正したい該当箇所が探しにくかったのが解決できて使い勝手が良いなと感じていました。
ただ、今思うと、当時はコンポーネントという概念を勘違いしていたことに後々気づきます。
フォルダの中にファイルを管理するぐらいで思っており、確かにコンポーネントに分けてはいるのですが、CSS や JavaScript などは 1 つのファイルにまとめてグローバルで読み込むといった方法をとっていました。
別にこれでも実行することができるのですが、フロントエンドをベースとした開発で得られるパフォーマンスアップからは程遠いものになっていきます。
この辺りから コード分割(code splitting) なども気にするきっかけの1つになりました。
後悔することは悪いことではなく、成長するために必要な気づきの階段です。
だからこそ、多少パフォーマンスが悪くても問題とならないコーポレートサイトから始めて改善を試みてみるなど、実践の機会を作り出すことが最高の学びに繋がりました。

SSG / SSR という選択肢

Python や Ruby といったバックエンド系のプログラミング言語を Web アプリケーション開発で採用した場合には、ユーザーからのリクエストが来ると、サーバー側で必要なデータを集めて HTML/CSS/JavaScript 内に埋め込み(ビルド)、それをユーザー側に返してブラウザでレンダリングしています。
したがって、サーバーがないと Web サイトも Web アプリケーションも作れないということが当たり前になっています。
それに対して、JavaScript をベースとした Vue.js や React では、手元やサーバー上で一度ビルドしてしまえば、あとは静的なファイルとしてホスティングしておくだけで、Web サイトや Web アプリケーションを構築することができます。
これはブラウザ上で動作できる(ほぼ)唯一の言語である JavaScript を利用するとても大きなメリットです。
もちろん静的ファイルをホスティングするためにもサーバーが必要ではあるのですが、最近では GitHub PagesVercel, Netlify などのサービスで無料で利用できるようになっています。
いまの キカガク のコーポレートサイトなどは GitHub Page で管理されているため、無料で稼働しています。
GitHub 上にソースコードをアップロードして管理しておけば、GitHub Actions でビルドを行い、ビルド後のファイルを GitHub Pages で無料公開できるといった素晴らしい環境が整います。
個人利用の範囲ではかなり使い込まない限りは無料で利用でき、これらのエコシステムを使う開発が少しずつメジャーになってきました。
静的ファイルにビルドしてしまう方法を Static Site Generation (SSG) と呼び、リクエストがある度にサーバー側でビルドして結果を返す方法を Server Side Rendering (SSR) と呼びます。
Nuxt.js では SSG も SSR もプロジェクト単位で自由に選択できるため、簡単な Web サイトは SSG, 高機能な Web アプリケーションは SSR と両方に対応して作ることができます。
これに加えて、ブラウザ上で JavaScript を動作させる Client Side Rendering (CSR) はどちらも併用することができます。

Firebase でバックエンドの構築

コーポレートページで知見もたまってきたこともあり、次は Web アプリケーションに挑戦するべく、研修で利用するシミュレータを Vue/Nuxt ベースで作りました。
機械学習は与えられたデータを解析して終わりになりがちなので、実際に構築したモデルをシミュレータに適用して結果が得られ、そこからうまくいかなかった要因を考察し、PDCA を回せるようなアプリケーションがシミュレータです。
初期に Vue.js や Nuxt.js を調べていたときに同時に情報が出てきていた Firebase を採用することにしました。 ホスティングが Firebase Hosting, データベースは Firebase Firestore (NoSQL), 認証が Firebase Authentication, バックエンドの処理は Firebase Cloud Functions といった Firebase のエコシステムをフル活用する形です。
SSR 側で組むと処理の分だけサーバー側に負担がかかるのに対して、CSR であれば処理も全部クライアント側で行える上、CDN 上にファイルがキャッシュしてあるので、ホスティング側の不可もほとんど考える必要がありません。 データベースや認証も Firebase なのである程度スケールしても心配いりません。
これまで Ruby on Rails や Django (on Python) を使って開発してきていた私達にとって、バックエンド側で開発を行うと、アプリケーションサーバーやデータベースサーバーをスケールしていかないといけない大変さがすごかったので、この選択は奇跡的な進歩だと感じていました。 もちろん、当時から Heroku のようなバックエンド側のマネージドサービスも出ていましたが、Heroku で実運用しているという話をほとんど聞いたことがなかったので、無料系のものは入門の際に使うサンドボックスぐらいにしか思えなかったのです。 それが無料で始められて、本格的なスケールアップにも対応できて、デプロイも簡単と夢のようなインフラ環境でした。 また、インフラの環境を持たないというのは限られたリソースを改善に注力することができ、アップデートのペースが大幅に早くなりました。
このときに心配していた点としてはセキュリティの問題です。
CSR はクライアント側で動いてくれるので楽な一方で、データベースなどバックエンドにアクセスさせるためのキーも持たせちゃっているのって本当に大丈夫だろうか?Firebase のセキュリティ対策って何をするの?などなどまだまだわからないことだらけでした。
API キーって .env ファイルに入れて環境変数として設定していたらセキュリティ的に大丈夫だよね。ぐらいで思っていましたが、もちろん大間違い。
.env などは GitHub のリポジトリ上にアップロードされないために .gitignore に設定するファイルであり、は本番環境向けのサーバー上に環境変数を設定して CSR で利用すれば当然ユーザー側からキーを確認することができてしまいます。 ちゃんと調べ直したところ、結果的に、Firebase では CSR で実行する上では API キーが漏れるのは当然であり、この前提でデータベース内の権限管理を行って、セキュリティ対策を行うという結論でした。 そこから調べなおして、データベースのセキュリティ対策を行って、社内の研修向けにクローズに使い始めました。
調査に時間をかけたため自信はある一方で、このキーが漏れているため権限管理をしっかりするというセキュリティ対策はミスが起きそうで心理的に不安な選択肢だと思い始めます。

パフォーマンスの壁

コーポレートサイト、KIKAGAKU で SSG の経験を積み、シミュレータで CSR の経験を詰んだところで、本格的な C 向けのプロダクト開発に挑戦します。
これが現在主力のプロダクトとなっている キカガク (kikagaku.ai) です。
ユーザー別の権限管理や動画視聴の基本的な機能に加えて、独自のテスト機能などもついており、知見が溜まってきている中でも開発は設計から実装まで多くの紆余曲折を経て、現在の形に辿り着きました。
Nuxt の課題が顕著に現れ始めたのは公開が迫ってきたタイミングでした。
一通りの動きをチェックした後に、PageSpeed Insights でパフォーマンスをチェックしてみると、PC 版は良いのですが、スマホ版がなかなか遅いのです。 パフォーマンスのスコアが 100 点満点中で PC 版 は 50 点程度で、スマホ版が 5 点となかなか厳しい数値でした。 たしかにスマホ版で見てみると最初の読み込みまでストレスを多少感じる程度でした。
やはりサービスのトップページはストレスなく開くことが重要であり、どれだけ良いことが書いてあっても遅いというの足を引っ張ってしまいます。
この要件がクリアできていませんでした。
色々と開発チームと協力しながら調整していきました。
CSR という構成の都合上、どうしても事前にビルドがしきれないので、デバイス上でのレンダリングが必要となり、ネットワーク速度が遅くてスペックの非力なスマートフォンでは致命傷でした。
この辺りまで経験してきて Vue/Nuxt や Firebase、それからチームの開発体制の作り方に対して、わかってきたのが以下の点です(2020 年 7 月頃の話)。
Vue / Nuxt の課題
  • ページ単位で SSR / SSG が選択できないため、パフォーマンスの最適化が難しい
    • 現状の Nuxt だとプロジェクト単位でしか設定できない都合上仕方ない(現状は不明)
  • コンポーネント指向なのにアトミックデザインと相性が悪い
    • この辺りも後々改善されると思いますが、現状では良くない(コンポーネントの増加でファイル増?)
    • Vue の仕様らしく、React では起こらないらしい
  • Nuxt の画像の取扱いはレベルが低い(現在は改善済み)
    • ほぼ全部手動で設計しないといけない
    • nuxt-optimized-image などのパッケージもまだまだ使いにくい
    • Vue/Gridsome の Image タグなど見習うべきだがない(現在は @nuxt/image がある)
    • これがないと First Content Paint を改善するのに骨が折れる
Firebase の課題
  • セキュリティ的に CSR を使うのがリスク
    • Firestore のリアルタイム性が必要な箇所も少ない割りにリスクは高い
  • CSR + Firestore はコードが複雑になりがち
    • データ層、ビジネスロジック層、プレゼンテーション層の3分割によっぽど意識しないとできない
    • データ層とビジネスロジック+プレゼンテーション層になりがち(リファクタリングしにくいと後で気付く)
  • Firebase Authentication が他のプロダクトに使いにくい
    • 1 プロジェクト、1 Authentication であるため、IDaaS として共通化できない
    • 認証と認可の意識は不要であるため容易な一方で、機能を増やすときに柔軟性が低い
  • Firestore など NoSQL はデータベース設計がしにくい
    • 正規化しないのがメリットな一方で、一般的なデータは正規化した方が扱いやすい
    • SQL が使えないためデータ解析もしにくく、解析時に正規化した形式へ直している
  • Cloud Functions が使いにくい
    • Nuxt との互換性が比較的良いが、内部に入り込めるほどではなく外部ツール
    • ちょっとした API を作るにも Cloud Functions めんどくさすぎ
  • Firebase Hosting が使いにくい
    • Basic 認証ひとつつけるにも Cloud Functions 通さないといけなかったり地味に面倒
チーム開発体制の課題
  • 最初からコンポーネント単位で CSS も設計しないといけなかった(チームの開発体制の問題)
    • 外注時にコーディングしてもらった style.css をグローバルに読み込むととにかく遅い
    • Bootstrap なども使うとコード分割が効率よくできず、遅くなってしまう
    • Purge CSS で 不要な CSS を削除できる機能を使うためには全 CSS の実装箇所の見直しが必要
最後の CSS の問題は Nuxt に対する問題ではなく、チーム開発体制の問題です。
ただ、Nuxt では従来の構造と似ていることから、MVC (Model View Controller) のような従来のチーム開発体制をとってしまうため、グローバルに style.css を書く従来のスタイルの人を巻き込んでしまうのです。
Nuxt でも コード分割 (code splitting) を意識して、必要な箇所に必要な分だけの CSS をコンポーネント単位で書いていくことが重要です。 ※ 先だしですが、React では従来の開発スタイルが取りにくくなっていると感じ、結果的に今回のようなコンポーネント単位で設計されていない問題に遭遇しにくい印象です。
バックエンドの Firebase に関する課題は小さなプロジェクトではメリットでもあります。
その一方で成熟してきたプロダクトや企業では、1プロジェクトに 1DB, 1Auth などが管理しにくくなってきます。
また、データ層、ビジネスロジック層、プレゼンテーション層の3つが分離できていない問題はリリースまでは気づきにくいのですが、機能追加やリファクタリング時に苦しめられました。
この点を考慮して、今後はバックエンドとフロントエンドの分離、OpenAPI ベースでの API サーバーの設置、Active Directory のような ID as a Service (IDaaS) の導入を Microsoft Azure で行っていく予定です。
追記:Firebase から Microsoft Azure へ移行する理由をもっと知りたいというコメントが多かったため、続編の記事を書きました。
パブリッククラウドの選択肢として Microsoft Azure を採用する3つの理由 - fwywd(フュード)
Done is Better than Perfect なので、しっかりと動く仕組みを作ってくれている開発メンバーに感謝しつつ、やはりその次の改善策を考えないといけないなと思っていました。
Vue/Nuxt でさらにチューニングしていく方法を考えるのか、別の技術に移行すべきか。 1年間のプロダクト開発の経験を通じて、もう少し学習コストが高くとも、パフォーマンスの細かいチューニングができる技術選定でも良いところまで到達できていました。

React / Next.js

Next.js の大幅アップデート

ちょうど他の技術への移行も視野に入れ始めたときに、React をベースとした Next.js の大幅アップデートが昨年 2020 年の後半にありました。
2020 年の初期に勉強を始めた時の Next.js はもう古くて全然使えず、それを踏襲してアップデートしたものが Nuxt.js と言われているほどでした。
たしかに最初に勉強した時は、ディレクトリ構成すら定まっておらず、Nuxt の方が使いやすいと感じており、そこに React の特殊な書き方が入ってくると、より Vue/Nuxt の方が良いなと感じるものでした。
大幅アップデートが行われた Next.js は以下のような変更点がありました。
  • 『ページ単位』で SSR / SSG の切り替え可能(CSR はどちらも併用可能)
    • もう Nuxt の苦労はなんだったのか...という感じでした
  • 画像を最適化できる Image タグもあるよ
    • Gatsby だけだった Image タグも登場しました
    • next-optimized-image の更新がこの日から止まりました
    • これを踏襲した nuxt-optimized-image も終わりそう
  • /pages/api/ に格納したファイルでバックエンドの API 機能を構築可能
    • なんで Cloud Functions なんか使ってたのか...という感じでした
Vue/Nuxt のときに頭を悩ませていた問題を Next.js では解決しており、多少の学習コストを払ったとしても移行しても良いだろうと思いました。
特に大きな決め手はページ単位での SSR / SSG の切り替えで、これがプロジェクト単位でしかできない Nuxt.js と大きな差でした。
※ 2021 年 5 月現在の Nuxt.js の情報収集をしていないため対応されていた場合はご指摘いただけますと幸いです。ざっと確認した感じはまだ対応していなさそうな印象でした。
特に今のキカガクチームには最初の SSG / SSR 切り替え可能は願ってもない機能でした。
トップページは認証がいらないので、SSG にしておけば爆速で対応できます。
もし、定期的に更新したかったとしても、Incremental Static Regeneration (ISR) にしておけば、表示の速度を失うことなく、更新も実現できます。
マイページなど認証後のページでは速度は多少落ちても(といってもそこまで落ちませんが)、表示を使い分けたいので SSR で組めば OK。
最高です。

Vercel という黒船到来

Next.js の大幅アップデートに加えて、さらなる決定だとなったのが Next.js の開発をメインで行っている Vercel 社のサービス Vercel(旧:Now) の大幅アップデートでした。
  • Vercel にデプロイすれば SSR の機能も API も全部自動的に Serverless Functions へ
    • SSR/SSG どちらで書いてもデプロイのこと気にしなくて良い
    • ローカルで開発したものがそのまま Vercel で動く
    • DB とか API で機能をラップすればサーバー側で動くので API キー隠せる
    • Serverless Functions なのでスケールしてもある程度までは問題なく動く
  • Next.js の新機能 ISR (Incremental Static Regeneration) を安定してデプロイできる
    • SSG でページ数多くても大丈夫
    • ISR で SSG の速さを実現しながら SSR の更新を実現できる
    • Vercel にデプロイすればインフラを気にする必要なし
  • Vercel で SSR でも個人開発無料
    • 商用利用のチーム開発でも $20/user
    • もう SSR で課金どうのこうのって気にする時代じゃなくなってる
    • Hosting + Serverless Functions で作る Web アプリケーションが新時代
  • Vercel はプルリクエスト等に対してプレビューリンクが自動で付く(最高)
    • 開発用のサブドメインを切って色々と試さなくても良くなる
    • コードだけ見ても良いか悪いか判断できないところも、プレビューリンクで動作確認ができる
    • しかもどのブランチにも適用されるよ(ブランチの限定も可能)
    • main ブランチにマージすれば本番に適用されて CI/CD も超簡単に構築可能
Next.js のアップデートだけでも痒い所に手が届くという言葉がぴったりですが、それ以上に Vercel との組み合わせで開発者体験 (DX: Developer eXperience) が爆上がりでした。
おそらく Nuxt.js もそのうち上記のような機能やエコシステムの充実が見られると思いますが、昨年だけでも 60 億円超の調達を行った Vercel 社が全力で推進する Next.js + Vercel の組み合わせを OSS の Nuxt.js が超えられるのかは定かではありません。
おまけに、React が React Server Component を出してバックエンドをネイティブでサポートも始めたので、より Next.js では詳細なチューニングができるようになっていくはずです。
Vue/Nuxt での開発を一通り体験して『書きやすい、学びやすい、これまでの知識から移行しやすい』といった初歩的なレベルでなく、本格的な開発で使うにはどういった観点が必要なのか?というところもわかってきたのが、上記のような点でした。
まだまだ今年の1年でも開発にコミットしていき、この情報からさらにこんな視点必要だと話せる日が楽しみです。

Tailwind CSS

これは React/Next とは直接的に関係のある話ではありませんが、生の CSS を書くことをなるべく避けて、Tailwind CSS を今回のチームでは採用しました。
Next.js が Tailwind CSS を推しているように感じていたのがきっかけでした。
これまでデザインのコーディングを外注して作っていただいた際に、適切にコード分割ができないと頭を悩ませていた一方で、自分たちで HTML や CSS のフロントエンド(厳密には Frontend of Frontend)のパートまで内製化して実装すべきかと迷っていました。 CSS の調整は骨が折れますし、限られたリソースではなるべくバックエンドよりの処理に力を入れた方がビジネスとして差別化を図りやすかったからです。
その一方で、ある程度プロダクトが大きくなってくると、先述したパフォーマンスのチューニングにもそれなりのコストが割けるようになります。
また、ユーザー体験(UX: User eXperience)をより高めるためのユーザーインターフェース (UI: User Interface) を追求すべく、フロントエンドの実装も開発陣で素早くアップデートしていきたいです。
ビジネスロジックなどを除いたフロントエンドを外注して組んでいただくと、この点に関する実装力が足りないため、どうしても速度が遅くなってしまっていました。 いつかは CSS もちゃんと書かないと...と思いながら日々増加し続ける自分の書いていない CSS を見て、自らアクションを取らないとそんな日は訪れないと危機感を感じ始めます。
そこで、CSS までちゃんと書けるように内製化していくことを決めたときに、開発者体験 (DX) として最も良さそうでもあったのが Tailwind CSS でした。
実際に fwywd のページもその大半を Tailwind CSS で書いているのですが、最初こそ慣れるまで多少の勉強が必要でしたが、1週間ほどでストレスが全然なくなりました。
懸念していたデザイン性の高い Web ページの実装まで可能であるかという点においては fwywd のレベルのページでは全然余裕であり、杞憂に終わりました。
たまにデザイナーの方がこの点を心配されているのですが、大半の CSS の機能が揃っている上、足りない機能があれば CSS Modules で付け加えれば良い程度です。
おそらく相当デザイン性の高い Web ページでも 8 割程度は Tailwind CSS で書けるのではないかと予想しています。
ちなみに、fwywd は Tailwind CSS 率が 95% ほどで 100% も可能です。
Tailwind はその使いやすさで評価されている声が多い一方で、私が感じている一番大きなメリットはコード分割 (code splitting) が完璧に行えることです。
パフォーマンスチューニングにおいて、CSS のファイル容量を減らしたり、無駄なクラス名を減らすといった地道な作業が存在します。   ファイルを一つ一つ見て、読み込む必要のないクラスを特定したり、、、とかなり面倒です。
Tailwind CSS では class 名が固定されていることで、不要なクラス名を作成することはありません。
また、Next.js では Webpack で Tailwind CSS の使われていないクラス名を簡単に最適化(by Purge CSS)できるため、パフォーマンスが抜群に良いです。
今回の技術選定では、『開発者体験 < パフォーマンスチューニング』でも良かったのですが、Tailwind CSS を使うことで開発者体験とパフォーマンスチューニングの両方を得ることができています。

おわりに

Nuxt.js と Next.js のどちらから学び始めるべきか?

今の話からすると React/Next.js 一択となりますが、世の常として細かく調整できるものほど学習コストが高いというトレードオフが存在します。
そのため、全ての人に現在の私たちの選択肢が当てはまっているわけではありません。
キカガクを含めた fwywd の開発チームでは、ある程度プロダクトとチームの技術力が成熟してきたからこそ、今回の選択に移ることができています。 『カスタマイズ性』と『学習コスト』のトレードオフを常に意識しながら意思決定を行ってみてください。
React/Next を最終的には推す形となりましたが、結論としては最初に Vue/Nuxt から学んでよかったと思っています。
自分と親和性の高い領域であったため、JavaScript ベースでの開発の違いの差分を意識しながら学べましたし、差分が少ないほど何がわかっていないのかがわかりました。
Nuxt がわかっていることは Next を学ぶ上でも非常に重要であり、これからは Vue/Nuxt が Python の Flask/FastAPI だと思って学んでもらって、React/Next を Python の Django としてステップアップして学んでもらえると良いですね。
時間がないという方は、挫折する可能性が多少高まるかもしれませんが、React/Next から学び始めていただくので良いかと思います。
fwywd のチームではこの学びで挫折する人が1人でも少なくなるように、技術速報チュートリアルを書いていきますので、ぜひ定期的に見にきていただけると嬉しいです。
長文にお付き合いいただきまして、誠にありがとうございました。
株式会社キカガク 代表取締役会長
吉崎 亮介
twitter: @yoshizaki_91
追記:Firebase から Microsoft Azure へ移行する理由をもっと知りたいというコメントが多かったため、続編の記事を書きました。
パブリッククラウドの選択肢として Microsoft Azure を採用する3つの理由 - fwywd(フュード)