摘要:是谷歌近幾年一直在推進的應(yīng)用新模型。既然如此,我們最好是站在巨人的肩膀上,這個巨人就是谷歌。是由谷歌瀏覽器團隊發(fā)布,用來協(xié)助創(chuàng)建應(yīng)用的庫。當然直接用還是太復(fù)雜了,谷歌還很貼心的發(fā)布了一個插件,能夠自動生成和靜態(tài)資源列表。
PWA(Progressive Web Apps)是谷歌近幾年一直在推進的 web 應(yīng)用新模型。PWA 借助 Service Worker 緩存網(wǎng)站的靜態(tài)資源,甚至是網(wǎng)絡(luò)請求,使網(wǎng)站在離線時也能訪問。并且我們能夠為網(wǎng)站指定一個圖標添加在手機桌面,實現(xiàn)點擊桌面圖標即可訪問網(wǎng)站。
Web App ManifestWeb App Manifest 是一個 JSON 文件,它用來定義網(wǎng)站添加到桌面的圖標以及從桌面圖標進入網(wǎng)站時的一系列行為,如:啟動樣式,全屏主題等。
先創(chuàng)建 manifest.json:
{ "name": "blog-pwa", "short_name": "blog-pwa", "icons": [ { "src": "/img/icons/android-chrome-192x192.png", "sizes": "192x192", "type": "image/png" }, { "src": "/img/icons/android-chrome-512x512.png", "sizes": "512x512", "type": "image/png" } ], "start_url": "/index.html", "display": "standalone", "background_color": "#000000", "theme_color": "#4DBA87" }
將文件引入:
我們可以從開發(fā)者工具上看我們的配置:
icons 屬性定義了添加到桌面的圖標, display: standalone 表示我們要從桌面全屏啟動,theme_color": "#4DBA87 是全屏啟動時手機頂部狀態(tài)欄的背景色,background_color": "#000000 是啟動頁的背景色,啟動頁目前不能定制,默認由 background_color 加 icon 加 name 組合而成。
Web App Manifest很簡單,只要照著文檔每個屬性看一遍就行。
Service WorkerService Worker 是瀏覽器在后臺獨立于網(wǎng)頁運行的腳本。是它讓 PWA 擁有極快的訪問速度和離線運行能力。
那它是如何做到的呢?我們一步步來看。
注冊 Service Workerif ("serviceWorker" in navigator) { navigator.serviceWorker .register("/service-worker.js") .then(registration => { console.log( "ServiceWorker registration successful with scope: ", registration.scope ) }) .catch(err => { console.log("ServiceWorker registration failed: ", err) }) }
需要注意的是,Service Worker 腳本除了域名為 localhost 時能運行在 http 協(xié)議下以外,只能運行 https 協(xié)議下。
安裝const CACHE_NAME = "cache-v1" const DATA_CACHE_NAME = "data-cache-v1" const PRE_CACHE = ["/index.html", "/css/app.css", "/js/app.js"] self.addEventListener("install", e => { console.log("[ServiceWorker] Install") e.waitUntil( caches.open(CACHE_NAME).then(cache => { return cache.addAll(PRE_CACHE) }) ) })
在安裝的時候預(yù)緩存網(wǎng)站的靜態(tài)資源,任何資源路徑出錯都會造成 Service Worker 安裝失敗。
代理請求self.addEventListener("fetch", e => { e.respondWith( caches.match(e.request).then(response => { if (response) { return response } const fetchRequest = e.request.clone() return fetch(fetchRequest).then(response => { // Check if we received a valid response if (!response || response.status !== 200) { return response } const responseToCache = response.clone() caches.open(DATA_CACHE_NAME).then(cache => { cache.put(e.request, responseToCache) }) return response }) }) ) })
安裝成功后,Service Worker 就可以監(jiān)聽網(wǎng)站的所有請求,匹配到緩存時直接返回,未匹配到時請求服務(wù)器,服務(wù)器成功返回時添加到緩存。
更新現(xiàn)在網(wǎng)站的 Service Worker 已經(jīng)可以正常工作了,那如何更新它呢?
我們只需要修改 Service Worker 文件就可以更新它。當我們每次訪問網(wǎng)站時都會去下載這個文件,當發(fā)現(xiàn)文件不一致時,就會安裝這個新 Service Worker ,安裝成功后,它將進入等待階段。當我們關(guān)閉窗口重新導(dǎo)航到網(wǎng)站時(刷新網(wǎng)頁不行),新 Service Worker 將開始控制網(wǎng)站。舊 Service Worker 終止工作并觸發(fā) activate 事件:
self.addEventListener("activate", e => { e.waitUntil( caches.keys().then(keyList => { return Promise.all( keyList.map(key => { if (key !== CACHE_NAME && key !== DATA_CACHE_NAME) { console.log("[ServiceWorker] Removing old cache", key) return caches.delete(key) } }) ) }) ) })
在其卸載時一定要刪除舊緩存,不然我們的網(wǎng)站永遠無法更新。
上面只簡單講了 Service Worker 如何工作。我們會發(fā)現(xiàn)有很多問題需要我們進一步解決:
預(yù)緩存的靜態(tài)資源修改后在下一次發(fā)版本時的文件名都不一樣,手動寫死太低效,最好每次都自動生成資源文件名。
緩存資源是以硬編碼字符串判斷是否有效,這樣每次發(fā)版本都需要手動修改,才能更新緩存。并且每次都是全量更新。能否以文件的粒度進行資源緩存呢?
請求代理沒有區(qū)分靜態(tài)資源和動態(tài)接口。已經(jīng)緩存的動態(tài)接口也會一直返回緩存,無法請求新數(shù)據(jù)。
上面只列出了三個明顯的問題,還有很多問題是沒有考慮到的。如果讓我們自己來解決這些問題,不僅是工作量很大,而且也很難寫出生產(chǎn)環(huán)境可用的 Service Worker。
workbox既然如此,我們最好是站在巨人的肩膀上,這個巨人就是谷歌。workbox 是由谷歌瀏覽器團隊發(fā)布,用來協(xié)助創(chuàng)建 PWA 應(yīng)用的 JavaScript 庫。當然直接用 workbox 還是太復(fù)雜了,谷歌還很貼心的發(fā)布了一個 webpack 插件,能夠自動生成 Service Worker 和 靜態(tài)資源列表 - workbox-webpack-plugin。
只需簡單一步就能生成生產(chǎn)環(huán)境可用的 Service Worker :
const { GenerateSW } = require("workbox-webpack-plugin") new GenerateSW()
打包一下:
還能說什么呢?谷歌大法好!當然這只是最簡單的可用版本,其實這里有一個最嚴重的問題不知道有沒人發(fā)現(xiàn),那就是 importScripts 引用的是谷歌域名下的 cdn ,這讓我們墻內(nèi)的網(wǎng)站怎么用,所以我們需要把這個問題解決并自定義一些配置增強 Service Worker 的能力:
new GenerateSW({ importWorkboxFrom: "local", skipWaiting: true, clientsClaim: true, runtimeCaching: [ { // To match cross-origin requests, use a RegExp that matches // the start of the origin: urlPattern: new RegExp("^https://api"), handler: "staleWhileRevalidate", options: { // Configure which responses are considered cacheable. cacheableResponse: { statuses: [200] } } }, { urlPattern: new RegExp("^https://cdn"), // Apply a network-first strategy. handler: "networkFirst", options: { // Fall back to the cache after 2 seconds. networkTimeoutSeconds: 2, cacheableResponse: { statuses: [200] } } } ] })
首先 importWorkboxFrom 我們指定從本地引入,這樣插件就會將 workbox 所有源文件下載到本地,墻內(nèi)開發(fā)者的福音。上面提到過新 Service Worker 安裝成功后需要進入等待階段,skipWaiting: true 將使其跳過等待,安裝成功后立即接管網(wǎng)站,注意這個要和 clientsClaim 一起設(shè)置為 true。runtimeCaching 顧名思義是配置運行時如何緩存請求的,這里只說一點,緩存跨域請求時 urlPattern 的值必須為 ^ 開頭的正則表達式,其它的配置看文檔都能得到詳細的介紹。
再打包一次:
現(xiàn)在我們就可以將打包好的代碼部署到網(wǎng)站上了,源碼在這,最后再上幾張圖:
參考Web App Manifest
服務(wù)工作線程:簡介
服務(wù)工作線程生命周期
workbox-webpack-plugin
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/95318.html
摘要:另外,單頁應(yīng)用因為數(shù)據(jù)前置到了前端,不利于搜索引擎的抓取。所以我們需要對自己的單頁應(yīng)用進行一些優(yōu)化。 前言 最近秋招之余空出時間來按自己的興趣動手做了一個項目,一個基于vue-cli3.0, vue,typescript的移動端pwa,現(xiàn)在趁熱打鐵,將這個項目從開發(fā)到部署整個過程記錄下來,并將從這個項目中學習到的東西分享出來,如果大家有什么意見或補充也可以在評論區(qū)提出。先介紹一下這個項...
摘要:實際上是指的為簡化開發(fā)而開源的第三方庫。首先安裝依賴然后再配置文件中啟用就完成了使用采坑官網(wǎng)上線后發(fā)現(xiàn),啟用后不能播放視頻了。把當成了失敗請求,導(dǎo)致請求視頻文件失敗。 PWA(Progressive Web App)是前端的大趨勢,它能極大的加快前端頁面的加載速度,得到近乎原生 app 的展示效果(其實難說)。PWA 其實是多種前端技術(shù)的組合,其中最重要的一個技術(shù)就是 service ...
摘要:文章首次發(fā)表在博客支持了前言使用插件使博客支持功能,目前我所知道的有兩種插件均可實現(xiàn)該功能前提全站支持目前本人使用的是騰訊云的免費證書網(wǎng)站配置已經(jīng)有很多文章寫了配置過程本篇文章不在贅述使用安裝修改配置文件的配置文件采用語言想要 文章首次發(fā)表在: 博客支持PWA了~ 前言 使用hexo插件使博客支持pwa功能,目前我所知道的有兩種插件均可實現(xiàn)該功能 hexo-pwa hexo-off...
摘要:在上一篇文章記一次基于的項目由開發(fā)到部署一中,我們了解到了給我們提供了哪些支持,也了解到了有哪些不足。項目回顧這是一個移動端的應(yīng)用,使用,,,,基于開發(fā)。可以添加到主屏幕,可以斷網(wǎng)條件下正常打開和訪問數(shù)據(jù)。 在上一篇文章記一次基于react、cra2、typescript的pwa項目由開發(fā)到部署(一)中,我們了解到了create-react-app 給我們提供了哪些pwa支持,也了解到...
閱讀 6179·2021-11-22 15:32
閱讀 813·2021-11-11 16:54
閱讀 3157·2021-10-13 09:40
閱讀 2162·2021-09-03 10:35
閱讀 1824·2021-08-09 13:47
閱讀 1865·2019-08-30 15:55
閱讀 1933·2019-08-30 15:43
閱讀 2455·2019-08-29 17:06