天天看點

PWA 入門

PWA 基本介紹

PWA(Progressive Web App)是一種理念,使用多種技術來增強web app的功能,可以讓網站的體驗變得更好,能夠模拟一些原生功能,比如通知推送。在移動端利用标準化架構,讓網頁應用呈現和原生應用相似的體驗。

pwa mdn

PWA特點

  1. 可靠——即時加載,即使在不确定的網絡條件下也不會受到影響。

    當使用者從主螢幕啟動時,service work可以立即加載漸進式Web應用程式,完全不受網絡環境的影響。service work就像一個用戶端代理,它控制緩存以及如何響應資源請求邏輯,通過預緩存關鍵資源,可以消除對網絡的依賴,確定為使用者提供即時可靠的體驗。

  2. 快速

    據統計,如果站點加載時間超過 3s,53% 的使用者會放棄等待。頁面展現之後,使用者期望有平滑的體驗,過渡動畫和快速響應。

  3. 沉浸式體驗—— 感覺就像裝置上的原生應用程式,具有沉浸式的使用者體驗。

    漸進式Web應用程式可以安裝并在使用者的主螢幕上,無需從應用程式商店下載下傳安裝。他們提供了一個沉浸式的全螢幕體驗,甚至可以重新與使用者接觸的Web推送通知。

PWA技術點

a). web app manifest

manifest_mdn

web程式應用清單

Web應用程式清單在一個JSON文本檔案中提供有關應用程式的資訊(如名稱,作者,圖示和描述)。manifest 的目的是将Web應用程式安裝到裝置的主螢幕,為使用者提供更快的通路和更豐富的體驗。

建立 manifest.json檔案,
           

引入,必須在https 或者 http://localhost 運作。 個人是vscode

live Serve

插件

  • 常見配置

    name:指定應用名稱

    short_name: 應用短名稱,主屏顯示

    start_url:使用者啟動程式加載的url

    icons:各個平台icon

    background_color:使用者指定的背景顔色

    theme_color:主題色

    display: app顯示方式

MDN 範例

<link rel="manifest" href="manifest.json" target="_blank" rel="external nofollow" >
           
{
    "name":"測試項目--appp",
    "short_name":"測試1",
    "start_url":"/index.html",
    "icons":[
        {
            "src":"images/1.jpg",
            "size":"144x144",
            "type":"images/jpg"
        }
    ],
    "background_color":"skyblue",
    "theme_color":"yellow",
    "display":"standalone"
}
           
PWA 入門
b). service worker

前提條件

了解

worker

worker mdn

運作者 Worker 接口是Web Workers API 的一部分,代表一個背景任務,它容易被建立并向建立者發回消息。建立一個運作者隻要簡單的調用Worker()構造函數,指定一個腳本,在工作線程中執行。臨時

let myWorker = new Worker("worker.js");
myworker.addEventListener('message',e=>{  console.log(e)   }),


// worker.js
self.postMessage({data})

簡單的注冊監聽
           

那正主來了 Service workor

service worker

  • 一旦install,就永久存儲,除非unregister
  • 用到的時候喚醒,不用的時候自動休眠
  • 可程式設計式攔截請求,緩存檔案
  • 必須https請求(localhost)

注冊步驟

  • window.onload注冊
  • navigator對象内置serviceWorker
  • 注意可能低版本相容性問題 if()
  • 注冊service worker,傳回的是一個promise對象
<script>
        window.addEventListener('load',()=>{
            if('serviceWorker' in navigator){
                navigator.serviceWorker.register('./sw.js').then(res=>{
                    console.log(res)
                }).catch(err=>{
                    console.log(err)
                })
            }
        })
    </script>
           

生命周期

install 會在 service worker 注冊成功後觸發,主要用于緩存資源

activate 事件會在service worker激活後觸發,一般用于删除舊的資源

fetch 發送請求的時候觸發

self.addEventListener('install',event=>{

    console.log('install',event)
    // service worker 跳過等待   直接進入activate
    event.waitUntil(self.skipWaiting())
})

self.addEventListener('activate',event=>{
    console.log('activate',event)


    // 表示service worker激活後,立即擷取控制器
    event.waitUntil( self.clients.claim())
})

self.addEventListener('fetch',event=>{
    console.log('fetch',event)
})
           
c). fetch api

關鍵是 傳回的 res為資料流

fetch mdn

fetch('./data.json').then(res=>{
        console.log(res) // 流
        return res.json()
    }).then(res=>{
        console.log(res)
    })

           
d) cache storage

cache storage

CacheStorage 接口表示 Cache 對象的存儲。它提供了一個 ServiceWorker 、其它類型worker或者 window 範圍内可以通路到的所有命名cache的主目錄(它并不是一定要和service workers一起使用,即使它是在service workers規範中定義的),并維護一份字元串名稱到相應 Cache 對象的映射。

常見方法

CacheStorage.match()

檢查給定的 Request 是否是 CacheStorage 對象跟蹤的任何 Cache 對象的鍵,并傳回一個resolve為該比對的 Promise .

CacheStorage.has()

如果存在與 cacheName 比對的 Cache 對象,則傳回一個resolve為true的 Promise .

CacheStorage.open()

傳回一個 Promise ,resolve為比對 cacheName (如果不存在則建立一個新的cache)的 Cache 對象

CacheStorage.delete()

查找比對 cacheName 的 Cache 對象,如果找到,則删除 Cache 對象并傳回一個resolve為true的 Promise 。如果沒有找到 Cache 對象,則傳回 false.

CacheStorage.keys()

傳回一個 Promise ,它将使用一個包含與 CacheStorage 追蹤的所有命名 Cache 對象對應字元串的數組來resolve. 使用該方法疊代所有 Cache 對象的清單。

cache mdn

Cache.match

(request, options)

傳回一個 Promise對象,resolve的結果是跟 Cache 對象比對的第一個已經緩存的請求。

Cache.matchAll(request, options)

傳回一個Promise 對象,resolve的結果是跟Cache對象比對的所有請求組成的數組。

Cache.add

(request)

抓取這個URL, 檢索并把傳回的response對象添加到給定的Cache對象.這在功能上等同于調用 fetch(), 然後使用 Cache.put() 将response添加到cache中.

Cache.addAll

(requests)

抓取一個URL數組,檢索并把傳回的response對象添加到給定的Cache對象。

Cache.put

(request, response)

同時抓取一個請求及其響應,并将其添加到給定的cache。

Cache.delete

(request, options)

搜尋key值為request的Cache 條目。如果找到,則删除該Cache 條目,并且傳回一個resolve為true的Promise對象;如果未找到,則傳回一個resolve為false的Promise對象。

Cache.keys

(request, options)

傳回一個Promise對象,resolve的結果是Cache對象key值組成的數組。

PWA 入門

簡易

const CACHE_NAME = 'cache_v2'

// 加載緩存資源
self.addEventListener('install',async event=>{
    const cache = await caches.open(CACHE_NAME)
    await cache.addAll([
        '/',
        '/manifest.json',
        '/images/1.jpg'
    ])
    
    console.log('install',event)
    // service worker 跳過等待   直接進入activate
    await self.skipWaiting()
})

// 主要是清楚緩存
self.addEventListener('activate',async event=>{
    console.log('activate',event)

    const keys = await caches.keys()

    keys.forEach(key => {
        if(key !== CACHE_NAME){
            caches.delete(key)
        }
    })
    // 表示service worker激活後,立即擷取控制器
    await self.clients.claim()
})


// 如果資料請求成功就響應成功資料,如果失敗,從緩存中取
self.addEventListener('fetch',event=>{
    const req = event.request;

    // 給浏覽器響應
    event.respondWith(netWorkFirst(req))  // 是否網絡優先情況而定
    
})


// 網絡優先
async function netWorkFirst(req){

    try {
       let fresh = await fetch(req)
        return fresh
    } catch (e) {
        // 緩存取
        const cache = await caches.open(CACHE_NAME)
        const cached = await cache.match(req)
        return cached
    }
}
           
e) notification

通知接口用于向使用者配置和顯示桌面通知。

noticcation mdn

浏覽器預設權限

PWA 入門

Notification.requestPermission() 用于目前頁面向使用者申請顯示通知的權限。

PWA 入門
if(Notification.permission === 'default'){ // 預設時去請求權限 
            Notification.requestPermission()
        }

        if(!navigator.onLine){
            new Notification('提示', { body: '你目前沒有網絡'})
        }

        window.addEventListener('online',()=>{
            new Notification('提示', { body : '你已經連上網絡'})
        })
           
PWA 入門

繼續閱讀