page-cache 绝对是一个了不起的神器,可能在访问应用后生成完整的 html 静态页面,再通过配置 nginx,下次访问时就可以直接读取静态页面,让你的站点速度快到飞起,完全可以构建成一个全静态化站点,再结合 vue 就可以有很好的交互体验
安装
$ composer require silber/page-cache
注册到中间件 app/Http/Kernel.php
protected $middlewareGroups = [
'web' => [
// ...
\Silber\PageCache\Middleware\CacheResponse::class,
],
];
访问应用时,就可以看到在 public 自动生成 page-cache 目录,生成的静态文件都置于此目录中,文件名与 url 一一对应
nginx 配置
location = / {
try_files /page-cache/pc__index__pc.html /index.php?$query_string;
}
location / {
try_files $uri $uri/ /page-cache/$uri.html /index.php?$query_string;
}
清除缓存
可以直接删除静态文件,也可以调用以下指令:
# 清空缓存
$ php artisan page-cache:clear
# 清空指定文件 {slug} 为 url 后缀 如清空 /1.html
$ php artisan page-cache:clear 1.html
指定路由缓存
如果不想全局应用缓存,将上文所说的全局缓存中间件去掉,在 app/Http/Kernel.php 的 $routeMiddleware 中新增:
protected $routeMiddleware = [
// ...
'page_cache' => \Silber\PageCache\Middleware\CacheResponse::class,
];
然后在需要的路由里直接指定使用中间件即可:
Route::get('/', 'TopicsController@index')->name('root')->middleware('page_cache');
自定义缓存
默认情况下,缓存目录是写在 public/page_cache ,如果我们的应用有多个域名,如 pc 端和 m 端,就会导致缓存互相覆盖。通过查找源码可发现,缓存目录是由 vendor/silber/page-cache/src/Cache.php 以下代码定义的
// 获取目录
protected function getDefaultCachePath()
{
if ($this->container && $this->container->bound('path.public')) {
return $this->container->make('path.public').'/page-cache';
}
}
// 定义目录的接口
public function setCachePath($path)
{
$this->cachePath = rtrim($path, '\/');
}
我们可以 参照文档 中的 Customizing what to cache 重写中间件自定义缓存目录
$ php artisan make:middleware CacheResponse
将以下代码粘贴到新建的 CacheResponse 中
namespace App\Http\Middleware;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Silber\PageCache\Middleware\CacheResponse as BaseCacheResponse;
class CacheResponse extends BaseCacheResponse
{
public function __construct(Cache $cache)
{
parent::__construct($cache);
// 根据域名生成目录
$cache_dir = request()->getHost();
$this->cache->setCachePath("cache/{$cache_dir}");
}
protected function shouldCache(Request $request, Response $response)
{
// In this example, we don't ever want to cache pages if the
// URL contains a query string. So we first check for it,
// then defer back up to the parent's default checks.
// 不缓存带有参数的 url
if ($request->getQueryString()) {
return false;
}
return parent::shouldCache($request, $response);
}
}
将 app/Http/Kernel.php 的中间件改为 \App\Http\Middleware\CacheResponse::class
接下来缓存文件会生有到 public/cache/域名 目录下,根据目录去修改 nginx 配置