Railsアプリのフロントエンド・リプレイスの失敗?を回避する方法?

に公開

オーソドックスな(ERBでの)SSRからJSON API+SPA(フロントエンド)へのリプレイスに失敗?する理由とその回避策を、自作のRailsアプリを(ERBでの)SSR→Nuxt3でのSPA(フロントエンド)+JSON API(バックエンド)化してみた経験から考えてみます。

https://qiita.com/asip2k25/items/8fd4a4d0f3ee515e0012

注意) オーソドックスな(ERBでの)SSR→JSON API+SPAへの移行(フロントエンド分離)プロジェクトに参加したことはないので、想像で書いています、PHPでのオーソドックスなWEBアプリ→JSON API(Rails)+ React SPAへの移行プロジェクトにバックエンドエンジニアとして参加したことはあります。。。

バックエンド

1) JSON APIの設計者のSPAへの理解が足りていない

SPAをスタンドアロンのGUIアプリの感覚で設計して、WEBアプリ特有の事情(URL直叩きにより各画面にアクセスできるようにする必要があるetc)の考慮に漏れがあった結果、ある程度、開発が進んでから、考慮対象外にしてしまっていた事柄を クライアント or 社内のテスター から指摘され、そこで問題が発覚し、設計レベルから手戻りが発生したりしているのではないかと思います。

バックエンドエンジニアの大半はフロントエンドに詳しくないので、フロントエンド側からみるとJSON APIの設計に問題があっても指摘できないことが多い。あるいは、JSON APIの設計の問題点に気づいても、その設計を聞いた時点で、その設計はクライアントサイドetcから追認された設計で、一般的には問題であっても今回は問題になっていないと考えて、態々、確認しない可能性も。

SPA(フロントエンド)+JSON API(バックエンド)の構成でCRUDを一通り含む小規模なアプリをプロトタイプとして、開発・検証してから、実プロジェクトのJSON APIの設計に取り掛かることで、SPAに関する考慮漏れはなくせるはずです。

2) JSON API設計時にフロントエンドエンジニアとの連携が足りていない

フロントエンドからみたWEBアプリ特有の事情(URL直叩きにより各画面にアクセスできるようにする必要があるetc)の考慮漏れを防ぐには、JSON APIの設計方針を確定させる前に、フロントエンドエンジニアに、フロントエンドとバックエンドの連携について、JSON APIの出力するJSONの内容について、意識の齟齬がないか確認し、齟齬があれば解消しておく必要があります。

3) ERBでのSSR→JSON APIの事前準備が足りていない

オーソドックスなRailsアプリはERBでの出力しか想定していない構造になっていることが多く、そのまま、既存のコードを流用して最小限のコード追加/変更でJSON APIに流用するのは難しいケースが多々あるように思います。

そのようなケースでは、ERBでの出力に依存したコードを局所化/最小化し、それ以外のコードは出力形式を問わず動作するように予めリファクタリングしておく必要があります。

Fat Controller/Fat Model etcになっていて、ERBでの出力に依存したコードの局所化/最小化に時間が掛かる場合、先にFat Controller/Fat Model etcの解消を行ってから、ERBでの出力に依存したコードを局所化/最小化します。

このリファクタリングを予め行なっておくことで、JSON APIの作成を最小のコード追加で行えるようになるはずです。

フロントエンド

1) 安易にSPAフロントエンドをReactで構築しようとしている

プロジェクトのチームメンバーの特性を考えず、今、世界で一番使われている(一番、流行っている)から「だけ」の理由で安易にReactを選定し、開発に行き詰まっているケースが多々あるように思います。

https://ja.wikipedia.org/wiki/ステートレス・プロトコル#:~:text=HTTPはステートレス・プロトコルで,手段が提供される。

Reactは一見シンプルに見えるけれどシンプル(に利用できる)とはいえない癖の強いライブラリなので、(JQueryを扱える程度+のフロントエンド知識しかないことが多い)バックエンドエンジニア(Rails)を即席でフロントエンド開発に投入するのは難しく、Reactについて十分な経験のあるエンジニアを一定数?揃えて開発をスタートしていないとどこかで手戻りetcの発生が多発しているのではないかと思います。

後述していますが、フロントエンドの基盤整備を先ず行うことで、フロントエンド開発メンバーのReactについての経験差(理解の深い/浅い)をある程度吸収することが可能だとは思います(吸収しきれるかは不明です)。

Vue.js(3以降)であれば、Vue.jsに精通したフロントエンドエンジニアが数人いれば、(基盤が充分に整備されていなくても)フロントエンドエンジニアのサポートのもと、バックエンドエンジニア(Rails)を即席でフロントエンド開発に投入することも可能なはずです。

Vue.js/React が、 easy/simple と表現されることが多いことからもわかるように、Vue.js の方が(遥かに?)扱いやすいです。

https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1149573806

https://note.com/himaratsu/n/nad0361600820

https://note.com/taksuzuki/n/n68aa37b2e746

Svelte5以降でも、同様かもしれません。

プロジェクトチームのメンバーの特性に応じた(+未来を見据えた)技術スタックの選定は必須です。

2) フロントエンドの基盤整備を(充分に)行っていない

一部機能を試験的に先行実装して、それをプロトタイプとして、SPAフロントエンドの本格的な開発をスタートしていることが多いのではないかと思います。

Railsバックエンドであれば、Rails自体が基盤としての要件?を(ある程度?)満たしているので、プロトタイプを参考にした開発で問題ないことが多いですが、SPAフロントエンドではフロントエンドのライブラリやフレームワークは基盤とするには機能面で弱い?です。

RailsがMVCを提供しているのに対し、フロントエンドのSPA用フレームワーク(React/Vue.js/Svelte/Solid.js/etcのライブラリやそれらをベースにしたFW( フレームワーク))はV(View)のみを(基本)対象としています。

一例をあげると、外部データソースにアクセスしJSONetcを返すしくみは、ほとんどのフロントエンドのSPA用フレームワークで提供されていません。

外部データソース(サーバー)へのアクセス→JSONorエラー情報の取得→オブジェクトへの変換まわりはブラウザに組み込まれたWEB標準のAPIor別のライブラリを利用して、プロジェクト内で自前で記述する必要があります。

Railsでは用意されているフラッシュ・メッセージの表示/データソースからのエラーメッセージ表示用のしくみも提供されていないので、プロジェクト内で自前で記述する必要があります。

この2つ以外にも、RailsにはあってフロントエンドのSPA用のフレームワークにはない機能は多々?あります。

それらについても、言わずもがなですが、必要なら、プロジェクト内で自前実装する必要があります。

プロトタイプの開発では、RailsにはあってフロントエンドのSPA用のフレームワークにはない機能については、プロトタイプの実装に(最低限?)必要な機能のみを実装し、残りの多くについては一旦無視されることが多いのではないかと思います。

RailsにはあってフロントエンドのSPA用のフレームワークにはない機能を後(ある程度、開発が進んで)から実装し組み込む、RailsにはあってフロントエンドのSPA用のフレームワークにはない機能を開発エンジニアが手探りで実装、類似の実装がプロジェクト内に多数存在するようになり、後からリファクタリングし、後付けで共通化する、なんてことは、失敗?するプロジェクトには多々あるのではないかと思います。

プロトタイプの段階で作り込みを(きちんと)行い、並行して、予定している機能に基づき、RailsにはあってフロントエンドのSPA用のフレームワークにはない機能を実装して基盤として整備する、or、プロトタイプ開発の後、RailsにはあってフロントエンドのSPA用のフレームワークにはない機能を先行実装して基盤として整備する、のなら、手戻り?や同一機能の多重実装を防げるのではないかと思います。

ある程度?整備できてから、SPAフロントエンドの本格的な開発をスタートすることで、基盤に基づいた各機能の実装が可能になり、開発のスピードアップに繋がるはずです。

また、基盤の構築により、バックエンドエンジニアのフロントエンド開発への投入もしやすくなるはずです。(基盤がフロントエンド開発経験の浅いプロジェクトメンバーをカバーしてくれます)

番外?) バックエンドテスト

1) Open APIによるJSON API定義に基づいた自動テスト(コード作成)に時間が掛かっている

rspec-openapi gem+committee-rails gemの組み合わせを活用するのが望ましい気がします。

rspec-openapi gemは、request specを実行すると、Open API(3.0.3)によるJSON API定義を自動生成してくれるRSpecのプラグインです。

committee-rails gemは、Open API(3.0.3)によるJSON API定義を読み込み、JSON APIのバリデーションを行うRSpecのプラグインです。

rspec-openapi gemにより生成されるJSON API定義は、request specの網羅性に依存するとともに、開発途上?で生成される定義には粗があるので、手動でのカスタマイズが多少必要となります。また、生成される定義は冗長です、冗長であることを許容することで、カスタマイズに掛かる時間を最小化することができます。

https://tech.studyplus.co.jp/entry/2024/01/22/090000

https://tech.gunosy.io/entry/openapi_rails_ts

Open APIによるJSON API定義の自動生成→それに基づいた自動テストにより、Open APIによるJSON API定義の 作成→JSON APIのテストコード作成に掛かる時間をかなり削減できるはずです。

Open APIによるJSON API定義に基づいた自動テストにより、バックエンド開発におけるケアレスミスによるフロントエンドとの接続時の問題発生も低減できるはずです。

推敲中…

Discussion