Slide 1

Slide 1 text

Laravel x Inertia.js "現代のモノリス"によるお手軽SPA開発 PHPカンファレンス福岡 2023 2023/06/24 tutida / 内田 大順 1

Slide 2

Slide 2 text

自己紹介 内田 大順 Uchida Tomoyuki - ID - GitHub:tutida - Twitter:@_tutida_ - Work at - 株式会社 Fusic (フュージック) - プリンシパルエンジニア - Skill - 本日の資料 - https://speakerdeck.com/tutida/ - 最近のこと - 今日(6/24)が奥さんの誕生日と気づかずプロポーザルを申 し込んでいた 2

Slide 3

Slide 3 text

01 最近の仕事で思うこと

Slide 4

Slide 4 text

最近の仕事で思うこと 顧客がWebアプリに求める "普通" のUI/UXのレベルが上がってきている • 「インスタの○○○○みたいな動き方が理想です」 • 「Netflixの○○○○みたいな機能が欲しいです」 • 「条件を入れるごとに、自動的に絞り込んでほしい」 などなど 4

Slide 5

Slide 5 text

最近の仕事で思うこと 顧客がWebアプリに求める "普通" のUI/UXのレベルが上がってきている • 「インスタの○○○○みたいな動き方が理想です」 • 「Netflixの○○○○みたいな機能が欲しいです」 • 「条件を入れるごとに、自動的に絞り込んでほしい」 などなど 5 UI/UXの要件を満たすため、SPAの構築の機会が増えている

Slide 6

Slide 6 text

02 Laravel での SPA

Slide 7

Slide 7 text

Laravel での SPA API APIサーバ フロントの何か LaravelをAPIサーバとして利用すると 7

Slide 8

Slide 8 text

Laravel での SPA • バックエンド / フロントエンドが疎結合 • APIスキーマによる型制約やモック • それぞれの開発に集中できる API APIサーバ フロントの何か LaravelをAPIサーバとして利用すると 良い点 8

Slide 9

Slide 9 text

Laravel での SPA • バックエンド / フロントエンドが疎結合 • APIスキーマによる型制約やモック • それぞれの開発に集中できる API APIサーバ フロントの何か LaravelをAPIサーバとして利用すると 良い点 • APIスキーマ・リポジトリの管理 • 開発スピードの初速が出にくい • お互いの開発に無関心になりやすい 要検討 9

Slide 10

Slide 10 text

Laravel での SPA • バックエンド / フロントエンドが疎結合 • APIスキーマによる型制約やモック • それぞれの開発に集中できる API APIサーバ フロントの何か LaravelをAPIサーバとして利用すると 良い点 • APIスキーマ・リポジトリの管理 • 開発スピードの初速が出にくい • お互いの開発に無関心になりやすい 要検討 疎結合という甘美な響きの裏にはそれ相応のコストが潜む。 中小規模(予算, 人数)の場合、スケジュール・コストの面で見合わないことがある 10

Slide 11

Slide 11 text

Laravel での SPA 11 (SPAとして構築をしたいが、スケジュールとコストが見合わない...)

Slide 12

Slide 12 text

Laravel での SPA 12 (SPAとして構築をしたいが、スケジュールとコストが見合わない...) (もっと...気軽にSPA開発がしたい....っ!!! )

Slide 13

Slide 13 text

Laravel での SPA 13 (SPAとして構築をしたいが、スケジュールとコストが見合わない...) (もっと...気軽にSPA開発がしたい....っ!!! ) そんな人にぜひ試してみてほしい。 疎結合とは正反対、現代のモノリス(The modern monolith)を提唱する Inertia.js

Slide 14

Slide 14 text

Laravel での SPA Inertia.js を使うと… 14

Slide 15

Slide 15 text

Laravel での SPA Inertia.js を使うと… • 直接 Vue などのJSコンポーネントを描画できる • セットした変数を JS 側で直接受け取れる 変数を直接渡せる 15 ・API必要なし ・JSONエンコード必要なし class UsersController { public function index() { $users = User::active() ->orderByName() ->get(['id', 'name', 'email']); return Inertia::render('Users', [ 'users' => $users ]); } } import Layout from './Layout' import { Link, Head } from '@inertiajs/vue3' defineProps({ users: Array })
{{ user.name }}
{{ user.email }}

Slide 16

Slide 16 text

Laravel での SPA Inertia.js を使うと… • 直接 Vue などのJSコンポーネントを描画できる • セットした変数を JS 側で直接受け取れる 変数を直接渡せる 16 ・API必要なし ・JSONエンコード必要なし まるでBladeファイルを書くように、フロントエンドの開発ができる! class UsersController { public function index() { $users = User::active() ->orderByName() ->get(['id', 'name', 'email']); return Inertia::render('Users', [ 'users' => $users ]); } } import Layout from './Layout' import { Link, Head } from '@inertiajs/vue3' defineProps({ users: Array })
{{ user.name }}
{{ user.email }}

Slide 17

Slide 17 text

03 Inertia.js

Slide 18

Slide 18 text

Inertia.js Inertia.js は Laravel8 から採用され Breeze で簡単にセットアップが可能 18 curl -s "https://laravel.build/laravel-inertia-vue-app?with=pgsql" | bash cd laravel-inertia-vue-app # Dockerコンテナ起動 ./vendor/bin/sail up -d # Breezeのインストール ./vendor/bin/sail composer require laravel/breeze --dev ./vendor/bin/sail artisan breeze:install vue # マイグレーションコマンド実行 ./vendor/bin/sail artisan migrate # Viteの開発サーバー起動 ./vendor/bin/sail npm install ./vendor/bin/sail npm run dev

Slide 19

Slide 19 text

Inertia.js 実際にインストールしたものがこちらに 19

Slide 20

Slide 20 text

Inertia.js どういう動きをしているか… 20

Slide 21

Slide 21 text

Inertia.js どういう動きをしているか… 21 ポイント① : Inertia が提供する コンポーネント ・をクリックすると 、通常の遷移を XHR 経由に変える ・ヘッダーに “X-Inertia : true” が付与される

Slide 22

Slide 22 text

Inertia.js どういう動きをしているか… 22 ポイント① : Inertia が提供する コンポーネント ・をクリックすると 、通常の遷移を XHR 経由に変える ・ヘッダーに “X-Inertia : true” が付与される ポイント② : Laravel は Inertia からのアクセスの場合、DOMではなくJSONを返す Laravel は ヘッダー “X-Inertia : true” が ・ない場合 : 定義されたViewをDOMとして返す ・ある場合 : DOMは返さず、setされた変数をJSON化して、JSONとして返す ※ https://github.com/inertiajs/inertia-laravel/blob/master/src/Response.php

Slide 23

Slide 23 text

Inertia.js どういう動きをしているか… 23 初回アクセス・アドレスバーから直接遷移した場合

Slide 24

Slide 24 text

Inertia.js どういう動きをしているか… 24 初回アクセス・アドレスバーから直接遷移した場合 REQUEST GET: http://example.com/dashboard Accept: text/html, application/xhtml+xml

Slide 25

Slide 25 text

Inertia.js どういう動きをしているか… 25 初回アクセス・アドレスバーから直接遷移した場合 < 普通のアクセスだから、DOMとデータ全部渡すぞ REQUEST GET: http://example.com/dashboard Accept: text/html, application/xhtml+xml

Slide 26

Slide 26 text

Inertia.js どういう動きをしているか… 26 初回アクセス・アドレスバーから直接遷移した場合 < 普通のアクセスだから、DOMとデータ全部渡すぞ REQUEST GET: http://example.com/dashboard Accept: text/html, application/xhtml+xml RESPONSE HTTP/1.1 200 OK Content-Type: text/html; charset=utf-8 My app

Slide 27

Slide 27 text

Inertia.js どういう動きをしているか… 27 2回目以降にからアクセスした場合 import { Link } from '@inertiajs/vue3'; Dashboard

Slide 28

Slide 28 text

Inertia.js どういう動きをしているか… 28 2回目以降にからアクセスした場合 経由だから、リクエストをXHRに変えたよ > X-Inertia ヘッダーもつけておいたよ > import { Link } from '@inertiajs/vue3'; Dashboard

Slide 29

Slide 29 text

Inertia.js どういう動きをしているか… 29 2回目以降にからアクセスした場合 経由だから、リクエストをXHRに変えたよ > X-Inertia ヘッダーもつけておいたよ > import { Link } from '@inertiajs/vue3'; Dashboard REQUEST GET: http://example.com/dashboard Accept: text/html, application/xhtml+xml X-Requested-With: XMLHttpRequest X-Inertia: true X-Inertia-Version: 6b16b94d7c51cbe5b1fa42aac98241d5

Slide 30

Slide 30 text

Inertia.js どういう動きをしているか… 30 2回目以降にからアクセスした場合 < X-Inertia があるから、JSONで返すぞ 経由だから、リクエストをXHRに変えたよ > X-Inertia ヘッダーもつけておいたよ > REQUEST GET: http://example.com/dashboard Accept: text/html, application/xhtml+xml X-Requested-With: XMLHttpRequest X-Inertia: true X-Inertia-Version: 6b16b94d7c51cbe5b1fa42aac98241d5

Slide 31

Slide 31 text

Inertia.js どういう動きをしているか… 31 2回目以降にからアクセスした場合 < X-Inertia があるから、JSONで返すぞ 経由だから、リクエストをXHRに変えたよ > X-Inertia ヘッダーもつけておいたよ > REQUEST GET: http://example.com/dashboard Accept: text/html, application/xhtml+xml X-Requested-With: XMLHttpRequest X-Inertia: true X-Inertia-Version: 6b16b94d7c51cbe5b1fa42aac98241d5 RESPONSE HTTP/1.1 200 OK Content-Type: application/json Vary: Accept X-Inertia: true { "component": "Dashboard", "props": { "canLogin": true, "canRegister": false, "laravelVersion": "10.13.5", "phpVersion": "8.2.7", "event": "phpconfuk2023" }, "url": "/dashboard", "version": "c32b8e4965f418ad16eaebba1d4e960f" }

Slide 32

Slide 32 text

Inertia.js どういう動きをしているか… 32 2回目以降にからアクセスした場合 < X-Inertia があるから、JSONで返すぞ 経由だから、リクエストをXHRに変えたよ > X-Inertia ヘッダーもつけておいたよ > < Dashboardコンポーネントだけを 受け取ったJSONの内容で書き換えるよ REQUEST GET: http://example.com/dashboard Accept: text/html, application/xhtml+xml X-Requested-With: XMLHttpRequest X-Inertia: true X-Inertia-Version: 6b16b94d7c51cbe5b1fa42aac98241d5 RESPONSE HTTP/1.1 200 OK Content-Type: application/json Vary: Accept X-Inertia: true { "component": “Dashboard", "props": { "canLogin": true, "canRegister": false, "laravelVersion": "10.13.5", "phpVersion": "8.2.7", "event": "phpconfuk2023" }, "url": "/dashboard", "version": "c32b8e4965f418ad16eaebba1d4e960f" }

Slide 33

Slide 33 text

Inertia.js Inertia.js を使うと… 33

Slide 34

Slide 34 text

Inertia.js Inertia.js を使うと… 34 API通信であることを意識せず、 Bladeファイルを書くようにSPA開発が出来るようになる

Slide 35

Slide 35 text

Inertia.js Inertia.js を使うと… 35 あえて、バックエンドとフロントエンドを密結合(モノリス)にする API通信であることを意識せず、 Bladeファイルを書くようにSPA開発が出来るようになる

Slide 36

Slide 36 text

04 仕事で使って感じた メリット・デメリット

Slide 37

Slide 37 text

仕事で使って感じた メリット・デメリット • 管理が楽 • SPAとは思えない開発速度 • それぞれの開発が見えやすい • エコシステム, Inertiaが用意しているコンポーネントが優秀 37 メリット

Slide 38

Slide 38 text

仕事で使って感じた メリット・デメリット • 管理が楽 • • • 38 メリット ・APIスキーマ用、フロントエンド用のリポジトリなどの管理を気にせず、 1つのリポジトリ内でアプリケーションが完結する。 ・1つのリポジトリにアプリケーションがあるため、 CI/CD, E2E テストもMPAのLaravelと同様の手順で行える。

Slide 39

Slide 39 text

仕事で使って感じた メリット・デメリット • • SPAとは思えない開発速度 • • 39 メリット ・変数の受け渡しがスムーズ APIスキーマを定義して…フロントと共有して…の必要がない。 ・Laravel側のルーティング, 認証などをそのまま使えるため、 フロント側は画面の作りにのみ集中できる。

Slide 40

Slide 40 text

仕事で使って感じた メリット・デメリット • • • それぞれの開発が見えやすい • 40 メリット ・同じリポジトリ内で作業をしているため、バックエンド・フロントエンド担当 それぞれの作業で何をやっているのかよく分かる。 → 仕様・知見の共有面でも良かった。 ・簡単な修正ならお互いに直せる。(Ex. この値欲しい, ここの表示こうしたい、など)

Slide 41

Slide 41 text

仕事で使って感じた メリット・デメリット • • • • エコシステム, Inertiaが用意しているコンポーネントが優秀 41 メリット ・Breeze で容易にセットアップが出来る。 ・Form, バリデーションとエラーの表示, ファイルアップロードなど、 SPAで面倒になりがちなところが Inertia.js 側で用意されている。

Slide 42

Slide 42 text

仕事で使って感じた メリット・デメリット 42 デメリット(注意点) • Laravelの単体テストはAPIの方が書きやすい • APIスキーマによるモック, 型の恩恵は受けれない • Webアプリ以外を作ることになると、基本的に作り直し

Slide 43

Slide 43 text

仕事で使って感じた メリット・デメリット 43 デメリット(注意点) ・(設計によるが)Controllerに画面表示に必要な変数を全てセットするため、 APIの場合と比べて単体テストがゴチャゴチャする。 → MPA方式の時と同様 ・Inertia 用のPHPUnitで実行できるAssertがあるため、埋め込みのJSよりはテストが書ける • Laravelの単体テストはAPIの方が書きやすい • •

Slide 44

Slide 44 text

仕事で使って感じた メリット・デメリット 44 デメリット(注意点) ・(設計によるが)Controllerに画面表示に必要な変数を全てセットするため、 APIの場合と比べて単体テストがゴチャゴチャする。 → MPA方式の時と同様 ・Inertia 用のPHPUnitで実行できるAssertがあるため、埋め込みのJSよりはテストが書ける • Laravelの単体テストはAPIの方が書きやすい • • get('/podcasts/41') ->assertInertia(fn (Assert $page) => $page ->component('Podcasts/Show') ->has('podcast', fn (Assert $page) => $page ->where('id', $podcast->id) ->where('subject', 'The Laravel Podcast') ->has('seasons', 4) ->has('seasons.4.episodes', 21) ->has('host', fn (Assert $page) => $page ->where('id', 1) ->where('name', 'Matt Stauffer') ) ) ); } }

Slide 45

Slide 45 text

仕事で使って感じた メリット・デメリット 45 デメリット(注意点) ・APIスキーマがあれば…という場面は実際何度もあった ・フロントエンドがモックサーバで開発が出来ない ・リクエスト, レスポンス, モデルの型チェック → 16:30~ Urata Daiki のレギュラートークの内容でカバー ・長期的, 大人数で開発する際には、APIスキーマがあるべきと改めて思った • • APIスキーマによるモック, 型の恩恵は受けれない •

Slide 46

Slide 46 text

仕事で使って感じた メリット・デメリット 46 デメリット(注意点) ・「そうだ、これスマホアプリにもしよう!」となっても、 APIサーバとしては構築がされていないので、結構な作り直しになる(実際なりかけた) ・近い未来の展望に、APIサーバとしての稼働が必須であれば、やめた方がよさそう • • • Webアプリ以外を作ることになると、基本的に作り直し

Slide 47

Slide 47 text

05 まとめ

Slide 48

Slide 48 text

まとめ Inertia.js • バックエンドとフロントエンドをあえて密結合(モノリス)にする • 複雑さを感じることなく、スピーディーにSPAを構築するためのプラグイン 向いていると感じたユースケース • MVPのように、まずはスピーディーに動くアプリケーションを作る場合 • データ構造はシンプルだが、画面の動きはリッチにしたい場合 • 中小規模(予算, 人数)のアプリケーション お気軽SPA開発をぜひ体験してみてください! 48 対応しているバックエンド 対応しているフロントエンド

Slide 49

Slide 49 text

ご清聴いただきありがとうございました Thank You We are Hiring ! https://recruit.fusic.co.jp/