Progressive Web Apps (PWA)是Google在移動時代力推的一個提高webapp性能和體驗解決方案,官方列舉了幾大新特色:css
— 鏈接無關性 - 可以藉助 Service Worker 在離線或者網絡較差的狀況下正常訪問html
我的理解核心目的加強WebApp的體驗:git
Service Worker是實現PWA應用最重要的一項技術,是一個在用戶沒有打開網頁沒有交互行爲時運行在瀏覽器後臺進程中的腳本,提供管理資源緩存、攔截資源、消息推送通知請求等功能。
閱讀下面內容前你須要作一些預備知識github
Service_Worker_API
Cache_API
首先咱們須要檢查瀏覽器是否支持service workerweb
if ('serviceWorker' in navigator) { navigator.serviceWorker .register('./service-worker.js') .then(function() { console.log('Service Worker Registered'); }); }
注意service-worker.js文件應用的根文件夾內,由於服務工做線程的做用域由該文件所在的目錄定義。
在service worker中,咱們經過cache相關的api緩存靜態資源或者請求數據,從而達到應用秒開的效果。shell
首先,咱們在service worker被install以後,經過 caches.open() 打開一個指定key的緩存。緩存key可以讓咱們對資源進行版本控制。實際使用時,咱們通常會將數據與 App Shell(靜態資源) 分開,以便咱們能輕鬆地更新某個數據,而不會影響其餘數據。json
緩存打開後,咱們即可調用 cache.addAll(),這個帶有網址列表參數的方法隨即從服務器獲取文件,並將響應添加到緩存內。遺憾的是,cache.addAll() 具備原子性,若是任何一個文件失敗,整個緩存步驟也將失敗!api
var cacheName = 'cache-1'; var filesToCache = [ '/scripts/app.js', '/styles/inline.css', '/images/clear.png', ]; 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); }) ); });
從新加載頁面以後,打開 DevTools,轉至 Application 面板的 Cache Storage 窗格,能夠查看全部被緩存的資源
瀏覽器
上面提到緩存分爲靜態資源和請求數據。在訪問頁面時,咱們攔截髮送的請求,並將其響應存儲在緩存內。對於靜態資源咱們再次訪問頁面時,若是資源版本沒有修改,就能夠直接命中緩存方便。而對於請求的數據咱們採用緩存優先於網絡策略,咱們指望網絡響應成爲「可信來源」,始終可以爲咱們提供最新信息。在第一次訪問頁面時,緩存數據解決了webapp內容區域空窗的問題,讓用戶體驗更好。緩存
self.addEventListener('fetch', function(e) { // console.log('[Service Worker] Fetch', e.request.url); var dataUrl = 'https://query.yahooapis.com/v1/public/yql'; if (e.request.url.indexOf(dataUrl) > -1) { /* * When the request URL contains dataUrl, the app is asking for fresh * weather data. In this case, the service worker always goes to the * network and then caches the response. This is called the "Cache then * network" strategy: * https://jakearchibald.com/2014/offline-cookbook/#cache-then-network */ e.respondWith( caches.open(dataCacheName).then(function(cache) { console.log('dataCacheName', cache) return fetch(e.request).then(function(response){ cache.put(e.request.url, response.clone()); return response; }); }) ); } else { /* * The app is asking for app shell files. In this scenario the app uses the * "Cache, falling back to the network" offline strategy: * https://jakearchibald.com/2014/offline-cookbook/#cache-falling-back-to-network */ e.respondWith( caches.match(e.request).then(function(response) { return response || fetch(e.request); }) ); } });
對於緩存,它是一把雙刃劍,它帶來了出色體驗,也會面臨一些新的難題-緩存更新。在生產環境中,google官方推薦sw-precache生成service worker代碼,它內置了緩存更新策略,能夠確保將資源過時的請求發送到服務器。
App Shell 是啓動PWA應用用戶界面所需的最小的資源(HTML、CSS 和 JavaScript)。Shell文件一旦經過網絡完成加載,就會經過service workder保存到緩存中。之後每當用戶打開應用時,就會自動從本地的緩存中打開Shell文件,確保加載速度很是快。
PWA應用容許用戶將輕鬆得將使用的webapp添加到系統的主屏幕,並且這個功能實現十分簡單,瀏覽器內核幫咱們處理了大量複雜的內部工做,咱們只須要在應用根目錄下添加一個應用清單文件manifest.json
供參考的模板
{ "name": "Weather", "short_name": "Weather", "icons": [{ "src": "images/icons/icon-128x128.png", "sizes": "128x128", "type": "image/png" }, { "src": "images/icons/icon-144x144.png", "sizes": "144x144", "type": "image/png" }, { "src": "images/icons/icon-152x152.png", "sizes": "152x152", "type": "image/png" }, { "src": "images/icons/icon-192x192.png", "sizes": "192x192", "type": "image/png" }, { "src": "images/icons/icon-256x256.png", "sizes": "256x256", "type": "image/png" }], "start_url": "/index.html", "display": "standalone", "background_color": "#3E4EB8", "theme_color": "#2F3BA2" }
manifest.json能夠描述webapp不一樣的展示形式
當咱們提PWA應用兼容性問題時,咱們說的實際上是PWA背後的新特性在各大瀏覽器廠商的支持程度。
在當前時間點來看這個問題,整體仍是抱樂觀態度,國內外的大部分瀏覽器都已經實現PWA必需的關鍵技術,全部剩餘技術目前都處於開發階段。
對於最大的絆腳石safari,蘋果也2018年1月宣佈將在 iOS 11.3 和 macOS 10.13.4 版本上正式增長對 Service Worker 的支持,同時還支持了添加到桌面(Web App Manfiest)。
兼容性參考,數據每兩週更新一次
行業內flipboard、flipkart、阿里巴巴國際站、餓了麼都已經落地PWA,百度開源了基於Vue的PWA解決方案lavas。PWA應用正在將迎來春天,成爲趨勢。對PWA感興趣的同窗能夠一塊兒探討學習