摘要:我喜歡移動,而且也是那些堅持使用技術構建移動應用程序的人之一。我們準備做這樣的一個漸進式應用是典型的旨在提高用戶離線體驗的應用。當我們開始構建應用時,你就能理解上面的場景了。的作用范圍是針對相對路徑的。最佳的做法是在應用的入口。
我喜歡移動app,而且也是那些堅持使用Web技術構建移動應用程序的人之一。
經過技術的不斷迭代(可能還有一些其它的東西),移動體驗設計愈來愈平易近人,給予用戶更好的體驗。
而今天,我們就要介紹一個新技術--漸進式 web 應用程序。在理解這個概念并自己嘗試了一下之后,我覺得沒有必要再做 hybrid 應用了。
我們準備做這樣的一個demo:
漸進式 Web 應用是典型的旨在提高用戶離線體驗的 Web 應用。它解決了這樣的問題:怎么才能不顯示類似下面的離線錯誤?
事實上,PWA 不僅解決了離線錯誤,還在恢復連接的時候將用戶與內容連接起來。移動設備是漸進式 web 應用的主要使用場景。讓我來告訴你為什么?
桌面瀏覽器用戶打開電腦(在家、學校或者辦公室)
檢查是否連上網絡,沒有則手動連接
打開 web 應用
移動端瀏覽器拿出手機
默認手機已經連接上網絡
直接打開 app
如上,用戶對待兩種場景的處理方式是不一樣的。移動端用戶不一定有很好的網絡連接,有的甚至沒有。在這樣的場景下,開發商需要做的就是保持用戶對產品的好感,在其網絡恢復時與其互動。如果信號很差,開發商需要通過一些手段保持用戶的耐心,不至于在請求過程中用戶直接關閉 web 應用。
當我們開始構建 PWA 應用時,你就能理解上面的場景了。
Service WorkersPWA 背后的原理是 service workers。如果想讓用戶在離線場景下依然保持打開 web 頁面,你需要在用戶打開 web 應用并且有網絡連接時做一些“后臺任務”,這個“后臺任務”會搜集 web 頁面最近一次運行需要的一些資源,以備離線時使用。
這就好像每年秋收儲備糧食,以備冬天不時之需一樣,不斷循環。
PWA 中的 service worker,可以類比成春天的播種的農民。下面是 MDN 對 service workers 的描述:
Service worker 是一個注冊在指定源和路徑下的事件驅動 worker。它采用 JavaScript 控制關聯的頁面或者網站,攔截并修改訪問和資源請求,細粒度地緩存資源。你可以完全控制應用在特定情形(最常見的情形是網絡不可用)下的表現。
簡而言之,service worker 就是一些在后臺運行邏輯的 worker。它沒有權限操作 DOM,但是可以調用其它的 API (例如 IndexDB 以及 Fetch API)。
開始之前請牢記:
service workers 只能在 HTTPS 協議下生效(或者 Localhost)。
service workers 被設計成異步的,不能使用 XHR (但你可以使用 Fetch)或者 LocalStorage。
service workers 的作用范圍是針對相對路徑的。因此,demo/sw.js 只能相對于 demo 起作用,demo/first/sw.js 相對于 first。
Mobile 還是 PWA如果你能利用 service workers 存儲離線使用所需的文件,那你就沒有必要開發移動 app 了。如果你的 web 應用對移動用戶進行了優化,并且幾乎不需要調用移動端的硬件功能,那么你應該嘗試一下 PWA。
我花了一些時間看飛行模式下一些移動 app 的表現。我將它們分成三類:
離線情況下不做任何操作例子: Coinbase
Coinbase 就是一直停留在 loading 的這個頁面。它甚至讓我懷疑這樣的 app 為啥要存在,因為這個頁面簡直跟 web 展示一模一樣。Coinbase 不是財經類 app,無需實時展示信息,因此,PWA 可能只適用應用于其 App Shell。
離線情況下展示警告信息(未連接網絡等等),展示 App Shell,但其它都不可用App Shell 是指不包含動態內容的一部分應用程序。例如導航菜單、側邊欄、背景、logo 等等。
例子:Uber
Uber 給用戶展示了一些信息(通過 App Shell 以及地圖),并且告知用戶不能操作是由于他網絡中斷了。Uber是一個很高頻的 app,這樣的交互展示對于他們的應用場景很有意義。
離線情況下展示緩存的數據例子: Medium
Medium在離線狀態下展示緩存的數據,一些離線展示在這個分類里面的 app(例如,Instagram)還會提示用戶離線了,所以,就不要對這個分類里面的 app 期望再搞了。
優化我的想法是,如果 PWA(或者 service workers)技術成熟并且被大規模應用的話,為什么不節省掉:
前往應用商店
下載并不常用的 app
呢?
當我們接下來談到 Web Manifest 時,你就意識到只要給你的 web 應用新增一個桌面 icon,web 應用就可以通過點擊這個 icon 實現啟動了。
一些公司已經在 PWA 方面做的比較好了,你可以在這個網址上面找到這些公司:pwa.rocks
開發準備我們已經介紹了足夠多的理論知識了。這是一個手把手的教程,來吧,讓我們動起手來。首先,按照下面的結構來創建一個新的項目:
|--pwa-demo |----css |----fonts |----images |----js |----index.html |----service-worker.js
下載 Materialize 這個 UI 庫,用里面 CSS、Fonts、js 文件分別替換項目里面的文件夾。
打開 index.html 文件,引入一些資源:
Body coming soon
我們已經引入了下載好的文件,還需要自己在相應的目錄創建一下 app.css 以及 app.js 這兩個文件。
注冊 Service Worker越早在瀏覽器注冊,Service Worker 就能越早的開始工作。最佳的做法是在應用的入口。在這個項目中,我們可以在 app.js 注冊一個新的 worker:
(function(){ if ("serviceWorker" in navigator) { navigator.serviceWorker .register("/service-worker.js") .then(function() { console.log("Service Worker Registered"); }); } })()
在做其他操作之前,我們首先需要檢測一下瀏覽器對于 Service Worker 的兼容性。如果支持,那我們就可以利用 register 這個方法來注冊這個 worker,這個方法告知了 service worker 文件的路徑。注冊函數返回一個 promise ,你可以在這個 promise 里面判斷注冊是否成功。
Service Worker 周期在開始構建 PWA 之前,你需要理解 Service Worker 的生命周期:
Install這一階段主要是讓 worker 在瀏覽器給定的作用域掛載。由于這是生命周期的第一步,最好在這一步緩存各種資源:
// ./service-worker.js var cacheName = "PWADemo-v1"; var filesToCache = [ "/index.html", "/css/app.css", "/js/app.js", /* ...and other assets (jQuery, Materialize, fonts, etc) */ ]; self.addEventListener("install", function(e) { console.log("[ServiceWorker] Install"); e.waitUntil( caches.open(cacheName).then(function(cache) { console.log("[ServiceWorker] Caching app shell"); return cache.addAll(filesToCache); }) ); });
caches.open 和 cache.addAll 都是異步操作.service worker 在這些操作完成之前可能會中斷,e.waitUntil用來等待 promise 的狀態變成 resolved 或者 rejected。
當緩存開關被打開時,我們嘗試利用 addAll 來新增緩存。
請記住,只要有一個文件緩存失敗,service worker 就無法被正確掛載。
Activate當 worker 掛載完成,其效果并不會立即展示出來,除非前一個 service worker 銷毀并且該 web 應用被重新訪問。假設我們掛載了另一個不同 cacheName 的 service worker:
// ./service-worker.js var cacheName = "PWADemo-v2"; var filesToCache = [ //... ]; self.addEventListener("install", function(e) { console.log("[ServiceWorker] Install"); //... });
當這個新的 service worker 創建之后,新的緩存 PWADemo-v2 也被創建,這時候 PWADemo-v1 仍然存在。當觸發 Activate 時,我們可以刪除 PWADemo-v1,使其“讓位”于 PWADemo-v2:
// ./service-worker.js self.addEventListener("activate", function(e) { console.log("[ServiceWorker] Activate"); e.waitUntil( caches.keys().then(function(keyList) { return Promise.all(keyList.map(function(key) { if (key !== cacheName) { console.log("[ServiceWorker] Removing old cache", key); return caches.delete(key); } })); }) ); });
我們檢查所有的 cache 名稱,如果發現不是正在使用的 cache,那么將其直接刪除。
FetchFetch 不是一個必需的生命周期,但它提供了攔截請求資源的方法。當發送請求時,首先會觸發這樣的事件:
// ./service-worker.js self.addEventListener("fetch", function(e) { console.log("[ServiceWorker] Fetch", e.request.url); e.respondWith( caches.match(e.request).then(function(response) { return response || fetch(e.request); }) ); });
如果資源已經被緩存了,我們返回瀏覽器緩存的版本。如果沒有,那么我們調用 fetch api 去發送 HTTP 請求該資源。
Debuggering Service Workers由于 service workers 的工作方式,特別是進行緩存時,不是很容易進行 debugger 調試。幸運的是,chrome 的 dev tools 提供了助力。跟著下面的步驟,調試我們剛注冊的 service worker:
打開 chrome dev tools
點擊 Application 這一選項,打開 service worker 分區:
你可以查看到 status 是綠色的,這就表明你的 service worker 成功了:
你可以打開 "Update on reload" 去強制更新 service worker,不用關閉所有已存在的 session:
右擊 "Cache Storage",然后點擊刷新去查看緩存。根據名稱點擊你所設置的cache,然后你就會看到緩存里面的各個項:
接下來你已經了解了必備的知識點,PWA 的概念對你來說已經不陌生了。接下來,我們將要討論 PWA 的緩存策略。我們將了解如何使用 IndexDB 來保存數據而不是 localStorage。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/89624.html
摘要:使用離線應用構建應用服務端服務器配置創建文件客戶端構建,并在標簽上添加屬性,屬性值是服務器上配置的緩存資源列表的文件名配置相關事件,創建離線文件內容將狀態代碼轉化成狀態離線應用創建即使沒有互聯網連接也可以使用的應用程序。 HTML5新增了localstroage和application cache做離線緩存,兩種緩存各有應用的場景,今天我們說說application cache這種方案...
摘要:原文地址譯文出自我的個人博客概述在本文中,您將學習如何使用和創建離線優先數據驅動的漸進式應用程序。在離線的情況下也可以使用后臺同步功能將應用程序與服務器同步。保存數據到中現在我們保存數據到剛創建的數據庫中的對象中。 原文地址:Build an offline-first, data-driven PWA譯文出自:我的個人博客 概述 在本文中,您將學習如何使用 Workbox 和 In...
摘要:技術實現離線應用的核心是離線緩存技術,歷史上曾先后出現兩種離線緩存技術。新的線程取得控制權后,將會觸發其事件。接入用構建接入的離線應用時,要解決的問題在于如何生成之前提到的文件。 內容主要引用自吳浩麟著《webpack深入淺出》 離線應用 離線應用的優點: 在沒有網絡的情況下能打開網頁。 由于部分緩存的資源直接從本地加載,所以對用戶來說可以加快網頁的加載速度,減少服務器壓力。 技術實...
閱讀 2158·2023-04-25 20:45
閱讀 1068·2021-09-22 15:13
閱讀 3641·2021-09-04 16:48
閱讀 2579·2019-08-30 15:53
閱讀 928·2019-08-30 15:44
閱讀 936·2019-08-30 15:43
閱讀 1001·2019-08-29 16:33
閱讀 3432·2019-08-29 13:08