概念
Progressive Web Apps 是漸進式Web應用程式,執行在現代瀏覽器並展現出超級能力。支援可發現,可安裝,離線執行,訊息推送等APP特有的能力,本專案以最簡單的方式封裝了以上功能。
SIMPLE-PWA
SIMPLE-PWA 是pwa搭載在vue的示例專案,pwa是一個漸進式web應用概念,不依賴任何框架,vue只是一個實現載體。
檢視 PWA推送訊息伺服器實現
demo
請使用android高版本(>5.0)最新版chrome瀏覽器訪問。
目錄
- 任務清單,檢視所有可配置項
- 離線瀏覽
- 推送通知
- 工具:效能工具LightHouse,sw工具庫sw-toolbox
執行過程
pwa工作依賴於Service Worker(簡稱sw)。
任務清單 -> sw註冊 -> sw監聽/代理
- 首先在index.html引入manifest.json和用於註冊sw的register.js;
- 接著register.js會檢測navigator.serviceWorker並將sw.js註冊;
- 最後sw.js持續監聽和代理sw事件。
注意:本專案使用copy-webpack-plugin和sw-precache-webpack-plugin將/src/sw下的檔案編譯並生成到專案根目錄下,因此使用<%= htmlWebpackPlugin.files.publicPath %>變數獲取
index.html:
<!DOCTYPE html>
<html>
<head>
...
<!-- Manifest -->
<link rel="manifest" href="<%= htmlWebpackPlugin.files.publicPath %>manifest.json">
</head>
<body>
...
<!-- Service Worker register -->
<!-- without webpush -->
<script src="<%= htmlWebpackPlugin.files.publicPath %>register.simple.js"></script>
<!-- with webpush -->
<!-- <script src="<%= htmlWebpackPlugin.files.publicPath %>register.js"></script> -->
</body>
</html>
複製程式碼
register.js:
if (navigator.serviceWorker) {
navigator.serviceWorker.register('/sw.js')
.then(function (registration) {
console.log('Registered events at scope: ', registration)
})
.catch(function (err) {
console.log('ServiceWorker registration failed: ', err)
})
}
複製程式碼
sw.js:
self.addEventListener('some event', e => {
// do something
})
複製程式碼
工作規則
新增到主螢幕
新增到主螢幕既可安裝,需要滿足以下條件:
- 需要 manifest.json 檔案
- 清單檔案需要啟動 URL(start_url)
- 清單檔案至少需要 144x144 的 PNG 圖示
- 網站正在使用通過 HTTPS(或localhost) 執行的 Service Worker,既sw處於activated狀態
- 使用者需要至少瀏覽網站兩次,並且兩次訪問間隔在五分鐘之上
{
"name": "PWA Lite",
"short_name": "PWA",
"display": "standalone",
"start_url": "/",
"theme_color": "#ffffff",
"background_color": "#ffffff",
"icons": [
{
"src": "./static/appicon_144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "./static/appicon_96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "./static/appicon_48.png",
"sizes": "48x48",
"type": "image/png"
}
]
}
複製程式碼
在chrome開發者工具中:
- Application/Manifest 檢查manifest.json有效性
- Application/Service Workers 檢視當前sw狀態
- Application/Service Workers 除錯時可勾選"Update on reload"
新增到主螢幕只會顯示一次,這在除錯過程非常不便。不過,如果你使用chrome除錯,可以訪問 chrome://flags/#bypass-app-banner-engagement-checks 勾選忽略,這樣每次訪問都會顯示。
離線瀏覽
sw提供很多種 快取模式。
sw處於activated狀態時,可以在sw.js監聽fetch事件並攔截和處理任何請求:
// 請求命中快取時直接返回快取結果,否則發起請求
self.addEventListener('fetch', e => {
e.respondWith(
caches.match(e.request).then(response => {
if (response != null) {
return response
}
return fetch(e.request.url)
})
)
})
複製程式碼
在chrome開發者工具中:
- Application/Cache/Cache Storage 檢視快取列表
- 如果sw攔截成功,在Network中size列可以看到(from ServiceWorker)字樣
- 在Network中勾選offline然後重新整理頁面,可以看到已訪問過的頁面仍然可以訪問,並不會出現“未連線到網際網路”,這就是離線瀏覽的威力
關於瀏覽器快取模式
- from memory cache 記憶體,只存在瀏覽器執行時,如base64圖片資料和靜態資源,不可控
- from disk cache 硬碟,長期快取在硬碟中,如靜態資源,不可控
- from ServiceWorker sw代理,完全可控
訊息推送
訊息推送需要滿足以下條件:
- sw處於activated狀態
- 使用者允許通知
- 詢問使用者是否允許的對話方塊只會顯示一次,可以在chrome位址列點選i圖示,將“通知”項改為“使用全域性預設設定(詢問)”即可發起詢問對話方塊
- 使用者允許後會得到訂閱物件,其中endpoint指向谷歌的推送伺服器,因此接收時需要全域性翻牆
// 伺服器推送事件
self.addEventListener('push', e => {
// do something
}
// 推送訊息對話方塊點選事件
self.addEventListener('notificationclick', e => {
// do something
}
複製程式碼
開始
# install dependencies
npm install
# serve with hot reload at localhost:8080
npm run dev
# build for production with minification
npm run build
複製程式碼