看到
PWA
,似曾相識,但又感覺很模糊,於是乎,又重新翻閱文檔,學習了一遍,順便把相關知識學習了一下,比如service worker
,workbox3
。
PWA 概念:
全稱:Progressive Web APP, 漸進式 Web 應用。
實際上是通過 Web 技術編寫出的一個網頁應用,加上App Manifest
和Service Worker
來實現PWA
的安裝和離線緩存等功能。
解決了哪些問題?
- 可以添加至主屏幕,點擊主屏幕圖標可以實現啟動動畫及隱藏地址欄
- 實現離線緩存功能
- 實現了消息推送
PWA 的實現-Manifest 實現添加至主屏幕
首先在index.html
的head
中引入manifest.json
文件,盡可能早的引入
<head>
...
<meta name="viewport" content="width=device-width, user-scalable=no" />
<link rel="manifest" href="manifest.json">
<link rel="stylesheet" type="text/css" href="main.css">
...
</head>
然后編寫manifest.json
文件,參考文檔:https://developer.mozilla.org/zh-CN/docs/Web/Manifest
{
"name": "Minimal PWA", // 必填 顯示的插件名稱
"short_name": "PWA Demo", // 可選 在APP launcher和新的tab頁顯示,如果沒有設置,則使用name
"description": "The app that helps you understand PWA", //用於描述應用
"display": "standalone", // 定義開發人員對Web應用程序的首選顯示模式。standalone模式會有單獨的
"start_url": "/", // 應用啟動時的url
"theme_color": "#313131", // 桌面圖標的背景色
"background_color": "#313131", // 為web應用程序預定義的背景顏色。在啟動web應用程序和加載應用程序的內容之間創建了一個平滑的過渡。
"icons": [ // 桌面圖標,是一個數組
{
"src": "icon/lowres.webp",
"sizes": "48x48", // 以空格分隔的圖片尺寸
"type": "image/webp" // 幫助userAgent快速排除不支持的類型
},
{
"src": "icon/lowres",
"sizes": "48x48"
},
{
"src": "icon/hd_hi.ico",
"sizes": "72x72 96x96 128x128 256x256"
},
{
"src": "icon/hd_hi.svg",
"sizes": "72x72"
}
]
}
PWA的實現-Service Worker 實現離線緩存
Service worker,是 Chrome 團隊提出和力推的一個 WEB API,就像介於服務器和網頁之間的攔截器,能夠攔截進出的http請求,從而完全控制你的網站。
最主要的特點:
- 在頁面中注冊並安裝成功后,運行於瀏覽器后台,不受頁面刷新的影響,可以監聽和攔截作用域范圍內所有頁面的 HTTP 請求。
- 網站必須使用 HTTPS,處於安全考慮,避免被攻擊。除了使用貝蒂開發環境調試。
- 運行於瀏覽器后台,可以控制打開的作用域范圍下所有的頁面請求
- 單獨的作用域范圍,單獨的運行環境和執行線程
- 不能操作頁面 DOM ,但是可以通過事件機制來處理
- 事件驅動型服務線程
瀏覽器支持情況:
生命周期
解析成功(parsed)、正在安裝(installing)、安裝整個(installed)、正在激活(activating)、激活成功(activated)、廢棄(redundant)
若 installing 事件失敗或 activeing 事件失敗,service worker 都會被廢棄。
實現離線緩存
首先在index.html
中注冊sw.js
<script async src="/js/script.js"></script>
<script>
// 注冊 service worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js', {scope: '/'}).then(function (registration) {
// 注冊成功
console.log('ServiceWorker registration successful with scope: ', registration.scope);
}).catch(function (err) {
// 注冊失敗 :(
console.log('ServiceWorker registration failed: ', err);
});
}
</script>
編寫sw.js
var cacheStorageKey = 'cachesName'
var cacheList = [
// 注冊成功后要立即緩存的資源列表
]
// 當瀏覽器解析完sw文件時觸發install事件
self.addEventListener('install', function(e) {
// install事件中一般會將cacheList中要換存的內容通過addAll方法,拉一遍放入caches中
e.waitUntil(
caches.open(cacheStorageKey).then(function(cache) {
return cache.addAll(cacheList)
})
)
})
// 激活時觸發activate事件
self.addEventListener('activate', function(e) {
// active事件中通常做一些過期資源釋放的工作,匹配到就從caches中刪除
var cacheDeletePromises = caches.keys().then(cacheNames => {
return Promise.all(cacheNames.map(name => {
if (name !== cacheStorageKey) {
return caches.delete(name);
} else {
return Promise.resolve();
}
}));
});
e.waitUntil(
Promise.all([cacheDeletePromises])
)
})
self.addEventListener('fetch', function(e) {
// 在此編寫緩存策略, 需要根據不同文件的擴展名把不同的資源通過不同的策略緩存在caches中,各種css,js,html,圖片,都需要單獨搞一套緩存策略
e.respondWith(
// 可以通過匹配緩存中的資源返回
caches.match(e.request)
// 也可以從遠端拉取
fetch(e.request.url)
// 也可以自己造
new Response('自己造')
// 也可以通過吧fetch拿到的響應通過caches.put方法放進chches
)
})
workbox3
workbox3,Google官方 PWA 框架,解決的就是 Service Worker 編寫太過復雜的問題。
// 首先引入workbox框架
importScripts('https://storage.googleapis.com/workbox-cdn/releases/3.3.0/workbox-sw.js');
workbox.precaching([
// 注冊成功后要立即緩存的資源列表
])
// 緩存策略: networkFirst、cacheFirst、staleWhileRevalidate
workbox.routing.registerRoute(
new RegExp(''.*\.html'),
workbox.strategies.networkFirst()
);
workbox.routing.registerRoute(
new RegExp('.*\.(?:js|css)'),
workbox.strategies.cacheFirst()
);
workbox.routing.registerRoute(
new RegExp('https://your\.cdn\.com/'),
workbox.strategies.staleWhileRevalidate()
);
生成緩存策略,可以采用workbox-build npm 包
或者workbox-webpack-plugin
方式自動生成。
緩存策略:
stateWhileRevalidate
:當請求的路由有對應的 Cache 緩存結果就直接返回,在返回 Cache 緩存結果的同時會在后台發起網絡請求拿到請求結果並更新 Cache 緩存,如果本來就沒有 Cache 緩存的話,直接就發起網絡請求並返回結果,這對用戶來說是一種非常安全的策略networkFirst
:當請求路由是被匹配的,就采用網絡優先的策略,也就是優先嘗試拿到網絡請求的返回結果,如果拿到網絡請求的結果,就將結果返回給客戶端並且寫入 Cache 緩存,如果網絡請求失敗,那最后被緩存的 Cache 緩存結果就會被返回到客戶端,這種策略一般適用於返回結果不太固定或對實時性有要求的請求,為網絡請求失敗進行兜底。cacheFirst
:當匹配到請求之后直接從 Cache 緩存中取得結果,如果 Cache 緩存中沒有結果,那就會發起網絡請求,拿到網絡請求結果並將結果更新至 Cache 緩存,並將結果返回給客戶端。這種策略比較適合結果不怎么變動且對實時性要求不高的請求networkOnly
:強制使用正常的網絡請求,並將結果返回給客戶端,這種策略比較適合對實時性要求非常高的請求。cacheOnly
:直接使用 Cache 緩存的結果,並將結果返回給客戶端,這種策略比較適合一上線就不會變的靜態資源請求。- 如果以上策略都不滿足需求,還可以自定義策略
參考文檔
- 講講PWA
- 背景
- What's PWA?
- PWA的實現
- Manifest實現添加至主屏幕
- service worker實現離線緩存
- serice worker實現消息推送
- 總結:PWA的優勢和存在的問題
- 參考文檔
- Vue筆記九:pwa技術在vue的使用(workbox/sw-precache)
- 歷史背景
- sw-precache 和 workbox
- 緩存機制
- 安全性
- Workbox 3.0 – Web 站點輕松做到離線可訪問
- 概述
- 用法
- precache (預緩存)靜態文件
- 處理/和/index.html
- 忽略請求參數
- 生成預緩存列表
- workbox 命令行
- workbox-build npm 包
- workbox-webpack-plugin
- 路由請求緩存
- 字符串方式
- 正則表達式fangs
- 回調函數方式
- 路由請求緩存策略
- state while revalidate
- network first
- cache first
- network only
- cache only
- 自定義策略
- 第三方請求的緩存
- workbox 配置
- 配置緩存名稱
- 指定 development 環境
- 配置日志 level: debug、log、warning、error
- workbox 插件
- 自定義插件
- webpack 中使用 workbox 實現 PWA
- Workbox3 - ServiceWorker可以如此簡單
- 科普ServiceWorker
- 一個完整的ServiceWorker
- workbox3
- 經驗之談
- Service Worker 生命周期
- 解析成功(parsed)、正在安裝(installing)、安裝整個(installed)、正在激活(activating)、激活成功(activated)、廢棄(redundant)