前端開發必須瞭解的 Nginx 單頁加載優化

  • 作者:XUXIN

  • 原文鏈接:https://xuxin123.com/web/nginx-spa-load/

  • 原文標題:Nginx 單頁加載優化

網頁加載

首先我們要看一下我們網頁加載到底中間是個什麼流程,那些東西比較耗費時間,比如我們訪問 github:

從圖中可以看出從與服務器建立連接,到接收數據,這裏的時間花費是非常多的,當然還有 DNS 解析,不過這裏有本地緩存,所以基本沒有時間。

gzip - 減少加載體積

首先我們可以通過 gzip 對我們的js以及css進行壓縮:
vue.config.js:

在 nginx 裏開啓 gzip:

server 模塊:

這裏簡單說明一下吧,

總結一下就是你如果打包後有.gz文件,只需要開啓gzip_static即可,如果沒有那麼得啓用gzip實時壓縮,不過我建議使用前者,另外 gzip 的適用於文本類型,圖片之類的使用的話會適得其反,故gzip_types請適當設置。

想看 gzip 是否成功啓用可以通過,查看返回的 header 頭Content-Encoding: gzip,以及查看文件的 size,這裏可以看到我們原來文件的是 124kb,而返回的 gzip 文件爲 44kb,壓縮效率還是蠻大的:

緩存控制 - 沒有請求就是最好的請求

瀏覽器於服務器的緩存交互,細說起來可就多了,想了解完整的請看其他人整理的文章吧,我只是這裏從配置上略說一下:

協商緩存

Last-Modified

我們的單頁入口文件是index.html,這個文件呢決定了我們要加載的 js 以及 css,故我們給 html 文件設置協商緩存Cache-Control no-cache,當我們首次加載時 http 的狀態碼爲 200,服務器會返回一個Last-Modified表示這個文件的最後修改時間,再次刷新時瀏覽器會把這個修改時間通過If-Modified-Since發送給服務器,如果沒有變動(Etag 也會校驗),那麼服務器會返回 304 狀態碼,說我的文件沒有變,你直接用緩存吧。

Etag

HTTP 協議解釋Etag被請求變量的實體標記,你可以理解爲一個 id,當文件變化了,這個 id 也會變化,這個和Last-Modified差不多,服務器會返回一個Etag,瀏覽器下次請求時會帶上If-None-Match,進行對比返回,有些服務器的 Etag 計算不同,故在做分佈式的時候可能會出問題,文件沒改動不走緩存,當然你可以關閉這個只使用Last-Modified

強緩存

我們的單頁應用打包時 webpack 等工具是會根據文件的變化生成對應的 js 的,也就也是文件不變的話 js 的 hash 值不變,故我們在加載 js 等文件時可以使用強緩存,讓瀏覽器在緩存時間類不進行請求,直接從緩存裏面取值,比如上面我們通過設置 expires(Cache-Control 也行,這個優先級更高)爲 30 天,那麼瀏覽器下此訪問我們相同的緩存過的 js 和 css 時(緩存時間內),就直接從緩存裏面拿(200 from cache),而不會請求我們的服務器。

注意:此方法是基於上述打包生成 hash 而言的,假如你生成的是 1.js,2.js 之類的,那麼你修改了 1.js 裏面的類容,打包出來的還是 1.js,那麼瀏覽器還是會從緩存裏面拿,不會進行請求的。也就是說使用此方式需要確保你修改了文件打包後修改的 hash 值需要變動。

強制刷新

強緩存用得好的話是飛一般的感覺,但是如果在錯誤情況下使用就老是走瀏覽器緩存,如何清理這個呢,我們常用的方式是Ctrl+F5或者在瀏覽器控制檯上把 Disable cache 給勾上,實際上這個是在請求文件時會自動加上一個 header 頭Cache-Control: no-cache,也就是說我不要緩存,那麼瀏覽器會老老實實的向服務器發出請求。

長連接 - 減少握手次數

TCP 握手以及 TLS 握手還是比較費時的,比如以前的 http1.1 之前的連接就是每一條都要進過 TCP 三次握手,超級費時,還好 1.1 默認使用了長連接,可以減少握手開銷,但是假如你做大文件上傳時會發現超過一定時間會斷掉,這是由於Nginx默認的長連接時間爲 75s,超過了就會斷開,當你的網頁確實要加載很多很多東西時可以適當把這個時間延長一點,以減少握手次數(keepalive_requests 可以限制 keep alive 最大請求數),至於大文件上傳嗎你可以選擇分片上傳,這裏就不做介紹了。

server:

HTTP/2 - 更安全的 HTTP、更快的 HTTPS

現在很多網站都啓用了HTTP/2HTTP/2最大的一個優點是完全保持了與HTTP/1的兼容,HTTP/2 協議本身並不要求一定開啓SSL,但瀏覽器要求一定要啓用SSL才能使用HTTP/2,頭部壓縮、虛擬的 “流” 傳輸、多路複用等技術可以充分利用帶寬,降低延遲,從而大幅度提高上網體驗。Nginx 開啓相當簡單:

HSTS - 減少 302 重定向

現在大多數網站都是https的了,但是有個問題就是用戶在輸入網址時一般來說不會主動輸入 https,走的還是 80 端口,我們一般會在 80 端口進行rewrite重寫:

但這種重定向增加了網絡成本,多出了一次請求,我想下次訪問時直接訪問https怎麼處理?我們可以使用HSTS,80 端口的不變,在 443 端口的 server 新增:

這相當於告訴瀏覽器:我這個網站必須嚴格使用HTTPS協議,在在max-age時間內都不允許用HTTP,下次訪問你就直接用HTTPS吧,那麼瀏覽器只會在第一次訪問時走 80 端口重定向,之後訪問就直接是HTTPS的了(includeSubDomains 指定的話那麼說明此規則也適用於該網站的所有子域名)。

Session Ticket-https 會話複用

我們知道 https 通信時,SSL 握手會消耗大量時間,使用非對稱加密保護會話密鑰的生成。而真正傳輸的是通過對稱加密進行通信傳輸。那麼我們每次刷新都進行 SSL 握手太費時間了,既然雙方都拿到會話密鑰了,那麼用這個密鑰進行通信不就可以了,這就是會話複用。
服務器把密鑰加密後生成 session ticket 發送給客戶端,請求關閉後,如果客戶端發起後續連接(超時時間內),下次客戶端再和服務器建立SSL連接的時候,將此 session ticket 發送給服務器,服務器解開session ticket後拿出會話密鑰進行加密通信。

本系列更新只有利用週末和下班時間整理,比較多的內容的話更新會比較慢,希望能對你有所幫助,請多多 star 或點贊收藏支持一下。

本文地址:https://xuxin123.com/web/nginx-spa-load

公衆號

Node 社羣

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/PN3bSFqTQHFu5P8PoBm7mw