Laravelで静的HTMLページを作って高速表示させる

さてさて、LaravelPHPに限らずプログラムを書くときにはいつも「表示速度」がテーマのひとつとしてついてまわると思います。

もちろん、最近はスマートフォンでもブロードバンド化してますし、レンタルサーバーやデバイスが高性能になったこともあって、昔ほどウェブページの表示が遅く感じられることは少なくなってきました。

ただ、やはり高速表示とフレームワークの多機能化は相容れない関係にあるのも事実で、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を作成するか」を区別する文字列(例えば、userproductなど)を想定したものになっていて、その他のパラメータは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単体より早くはならないとは思いますが、私の開発者のひとりとして早く試してみたい限りです。(さすがに正式版になってからですが😊)

みなさんもぜひサイトの高速化に注目した開発を進めてみてはいかがでしょうか。

ではでは〜!

この記事が役立ちましたらシェアお願いします😊✨