Laravel のデフォルトの Blade テンプレートを使って実装していると、コード量が増えるにつれ、可読性が落ちるのが気になっていました。
React や Vue などのコンポーネント指向の書き方に慣れているので、それっぽく書ける機能がないか調べたところ、Laravel のエコシステムの1つに「Livewire」というものがあったので、今回取り上げてみました。
Livewire is 何
公式サイトのファーストビューには以下のように書かれてます。
Livewire is a full-stack framework for Laravel that makes building dynamic interfaces simple, without leaving the comfort of Laravel.
「Livewire を使えば、Laravel の扱いやすさをそのままに、動的なインターフェースを作れるぜ」的なことだと思います。
脱線。 語源を推測
開発者がどんな意図で名前をつけたのか気になってしまうので、推測してみました。
1単語ですが、語形成からlive
を生きた
、wire
を線、ワイヤー
と分解して解釈すると、「クライアントとサーバーをリアルタイムで繋ぐワイヤー」みたいな意味合いでしょうか。
記事の後半で軽くいじってみますが、機能的には↑の意味合いで合ってそうでした。
とか思っていたんですが、そもそも活動家、精力的な人
という意味のlive wire
という熟語があるらしく、ダブルミーニング的なことなのかなと。
その名の通り、こいつめちゃくちゃ働きます。
Livewire 試運転
導入は Livewire のクイックスタートのままにやったので割愛します。
Quickstart
・・・
素朴な計数機の出来上がりです。
app/Livewire/Counter.php
<?php
namespace App\Livewire;
use Livewire\Component;
class Counter extends Component
{
public $count = 1;
public function increment()
{
$this->count++;
}
public function decrement()
{
$this->count--;
}
public function render()
{
return view('livewire.counter');
}
}
resources/views/livewire/counter.blade.php
<!-- Counter コンポーネント -->
<div>
<h1>{{ $count }}</h1>
<button wire:click="increment">+</button>
<button wire:click="decrement">-</button>
</div>
App\Livewire
で作ったコンポーネントクラスで定義した
変数($count
)、
メソッド(increment()
,decrement()
)
が、resources/views/livewire/counter.blade.php
で呼び出せます。
計数機くんは、クリックした時にwire:click
で指定したメソッド名が呼び出されます。
仕組み
Livewire の実装はほどほどにして、どういう仕組みで動いているかの方が気になったので、そちらの路線で調べました。
まず、ページにアクセスした時の初期状態ですでに、Livewire を使っているコンポーネントに wire属性が付与されています。
wire:snapshot
に count:1
のような記述があるので、ここでデータを持っているようです。
<div
wire:snapshot="{"data":{"count":1},"memo":{"id":"x6b7a98mTcP8XrG0d4Im","name":"counter","path":"counter","method":"GET","children":[],"scripts":[],"assets":[],"errors":[],"locale":"en"},"checksum":"274122539214fa2e25def11ec2670f57fef33dde471b2c05aef1d9832683a505"}"
wire:effects="[]"
wire:id="x6b7a98mTcP8XrG0d4Im"
>
<h1>1</h1>
<button id="btn-increment" wire:click="increment">+</button>
<button id="btn-decrement" wire:click="decrement">-</button>
</div>
次に、ボタンをクリックして、count の数を増減させ、開発者ツールのネットワークで動きを監視します。
すると、自サーバー内の /livewire/update
に POST していました。
div タグに付与された wire:xxx 属性等の情報を渡して POST し、そのレスポンスとして wire:xxx に相当するデータと、コンポーネント自体の HTML が返ってきているようです。
更新されたHTMLを見てみると、レスポンスにある HTML に書き換わっているようで、データのみではなく、HTML自体がレスポンスとして返ってきていることに驚きました。
このリクエスト先(/livewire/update
)は、Livewire の機能を追加すると自動でルーティングされます。
> php artisan route:list
GET|HEAD / ...............................................................................................................
GET|HEAD counter .................................................................................... App\Livewire\Counter
GET|HEAD livewire/livewire.js ................................ Livewire\Mechanisms › FrontendAssets@returnJavaScriptAsFile
GET|HEAD livewire/livewire.min.js.map .......................................... Livewire\Mechanisms › FrontendAssets@maps
GET|HEAD livewire/preview-file/{filename} ....... livewire.preview-file › Livewire\Features › FilePreviewController@handle
POST livewire/update ............................. livewire.update › Livewire\Mechanisms › HandleRequests@handleUpdate
POST livewire/upload-file ..................... livewire.upload-file › Livewire\Features › FileUploadController@handle
GET|HEAD storage/{path} .................................................................................... storage.local
GET|HEAD up ..............................................................................................................
このように、クライアントとサーバーを活発に通信してリアルタイムにデータを書き換えていくところが、live wire たる所以な気がしました。
何回も押すと、押す度リクエストが走るので、とても働き屋のくらげです。
まとめ
Livewire で複雑なシステムを組んでいないので、パフォーマンス・速度等はなんともですが、どうやって値を書き換えているかのロジックを画面の情報から追ってみるのは、おもしろかったです。
コンポーネント指向っぽく Blade テンプレートを使って運用できるので、これまでやってきた Laravel プロジェクトの一部を書き換えてみたりして、この先検証できればなあと思います。
粗雑で拙い文章をここまで読んでいただきありがとうございました。