Laravel 使用 laravel-httpcache 扩展包的正确姿势

为了提高网页的加载速度,除了使用 cdn 和静态文件浏览器缓存以外,还有使用 http cache 的方法,对 html 请求进行缓存。barryvdh/laravel-httpcache 是个 laravel http 缓存的包,本文介绍下这个包的正确使用姿势。

安装和启用

参考 github 上 barryvdh/laravel-httpcache 的说明,不再赘述。安装完记得
php artisan vendor:publish --provider="Barryvdh\HttpCache\ServiceProvider" 生成配置文件。

配置

该包通过中间件的方式提供缓存服务,默认的 config/httpcache.php 文件长这样:

<?php
return array(
    'enabled' => true,
    'esi' => false,
    'cache_dir' => storage_path('httpcache'),
    'options' => array(
    ),
);

然而按照默认配置,并加上中间件'Barryvdh\HttpCache\Middleware\CacheRequests',的话,cache 是根本不起作用的, 甚至会使原本的登录、注销等操作发生异常,需要修改配置。该包脱胎于 Symfony 的 HttpCache,配置也基本一致,options 里的选项有:

  • debug :调试,启用后在 response header 里会带上X-Symfony-Cache的调试信息(默认 false)。
  • default_ttl:缓存默认到期时间(默认为 0,所以根本不会产生缓存,需要改成一个正整数)。
  • private_headers:(默认: Authorization and Cookie,需要去掉 Cookie,laravel 的 web 中间件组必然会产生 Cookie)
  • allow_reload:(默认 false)
  • allow_revalidate:(默认 false)
  • stale_while_revalidate:(默认 2 )
  • stale_if_error:(默认 60 )

不多 bb 因为我也不太明白,为了防止出现偏差,这里请看原文档说明:HttpCache | Symfony API

改完后的配置长这样:

<?php
return array(
    'enabled' => true,
    'esi' => false,
    'cache_dir' => storage_path('httpcache'),
    'options' => [
        'debug'                  => env('APP_DEBUG', false),
        'default_ttl'            => 60,
        'private_headers'        => ['Authorization'],
        'allow_reload'           => true,
        'allow_revalidate'       => true,
        'stale_while_revalidate' => 2,
        'stale_if_error'         => 60,
    ],
);

另外并不是所有页面都要做 http 缓存的,比如登录相关的页面就不应该缓存,将 \Barryvdh\HttpCache\Middleware\CacheRequests::class,中间件放入 app/Http/Kernel.php 里的全局中间件组(protected $middleware)是不合适的(除非是全站静态化的网站)。我的做法是加到路由中间件组(protected $routeMiddleware):

    protected $routeMiddleware = [
        //something else...
        'http.cache' => \Barryvdh\HttpCache\Middleware\CacheRequests::class,
        'ttl' => \Barryvdh\HttpCache\Middleware\SetTtl::class,
    ];

在需要加缓存的路由条目上加 http.cache 中间件,配合 ttl 中间件修改默认过期时间:

Route::get('/', 'PostController@index')->name('post.index')->middleware('http.cache');
Route::get('/{post}', 'PostController@show')->name('post.show')->middleware(['http.cache', 'ttl:61']);

效果

开启 debug 情况下,在返回的 header 里看到 X-Symfony-Cache: GET /: stale, invalid, store ,再次访问后变成 X-Symfony-Cache: GET /: fresh,说明缓存成功并命中了。

参考文档