
九保すこひです(フリーランスのITコンサルタント、エンジニア)
さてさて、Laravel
やPHP
に限らずプログラムを書くときにはいつも「表示速度」がテーマのひとつとしてついてまわると思います。
もちろん、最近はスマートフォンでもブロードバンド化してますし、レンタルサーバーやデバイスが高性能になったこともあって、昔ほどウェブページの表示が遅く感じられることは少なくなってきました。
ただ、やはり高速表示とフレームワークの多機能化は相容れない関係にあるのも事実で、Laravel
のバージョン5が公開されたときは「4.2より表示速度が遅くなってしまった」というような評価があったりもしました。
LaravelのテンプレートエンジンBlade
はアクセスがあるたびに/storage/framework/views
フォルダの中にキャッシュを作成するようになりより高速化されていますが、それでもPHPコードが中に含まれている状態ですので、やはり静的なHTMLと比べる表示が遅くなってしまいます。
そこで!
今回はより高速表示をめざすために、Laravel
+ Blade
で静的なHTMLファイルを作成して直接そのファイルにブラウザからアクセスして高速表示できるようにしてみたいと思います。
ぜひ皆さんのお役に立てると嬉しいです
目次 [非表示]
準備する
専用フォルダをつくる
まずは静的なHTMLファイルを保存しておくフォルダを作成します。場所は、/public/statics
にします。
そして、そのままではフォルダに書き込み権限がありませんのでLaravel
がファイル作成することができません。そのため、以下のコマンドを実行して権限をつけておきましょう。
sudo chmod 707 statics -R
これで、このフォルダにHTMLファイルが作成されると、https://example.com/statics/********.html
でファイルにアクセスできるようになります。
静的HTMLを作成する部分をつくる
では、Laravel
側で静的HTMLをつくるコードを書いていきましょう。
※ なお、今回はユーザーのプロフィールを表示する静的HTML作成のサンプルになります。
ルートをつくる
まずはルートを作成します。routes/web.php
を開いて以下を追加してください。
Route::get('generate_static/{mode}', 'HomeController@generate_static');
※ mode
は「どこの静的HTMLを作成するか」を区別する文字列(例えば、user
やproduct
など)を想定したものになっていて、その他のパラメータはRequest
で取得することになります。
ビューをつくる
続いてビューです。
といっても、ここは通常のBlade
テンプレートを作るのと全く同じですので、/resources/views/user/profile.blade.php
で保存します。
<html>
<body>
<ul>
<li>名前: {{ $user->name }}</li>
<li>Email: {{ $user->email }}</li>
<li>登録日: {{ $user->created_at->format('Y/m/d') }}</li>
</ul>
</body>
</html>
中身はシンプルに、
- ユーザー名
- メールアドレス
- 登録日
の3つを表示するだけになっています。
モデルにメソッドを追加する
どこからでも静的HTMLファイルを作成できるにしておきたいので、今回はUser
モデルの中にgenerate_static()
というメソッドを追加しておきます。
<?php
// 省略
class User extends Authenticatable
{
// 省略
// Accessor
public function getStaticUriAttribute() {
// 静的HTMLファイルのURI
return '/statics/user_profile_'. $this->id .'.html';
}
// Others
public function generate_static() {
// 静的HTMLのデータを作成
$path = public_path($this->uri);
$html = view('user.profile')
->with('user', $this)
->render();
return file_put_contents($path, $html);
}
}
また、getStaticUriAttribute()
は$user->static_uri;
とするだけで静的HTMLファイルのURI
を取得できるAccessor
です。
イベントを作成する
前項目で静的HTMLファイルを作成できるようになりましたが、データ更新や削除をするたびにgenerate_static()
を実行するのはめんどうですし、もしかすると実行を忘れてしまうことがあるかもしれません。
そのため、データを更新/削除された場合は必ず静的HTMLファイルを自動的に操作するようにイベントを作成しておきましょう。
データ更新したとき
まず以下のコマンドでUserSaved
イベントを作成します。
php artisan make:event UserSaved
すると、/app/Events/UserSaved.php
にファイルが作成されるので内容を以下のように変更します。
<?php
namespace App\Events;
use App\User;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class UserSaved
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public function __construct(User $user)
{
$user->generate_static();
}
// 省略
やっていることは、先ほどUser
モデルに追加したgenerate_static()
を実行して静的HTMLファイルを作成しているだけです。
データ削除したとき
では、続いてデータ削除されたときのイベントUserDeleted
です。以下のコマンドを実行してください。
php artisan make:event UserDeleted
そして、/app/Events/UserDeleted.php
を開いて以下のように変更します。
<?php
namespace App\Events;
use App\User;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class UserDeleted
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public function __construct(User $user)
{
$path = public_path($user->static_uri);
@unlink($path);
}
// 省略
なお、イベントはファイルを作成するだけでは実行はされませんので、User
モデルに以下のように登録しておきましょう。
<?php
// 省略
class User extends Authenticatable
{
protected $dispatchesEvents = [
'saved' => UserSaved::class,
'deleted' => UserDeleted::class
];
これで、ユーザーが登録されると以下のようにHTMLファイルが作成されることになります。
実際にアクセスすると次のようになります。
お疲れ様でした!
おまけ:静的HTMLファイルを削除する独自コマンドをつくる
もしかすると、一気に作成した静的HTMLファイルを削除する必要がでてくるかもしれません。
そんなときのために、おまけとして全ての静的HTMLファイルを削除する独自コマンドの作り方を紹介したいと思います。
まず、以下のコマンドを実行してください。
php artisan make:command ClearStaticCommand
/app/Console/Commands/ClearStaticCommand.php
を開いて中身を以下のように変更します。
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use League\Flysystem\Filesystem;
class ClearStaticCommand extends Command
{
protected $signature = 'static:clear';
protected $description = 'Clear static files';
// 省略
public function handle()
{
$files = glob(public_path('statics/*'));
foreach($files as $file) {
if(is_file($file)) {
@unlink($file);
}
}
}
}
そして、app/Console/Kernel.php
内に以下のように登録するとphp artisan static:clear
コマンドが実行できるようになります。
<?php
// 省略
class Kernel extends ConsoleKernel
{
protected $commands = [
ClearStaticCommand::class
];
おわりに
ということで、今回はLaravel
で静的HTMLファイルを作成して高速表示できるようにしてみました。
アクセス数が非常に多いサイトでしたらキャッシュをとるよりも高速な表示ができると思います。
・・・とはいえ、プログラミング業界も常に進歩していて、かねてより実装が期待されていた「JITコンパイラ」がPHP 7.4&8に実装されるということなので更にPHPは高速表示が可能にはなるようです。
さすがにHTML単体より早くはならないとは思いますが、私の開発者のひとりとして早く試してみたい限りです。(さすがに正式版になってからですが)
みなさんもぜひサイトの高速化に注目した開発を進めてみてはいかがでしょうか。
ではでは〜!