Laravel 结合 Nginx 实现 Web 页面的纯静态极限访问性能

最新在用 Laravel 做一个博客信息聚合的小项目,考虑到内容的更新频率和目前项目的价值,思考了下怎么尽最大可能节省服务器计算资源,最好是能够第一次访问时生成内容后,在内容没有变化时,直接以纯静态的方式直接输出,完全不要有 PHP-FPM 的参与。在经过一番尝试后,结合 Nginx 终于实现了这个想法。

整个逻辑不复杂,但在 Nginx 配合的这一层花了些时间,主要还是对 Nginx 的配置了解的不够深入。核心流程就两步:

  1. 实现一个新的 Laravel 视图加载处理方法。即在默认的 view 方法基础上,添加输出前的渲染结果保存逻辑。
  2. 使 Nginx 优先读取缓存的渲染内容,如果没有渲染时再执行 Laravel 的处理逻辑。

下面分别针对这两步做一个详细的说明。

首先是第一步的保存视图渲染内容,我写了一个全局函数,主要代码如下:

<?php
use Storage;

if (! function_exists('staticize_view')) {
    function staticize_view($view = null, $data = [], $mergeData = [])
    {
        $viewObject = view($view, $data, $mergeData);

        $filename = request()->path();

        if (substr($filename, -1) != '/') {
            $filename .= '.html';
        }

        if (substr($filename, -5) != '.html') {
            $filename .= 'index.html';
        }

        if (substr($filename, 0, 1) != '/') {
            $filename = '/'.$filename;
        }

        Storage::disk('local')->put('staticize_view'.$filename, $viewObject->render());

        return $viewObject;
    }
}

然后根据需要,再需要实现静态化访问的控制器方法中替换 view 函数为 staticize_view 就可以了。生成的渲染内容文件以 .html 后缀的形式保存在项目的 storage/app/staticize_view/ 目录下。

接下来就是最重要的第二步,实现 Nginx 默认优先输出静态缓存内容的行为。这一步需要利用 Nginx 的 try_files 指令。核心配置如下:

location / {
    root /Projects/zzxworld/storage/app/staticize_view;
    index index.html;
    try_files $uri $uri/ $uri.html @default;
}

location @default {
    root /Projects/zzxworld/public;
    index index.php;
    try_files $uri $uri/ /index.php?$query_string;
}

try_files 是基于 root 来查找目录的,所以需要利用两个 location 分别来实现先静态目录查找,然后再引导到 PHP 处理的流程。我开始不了解 try_files 的特性,一直想用一个 locationtry_files 来实现,浪费了一些时间。

posted @ 2020-10-24 09:37  zzxworld  阅读(277)  评论(0编辑  收藏  举报