引言
PWA(Progressive web apps, 漸進式Web應用),近兩年被炒的十分火爆,它有什麼優點呢?
- 可以生成桌面小圖示,不需要開啟瀏覽器,方便使用者訪問
- 通過網路快取提升頁面訪問速度,達到漸進式的頁面甚至離線訪問,提升使用者體驗
- 實現類似app的推送功能,生成系統通知推送給使用者
上面的這些優點足以讓它吸引大量的開發者來探索和應用,畢竟對於web應用來說,使用者體驗才是檢驗web應用的好壞的至高標準,而PWA的這些優點恰恰是開發者在開發時一直追求的
Service Worker
service worker是實現PWA的核心,service worker是一個獨立的瀏覽器執行緒,不會對當前程式的執行執行緒造成阻塞,通過service worker可以實現頁面離線訪問、使用者訊息推送等功能
生命週期
service worker生命週期完全獨立於網頁,因此,要想網頁中使用service worker,需要先註冊,註冊後瀏覽器會在後臺啟動相關的安裝步驟,一般情況下,我們需要service worker快取一些靜態檔案,因此安裝過程中會對指定的靜態檔案進行快取,若快取成功,則service worker安裝成功,若中間有任何一個檔案快取失敗,則service worker安裝失敗,會在下次重啟時再次嘗試,下面來看一個具體的生命週期圖(來源developer.mozilla.org/zh-CN/docs/…):
簡單應用
看來上面的介紹,是不是躍躍欲試呢?接下來將用程式碼來簡單使用一下service worker,快取頁面中的css、js檔案,具體例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="/cache1.css">
<title>pwa</title>
</head>
<body>
<div id="app">test1</div>
<!-- built files will be auto injected -->
<script src='/cache1.js'></script>
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
navigator.serviceWorker.register('/sw.js').then((registration) => {
console.log('Service Worker Registration')
}, (err) => {
console.log(err)
})
})
}
self.addEventListener('fetch', () => {
console.log('ss')
})
</script>
</body>
</html>
複製程式碼
sw.js:
var cacheName = 'my-cache'
var cacheList = ['/cache1.css', '/cache1.js']
self.addEventListener('install', function(event) {
event.waitUntil(
// 安裝成功後向caches中存入需要快取的檔案
caches.open(cacheName).then(function (cache) {
return cache.addAll(cacheList)
})
)
});
// 監聽service worker fetch
self.addEventListener('fetch', function (event) {
event.respondWith(
caches.match(event.request)
.then(function(response) {
// 在快取中查詢到匹配的請求,就從快取返回
if (response) {
console.log(response)
return response;
}
// 快取中沒有查詢到對應請求,繼續網路請求
return fetch(event.request);
}
)
);
})
複製程式碼
如上例所示,利用service worker快取了頁面請求中cache1.js、cache1.css,然後再重新整理一下網頁,網頁請求就會變成下圖這樣:
在網路請求面版可以很清楚看到這兩個檔案是從ServiceWorker中請求出來的,可能有些人對caches這個快取物件還不是很瞭解,這有一篇文章可以幫助大家理解:傳送門vue-cli3中的pwa
vue最新腳手架中整合了pwa的外掛,將pwa的實現變得更加的簡單,只需要在vue.config.js檔案中配置pwa屬性就可以自動生成對應的service-worker.js配置檔案,配置參考:傳送門,這裡面最核心的就是整合了google團隊開發的Workbox,因此關於更加詳細的pwa配置可以參考:傳送門,這裡麵包含workbox所有配置項,這裡面需要關注的是runtimeCaching屬性,這個屬性提供五種快取策略:
- CacheFirst:優先取快取中的資料,若沒有則請求網路,請網路也失敗就會報錯
- CacheOnly:只從快取中獲取,若沒有則報錯
- NetworkFirst:優先從網路獲取,若沒有則從快取中獲取,快取獲取失敗則報錯
- NetworkOnly:只從網路獲取,若沒有則報錯
- StaleWhileRevalidate:同時從網路與快取獲取,如果快取可用,取快取資料,否則從網路中請求,同時快取會隨著網路請求而更新
更加詳細的快取策略可以參考傳送門,這裡的快取策略還需要注意的一個問題就是同源策略的問題,一般情況下workbox不會快取跨域的資源請求,因為在快取跨域資源時,workbox無法檢測跨域請求是否成功,如果失敗,使用者將無法獲取響應資料,但是在NetworkFirst和StaleWhileValidate策略下,可以快取跨域資源,因為這兩個策略的快取會定期更新,即便出現失敗請求,快取的時間也是短暫的,具體詳情可以參考傳送門
相容性
ServiceWorker這麼牛,是不是就沒有什麼問題了呢,它最大的問題應該就是它的相容性問題了,iOS11.3之前都不支援,具體詳情參考:傳送門,因此vue腳手架在整合時預設在ios下是關閉的
總結
PWA確實是當下很熱門的技術,因為它提升了web應用的體驗,甚至達到可以和原生app體驗相提並論,但是它的問題就是相容性問題,相信如果相容性問題得到解決,這種技術一定會被大面積推廣到實際應用,希望通過這篇文章能對大家瞭解這門技術有一定的幫助。如果有錯誤或不嚴謹的地方,歡迎批評指正,如果喜歡,歡迎點贊。