PWA之前端專案,實現可安裝、離線快取、訊息推送

象棋發表於2018-03-08

概念

Progressive Web Apps 是漸進式Web應用程式,執行在現代瀏覽器並展現出超級能力。支援可發現,可安裝,離線執行,訊息推送等APP特有的能力,本專案以最簡單的方式封裝了以上功能。

SIMPLE-PWA

SIMPLE-PWA 是pwa搭載在vue的示例專案,pwa是一個漸進式web應用概念,不依賴任何框架,vue只是一個實現載體。

檢視 PWA推送訊息伺服器實現

demo

pwa example

請使用android高版本(>5.0)最新版chrome瀏覽器訪問。

目錄

執行過程

pwa工作依賴於Service Worker(簡稱sw)。

任務清單 -> sw註冊 -> sw監聽/代理

  1. 首先在index.html引入manifest.json和用於註冊sw的register.js;
  2. 接著register.js會檢測navigator.serviceWorker並將sw.js註冊;
  3. 最後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
})
複製程式碼

工作規則

新增到主螢幕

新增到主螢幕既可安裝,需要滿足以下條件:

  1. 需要 manifest.json 檔案
  2. 清單檔案需要啟動 URL(start_url)
  3. 清單檔案至少需要 144x144 的 PNG 圖示
  4. 網站正在使用通過 HTTPS(或localhost) 執行的 Service Worker,既sw處於activated狀態
  5. 使用者需要至少瀏覽網站兩次,並且兩次訪問間隔在五分鐘之上

新增到主螢幕

{
  "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開發者工具中:

  1. Application/Manifest 檢查manifest.json有效性
  2. Application/Service Workers 檢視當前sw狀態
  3. 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開發者工具中:

  1. Application/Cache/Cache Storage 檢視快取列表
  2. 如果sw攔截成功,在Network中size列可以看到(from ServiceWorker)字樣
  3. 在Network中勾選offline然後重新整理頁面,可以看到已訪問過的頁面仍然可以訪問,並不會出現“未連線到網際網路”,這就是離線瀏覽的威力

關於瀏覽器快取模式

  1. from memory cache 記憶體,只存在瀏覽器執行時,如base64圖片資料和靜態資源,不可控
  2. from disk cache 硬碟,長期快取在硬碟中,如靜態資源,不可控
  3. from ServiceWorker sw代理,完全可控

瀏覽器快取模式

訊息推送

notification
notification

訊息推送需要滿足以下條件:

  1. sw處於activated狀態
  2. 使用者允許通知
  3. 詢問使用者是否允許的對話方塊只會顯示一次,可以在chrome位址列點選i圖示,將“通知”項改為“使用全域性預設設定(詢問)”即可發起詢問對話方塊
  4. 使用者允許後會得到訂閱物件,其中endpoint指向谷歌的推送伺服器,因此接收時需要全域性翻牆

訊息推送

// 伺服器推送事件
self.addEventListener('push', e => {
  // do something
}

// 推送訊息對話方塊點選事件
self.addEventListener('notificationclick', e => {
  // do something
}
複製程式碼

開始

github

# install dependencies
npm install

# serve with hot reload at localhost:8080
npm run dev

# build for production with minification
npm run build
複製程式碼

相關文章