基於 Laravel 中介軟體簡單地整合 HTTP/2 伺服器資源推送

半夏發表於2017-06-10


我們都知道隨著技術的迅速發展,如果不偶爾停下腳步環顧四周,將會錯過很多。

HTTP/2 ,很熱的一個技術話題。實話說, Ben Ramsey 在 laracon 對此發表演講之前,我對其一無所知。而本文將介紹 HTTP/2 眾多理念中的一個——伺服器資源推送。

讀者想要了解更多,可觀看影片或者訪問他的網站。瞭解後,你會發現實現伺服器推送、預載入資源資料簡單地讓人大吃一驚。基本上,只要在伺服器端響應的頭部新增一個帶有整個頁面資源的特殊“ link ”,如果伺服器和瀏覽器都支援的話,這些資源將以高效的網路方式拉取獲得(具體點選連結 )。

在 Ben 的演講中,他舉了如何在 laravel 中實現的例子,這是其中一種方法。

  return response($content, $status)
  ->header('Link', '; rel=preload; as=style', false)
  ->header('Link', '; rel=preload; as=script', false);

當然,如果這樣一個一個資源實現推送是件可怕的事情。但是,感謝活躍的 laravel 使用者,目前已經有兩個基於 laravel 中介軟體自動整合資源實現統一推送的包了。

其中一個是 Tome Schlick 建立的,另一個是 Jacob Bennett。大體上,這兩個包沒什麼區別,但是在如何整合資源方面兩個作者都有各自的想法。

Tome

*實現

先在 config/server-push.php 中,手動定義預設的資原始檔包括 style、script、image 等。同時,並配置是否從 mianfest 中自動匯入資源資料。

return [
    // Include assets you want to link on every page load here.
    'default_links' => [
        'styles' => [
        ],
        'scripts' => [
        ],
        'images' => [
        ],
    ],

    'autolink_from_manifest' => true,

    'manifest_path'   => public_path('build/rev-manifest.json')
];

中介軟體—— Http2ServerPushMiddleware.php 先驗證請求是否為頁面請求,若為頁面請求,則將拼接成的“link“新增到響應的頭部中。

   public function handle(Request $request, Closure $next)
    {
        $this->response = $next($request);
        if ($this->shouldUseServerPush($request)) {
            $this->addServerPushHeaders();
        }
        return $this->response;
    }

    protected function addServerPushHeaders()
    {
        if (app('server-push')->hasLinks()) {
            $link = implode(',', app('server-push')->generateLinks());
            $this->response->headers->set('Link', $link, false);
        }
    }

    protected function shouldUseServerPush(Request $request) : bool
    {
        return !$request->ajax();
    }

到這裡,你可能會想那配置檔案中的那些資料用處在哪呢?
哈哈,接下來 ServiceProvider 便會用到了,下列方法中先新增手動填寫的預設資源連結,接著新增 mainfest 中的資源資料。具體實現請看詳細程式碼,這裡就不多闡述了。

public function register()
{
        $this->app->singleton('server-push', function () {
            return new HttpPush();
        });
        $this->app->alias('server-push', HttpPush::class);
        $this->registerDefaultLinks();
        $this->registerElixirLinks();
}
  • 安裝

秉著實用主義的心理,安裝使用才是最重要的了!

composer 安裝:

composer require tomschlick/laravel-http2-server-push

config/app.php 中註冊 provider:

\TomSchlick\ServerPush\ServiceProvider::class,

app/Http/kernel.php中註冊中介軟體:

protected $middleware = [
    \TomSchlick\ServerPush\Http2ServerPushMiddleware::class,
];

注意,你還可以在專案中任何地方使用下列方法根據具體情況新增區域性的資原始檔,很方便有沒有。

 pushStyle($pathOfCssFile);
 pushScript($pathOfJsFile);
 pushImage($pathOfImageFile);

Jacob

  • 實現

相比之下,這個包較為簡練,所有的邏輯全部都在中介軟體中處理。

將需要推送資源的路由加上中介軟體—— AddHttp2ServerPush ,中介軟體將會自動那些需要伺服器來推送的 css,style,image 等資源並將它們加到伺服器響應的頭部。

public function handle(Request $request, Closure $next, $limit = null)
    {
        $response = $next($request);
        if ($response->isRedirection() || !$response instanceof Response || $request->isJson()) {
            return $response;
        }
        $this->generateAndAttachLinkHeaders($response, $limit);
        return $response;
    }

上述是部分中介軟體程式碼。首先可以看出這是一個後置中介軟體。然後流程這樣走:校驗伺服器響應和瀏覽器請求,若非跳轉響應並請求非傳送 Json 資料——>獲取伺服器響應想要推送的資源——>基於資源裡的檔名字尾即檔案型別組合生成頭部字串——>新增到響應的頭部中。

  • 安裝

composer 安裝:

 $ composer require jacobbennett/laravel-http2serverpush

千萬不要忘記把中介軟體新增
\JacobBennett\Http2ServerPush\Middleware\AddHttp2ServerPush
app/Http/Kernel.php 中!可直接放到 web 組中,一勞永逸。也可根據具體需求新增到個別路由中。

protected $middlewareGroups = [
    'web' => [
        ...
        \JacobBennett\Http2ServerPush\Middleware\AddHttp2ServerPush::class,
        ...
    ],
    ...
];

講了這麼多,選用哪個包還是依據具體專案和個人偏好來決定。Jacob 的包必須掃描所有的檢視來獲取全部資源。相比之下,Tome 的包需要手動操作,但是使用者能夠更方便地控制。

實踐是檢驗真理的唯一標準,為了提高 laravel 應用效能,不要猶豫來,動手試試看吧!

參考連結:https://laravel-news.com/http2-server-push-middleware\JacobBennett\Http2ServerPush\Middleware\AddHttp2ServerPush
https://github.com/JacobBennett/laravel-HT...
https://github.com/tomschlick/laravel-http...

本作品採用《CC 協議》,轉載必須註明作者和本文連結
step by step

相關文章