PWA踩坑記,手把手教學vue搭建PWA

BillsonKam發表於2018-09-08

PWA離線應用

  • 前端的日益發展,都離不開效能優化的手段,包括 CDN、CSS Sprite、檔案的合併壓縮、非同步載入、資源快取等等。更多的時候為了減少使用者量的請求,於是就有了PWA,秒開網站,離線訪問等等的炫酷裝B技能。

  • 於是就迫不及待想拉開PWA神祕的面紗,使用到下面的:

    • vuecli3.0
    • register-service-worker
    • 一臺不太卡的安卓(安卓版本不夠高,Chrome不能新增到桌面上)
  • 先上圖:

PWA踩坑記,手把手教學vue搭建PWA

vuecli3.0

  • vuecli的最新版本vuecli3.1,通過 npm install -g vue@cli 來安裝
  • vuecli3.0多了很多神奇方便的功能,作者應該想要簡化開發者的開發過程,有了炫酷的視覺化介面GUI,通過 vue ui 可在瀏覽器檢視、安裝、管理包等等
  • vuecli3.0還整合了service worker、一些常用的語法檢測,自動化測試等等的工具

register-service-worker

  • 使用過 create-react-app 的小夥伴肯定知道,react官方推薦的腳手架中預設佩帶有 register-service-worker的包,經過打包後,額外生成以下檔案:

    • `manifest.json: 可配置該應用在瀏覽器,桌面中的開啟方式,應用名字,應用執行動畫等等

    • service-worker.js: 可看到被壓縮打包好的service worker的安裝,啟用、解除安裝等等的功能與配置

    • asset-manifest.json: 離線下強制快取的檔案,使得APP可在離線下執行

有關service worker的詳細問題可通過以下連結檢視:

後端配置

  • 離線快取需要後臺配合,通過有效的快取達到離線的效果,怎樣的快取才是有效的?就是強制快取啊!
  • 強制快取與協商快取都為快取,主要有以下的不同:
    • 協商快取:有快取,但是會主動請求伺服器後,伺服器不返回任何資源
    • 強制快取:有快取,不會請求伺服器,使用本地或者記憶體或者service worker中的快取
  • 先科普下快取的分佈圖:

PWA踩坑記,手把手教學vue搭建PWA

  • 在Chrome控制檯的 Network 中檢視頁面載入時所下載的資源,會發現有些資源會有cache from diskcache from memory等等,還會有些資源直接顯示該資源的資原始檔大小,那麼這是怎麼回事呢?
    • cache from disk: 這是強制快取,表示該資源從本地的快取檔案中拉取資源
    • cache from memory:這是強制快取,表示該資源從記憶體中拉取資源
    • 直接顯示資源大小:這是協商快取或者是不存在快取,每次都是從伺服器下載該資源

PWA踩坑記,手把手教學vue搭建PWA

  • 這裡就以express為例子,需要設定公用過濾器,為GET請求設定強制快取,時間為兩小時
//以下的Code設定了公用的響應頭中返回的強快取時間、CORS跨域等等
app.all("*", function(req, res, next) {
	if(req.path !== "/" && !req.path.includes(".")) {
		res.header("Access-Control-Allow-Origin", req.headers["origin"] || "*")
		res.header("Access-Control-Allow-Credentials", true)
		res.header("Access-Control-Allow-Headers", 'Content-Type,Content-Length, Authorization, authorization,\'Origin\',Accept,X-Requested-With')
		res.header("Access-Control-Allow-Methods", "POST,GET,PUT,DELETE,OPTIONS")
		res.header("Content-Type", "application/json;charset=utf-8")
		if(req.method.toUpperCase() === "GET"){
			res.header("Cache-Control","max-age=7200")
		}
	}
	next()
})
複製程式碼

通過設定請求快取後,靜態資源都必須設定為強制快取,才能達到離線訪問的效果。

  • 這次採坑中遇到神坑的問題,當伺服器設定了響應頭res.header("Access-Control-Allow-Origin", req.headers["origin"] || "*")後,如果同一個瀏覽器都是GET到該伺服器的請求,則會報錯,報錯中顯示跨域禁止,因為上面設定的強制快取的原因,瀏覽器會主動快取該GET請求,所以快取中的GET請求的響應頭中的Access-Control-Allow-Origin(設定允許域名跨域)會顯示第一次發出GET請求的域名,而第二次同一個瀏覽器不同的域名去GET這個請求,則Access-Control-Allow-Origin返回的是第一個請求的域名,所以會報錯。

  • 最後通過打包後,第一次訪問SPA時,service worker會自動快取該SPA中所需要的資源,而AJAX請求的資料,則是被瀏覽器主動快取的,從而可以達到快取的效果,在安卓的高版本的chrome中,還可以將該SPA像APP一樣打包下載到桌面上,有自己的開機動畫等等。

  • 在評論處感謝王品洲的提醒:(PC)Chrome不能新增到桌面上 :可以試試 F12->Application-> Manifest ->Add to homesreen

相關文章