Flatten
https://github.com/Anahkiasen/flatten/
Webサイトを作っているとどうしても気になるのがレスポンス速度。
認証だったり、DBから情報をひっぱったり、外部のAPIを叩いていたりと
最終的なHTMLを構成し吐き出すまでに様々な処理が挟まることで、イライラするサイトになってしまう事は良くあることです。
ECサイトなんかだと、購買意欲を削がないために0.5秒でも速く動くサイト作りが求められますよね。
そのための手段にページキャッシュがあります。
(ビューキャッシュやエレメントキャッシュと呼ぶことも)
これは動的ページを一定期間だけ静的ページとして扱ってしまう方法です。
Flattenを使えば簡単にページキャッシュが利用できます。
Laravelで使う
Flatten自体はLaravelじゃなくても利用出来ますが、Laravelでとても使いやすくなっています。
今回はLaravelの5系でどう使うのか紹介したいと思います。
準備
まずはcomposerでインストール
composer.jsonのrequireに1行追加します。
"require": {
"laravel/framework": "5.1.*",
<< 省略 >>
"anahkiasen/flatten": "^1.1"
}
そしたらcomposer updateしましょう。
$ composer update anahkiasen/flatten
無事にインストール出来たらLaravelで使いやすくするために設定しましょう。
config/app.phpのprovidersとaiasesへFlattenの設定を追記します。
'providers' => [
/*
* Laravel Framework Service Providers...
*/
Illuminate\Foundation\Providers\ArtisanServiceProvider::class,
Illuminate\Auth\AuthServiceProvider::class,
// 省略 //
/**
* Flatten
*/
Flatten\FlattenServiceProvider::class, // この行を追記
],
'aliases' => [
'App' => Illuminate\Support\Facades\App::class,
'Artisan' => Illuminate\Support\Facades\Artisan::class,
'Auth' => Illuminate\Support\Facades\Auth::class,
'Blade' => Illuminate\Support\Facades\Blade::class,
// 省略 //
'Flatten' => Flatten\Facades\Flatten::class, // この行を追記
],
そして最後にFlatten用のconfigファイルを作ります。
artisanコマンドでも作れますが僕は直接コピーしちゃいました。
$ cp vendor/anahkiasen/flatten/config/flatten.php ./config/
使い方はさておきconfigファイルにはこんな項目があります。
<?php
return [
'enabled' => true,
'ignore' => [],
'only' => [],
'blockers' => [],
'lifetime' => 0,
'saltshaker' => [],
'timestamp' => true,
'minify' => false,
];
Viewでキャッシュしたい範囲を指定する
bladeテンプレートでは @cache
~ @endcache
で囲うだけで、その中をまるっとキャッシュしてくれるようになります。
@cache('greeting', 5) {{-- greetingというkeyで5分キャッシュする --}}
Hello, Sasakure.
@endcache
@cache
の第1引数でkeyを、第2引数にはキャッシュする時間を指定する。
第2引数を省略した場合はconfig/flatten.phpの lifetime値 が採用される。
単位は 分 となる。
たったコレだけで激重ページがチョッパヤになるのでとても嬉しい。
変数の扱いには注意が必要
さきほどのbladeテンプレートがPHPにコンパイルされるとこのようになります。
<?php echo Flatten\Facades\Flatten::section('greeting', 1, function() { ?>
Hello, Sasakure.
<?php }); ?>
@cache
~ @endcache
で囲った範囲を無名関数にぶっこんでキャッシュしているのが分かりますね。
そのため下記のような使い方をするとエラーになります。
<?php $name = 'Sasakure'; ?>
@cache('greeting')
Hello, {{ $name }}.
@endcache
これだと$nameなんて変数は無いよって怒られる。
そんな時はblade記法は使わずに書きましょう。
<?php $name = 'Sasakure'; ?>
<?php echo Flatten\Facades\Flatten::section('greeting', 1, function() use ($name) { ?>
Hello, <?= $name ?>.
<?php }); ?>
キャッシュのされかた
Flatten\Facades\Flatten::section()では $this->app['cache'] を利用しています。
つまりLaravelアプリケーション側のキャッシュ指定に合わせてくれます。
config/cache.phpでRedisを使うように設定していればRedisになるといった具合です。
ちなみにキャッシュのキープレフィックスには 'flatten-section-' が付きます。
(実際には更にアプリ側で指定したプレフィックスが付くはずです。)
ページ全体をキャッシュする
上述した方法だと、そもそもViewの前段(コントローラーやそこから呼び出す処理)が重い場合には効果が薄いです。
ページ全体をキャッシュしたいからコントローラーとか無視したいわ って場合にはFlattenミドルウェアを使いましょう。
app/Http/Kernel.phpのrouteMiddlewareに1行追加します。
protected $routeMiddleware = [
// 省略
'flatten' => 'Flatten\FlattenMiddleware', // この一行を追加
];
そうしましたら routesにてこんな感じでFlattenMiddlewareを咬ませす。
URLに応じてキャッシュしたレスポンスを返却してくれるようになります。
Route::group(['middleware' => 'flatten'], function () {
Route::get('home', 'HomeController@getIndex');
});
この例だとキャッシュがあればHomeControllerは呼ばれもしません。
予めキャッシュを作っておく機能まである
Flattenにはクローリング機能があります。
これは artisan flatten:build
というコマンドを叩く事でFlattenに全ページリクエストさせて予めキャッシュを作っちゃう機能です。
config/flatten.phpにて対象URLや除外URLなんかを指定する事も出来ます。
'ignore' => ['home/.+'],
こんな感じで正規表現で指定できます。複数指定も可能です。
デプロイスクリプトにキャッシュクリアコマンドと一緒に仕込んでおくと良いですね。