Inertia.jsでシンプルにSPAを構築する Inertia入門#1

Laravel

Inertia.jsを使うとLaravelやRuby on Railsなどのフレームワーク上でAjax用のAPIやコントローラーを作成しなくても、通常のビューを使う要領でSPA(シングルページアプリケーション)が構築できます。

Laraveler
Laraveler

Laravel8でInertiaというものを見かけるようになったけど、このInertiaとは一体何です?

シップ
シップ

Inertiaはフロントエンドとバックエンドの間にうまく入って、リクエストをよしなに処理してくれるもので、使うとSPAを作るのが楽になるよ!

この記事では、Inertia.jsの役割や目的、仕組みについて解説します。
具体的な使用方法については続く記事で解説していきます。

Inertia.jsとは何か

Inertia.jsとは、公式サイトの説明によると、「 従来のサーバー駆動型Webアプリケーションの構築への新しいアプローチ」で「現代のモノリス」と呼んでいます。

Inertia.jsによって、完全にクライアントサイドでの画面描画を行うSPAを、複雑なSPAのためのAPIをバックエンドに必要とせず、今まで使用していたフレームワークのコントローラーを記述するのとほぼ同じ形で構築できるということです。

これまではLaravelとVueでSPAを開発しようとした場合、Laravel側では通常のリクエストに対しては通常のビューを返すのに加え、Vueから呼び出されるリクエストのためにもAPIを作る必要がありました。さらに、Vue側でもVue-RouterなどでURLに対応するビューを指定する必要があって複雑になっていました。

これが、Inertia.jsを使用すると、一つのコードで、フルのHTMLを返す時とXHRでの部分的なデータを返す時の両方に対応させることができるようになります。また、Vue側でルーティングする必要もありません。Vue-Routerは要らないということです。

フレームワークなのか

Inertia.jsはフレームワークではありません。LaravelやVue.jsなどのフレームワークを置き換えるものではなく、その間に入って仲介する役割を果たすものです。

クライアントサイドのフレームワークは公式にReact,Vue,Svelteに対応しています。サーバーサイドのフレームワークとしてはLaravelとRailsに公式対応しています。その他のフレームワークにも有志により対応するためのパッケージが提供されています。

Inertia.jsは、サーバーサイドとクライアントサイドの両方を取り持って、一つのコードで通常のリクエストとXHRリクエストどちらにも対応できるようにしてくれるもの

Inertia.jsを使うべき時

こんなWebアプリを作る際にInertia.jsは役立ちます
  • LaravelやRuby on Rails、Djangoなどのフレームワークでビューを使ってHTMLを出力しているMPAをSPAに変更したい。
  • もしくはそれらのフレームワーク上で、シングルページアプリケーション(SPA)をAPIなど複雑なことを考えずに構築したい。

サーバーサイドでHTMLを出力するMVC構造のフレームワークでは通常、データベースからデータを取得するモデル、画面を描写するためのHTMLを出力するビュー、そしてモデルとビューを結び付けるコントローラーを作成します。

Inertia.jsでは、このビューをJavascriptコンポーネントとして作成していく以外はさほど違いはありません。例えばBladeで作成していたビューをVue.jsのコンポーネントとして作成するという感じです。

Inertia.jsを使うと、JavascriptベースのSPAを面倒なAPIを作成せずに、従来のサーバーサイドでHTMLを出力していた時と同じような感じで構築できます。

Inertia.jsの動作の仕組み

Inertia.jsはフロントエンドとバックエンド両方に絡んで両社の橋渡しを行います。

バックエンド側

バックエンドでは初回か2回目以降かに応じて、フルHTMLを返すのか、それともJSONデータだけを返すのかを制御します。これはLaravelなどバックエンドフレームワークに組み込まれたInertiaでやってくれるので、作成側としては特に意識する必要なくビューとデータを返すコントローラーを作成するだけで大丈夫です。

初回か2回目以降かどうかの判定方法

初回のアクセスか2回目以降のアクセスかどうかを「X-Inertia」ヘッダーがTrueにセットされているかどうかで判別しています。「X-Inertia」ヘッダーがセットされていなければ、通常のリクエストとみなして、ページを構成するHTMLをレスポンスとして出力します。逆に「X-Inertia」ヘッダーがセットされていればXHRリクエストとみなして、JSONデータのみを出力します。

初回のレスポンス

このHTMLには、SPAのマウントポイントとなるルート<div>タグが含まれ、その属性値「data-page」にJSONエンコードされたページオブジェクトが含まれ、このページオブジェクトを用いてフロントエンドがページの内容を描画します。

つまり、初回のリクエスト時の応答にはHTMLの枠と中身のデータが含まれ、Vue.jsなどのフロントエンドのアプリでその中身のデータを使って最初の画面を構築していきます。

初回アクセス時もサーバーサイドレンダリングされるわけではありません。あくまでHTMLに、初回アプリ立ち上げに必要なデータが付加されたものが返ってくるだけで、実際の画面描画は初回の場合もフロントエンドで行われます。

2回目以降のレスポンス

「X-Inertia」ヘッダーがTrueにセットされている場合、Inertia.jsによるXHRリクエストと判定し、ページオブジェクトのJSONデータのみをレスポンスとして返します。

フロントエンド側

フロントエンド側では、リンクをクリックした際に通常のページ読み込みではなく、XHRでのリクエストにすることで、SPAを実現させています。そのために「<a>」タグの代わりに「<inertia-link>」コンポーネントを使用します。リンクをこのコンポーネントで置き換えることで、リンククリックの際にInertia.jsが介入して「X-Inertia」ヘッダーを付加したXHRリクエストを送信します。

JavascriptからXHRリクエストを送信する場合は「Inertia.visit()」メソッドを使用できます。

ページの描写は、data-page属性や、JSONレスポンスで渡されたページオブジェクトをもとに行います。同時に履歴の追加や、アセットファイルの更新時はページ全体の再読み込みなども行います。

ページオブジェクト

バックエンドからフロントエンドへ渡されるデータをページオブジェクトと呼んでいます。このオブジェクトにはページを描画するのに必要な情報が含まれています。

ページオブジェクトに含まれるデータ
  • component: Javascriptのページコンポーネント名
  • props: ページで必要なデータ
  • url: ページのURL
  • version: アセットバージョン

アセットバージョン

アセットバージョンはアセット(コンポーネントを構成するファイルやCSSやJSなど)が更新されたことを、検知するための仕組みです。XHRリクエストの際にサーバーから提供されたアセットバージョンをヘッダーに付加して送信します。サーバー側でそのアセットバージョンが最新のバージョンかどうかを確認し、異なる場合は409レスポンスを送信し、ページ全体の読み込みをするようフロントエンドに促します。

まとめ

Laraveler
Laraveler

Inertiaはフロントエンドとバックエンドの両方に介入してSPAを作りやすくしてくれるプロダクトなんですね!

シップ
シップ

そうですね!ただメリット、デメリットもあるので見ていきましょう。

Inertia.jsを使うメリット
  • コントローラーをシンプルにできる
  • フロントエンド側でもあまり意識せずにSPAを実現できる
Inertia.jsを使う場合のデメリット
  • 比較的最近出てきた(初版は2019年8月)もののため、日本語の情報が少ない
  • まだ開発途中といった段階なのでバグなどもあり、安定した動作が必要な場合には不向き

次回は、Inertia.jsのLaravelへの導入方法と、HelloWorldを表示するところまで行います。

Inertia.js入門記事一覧
Inertia.jsでシンプルにSPAを構築する Inertia入門#1
Inertia.jsを使うとLaravelやRubyonRailsなどのフレームワーク上でAjax用のAPIやコントローラーを作成しなくても、通常のビューを使う要領でSPA(シングルページアプリケーション)が構築できます。
Laravel 10+Inertia.js+Tailwindインストール Inertia入門#2
この記事ではLaravelにInertia.jsをインストールしてHelloWorldを出力する方法までを解説します。
Inertia.jsのルーティングとレスポンス作成 Inertia入門#3
Laravel8でjetstreamを入れるとLimewireかInertiaかを選べます。この記事ではInertiaを使ってルーティングやInertiaレスポンスの返し方を解説します。
Inertia.jsでページレイアウト Inertia入門#4
この記事では、ページレイアウトについて解説します。親レイアウトに子ページを組み込むことで、ヘッダーやフッターを共通化できます。
Inertia Linkの使い方 Inertia.js入門 #5
この記事では、Inertia.jsのLinkコンポーネントについて解説します。
Inertia.jsでXHRリクエスト Inertia.js入門 #6
この記事では、Inertia.jsで非同期通信を行うrouter.visit()について解説します。
Inertia.jsでのフォームとリダイレクト Inertia.js入門 #7
この記事では、Inertia.jsでのフォーム送信とリダイレクトについて解説します。
Inertiaでのバリデーション Inertia.js入門 #8
この記事では、Inertia.jsを使った際のバリデーションエラーの表示について解説します。
Inertiaで共通データとフラッシュメッセージ Inertia.js入門 #9
この記事では、Inertiaのレスポンスに毎回同じデータを含める方法やフラッシュメッセージの使い方について解説します。

この記事を書いた人

PHPが好物な個人開発プログラマ。フリーランスエンジニアとしてWebサービス作ったりしてます。15年の経験を生かしてMENTAでメンターもやってます。WordPressやPHPでお困りのことがあればご相談に乗りますのでDMください。

Follow on SNS
Laravel
SOHO MIND

Comments

タイトルとURLをコピーしました