Web 應用的現狀html
針對以上問題,結局方案出現了PWA前端
PWA全稱Progressive Web App,即漸進式WEB應用。 一個 PWA 應用首先是一個網頁, 能夠經過 Web 技術編寫出一個網頁應用. 隨後添加上 App Manifest 和 Service Worker 來實現 PWA 的安裝和離線等功能web
Service Worker 是瀏覽器在後臺獨立於網頁運行的腳本,它打開了通向不須要網頁或用戶交互的功能的大門。 Service Worker從英文翻譯過來就是一個服務工人,服務於前端頁面的後臺線程,基於Web Worker實現。有着獨立的js運行環境,分擔、協助前端頁面完成前端開發者分配的須要在後臺悄悄執行的任務。編程
客戶端訪問,經過Service Worker 服務,判斷請求內容從哪裏取的,若是緩存中存在,直接 取緩存,不然就走網絡主要包含六種狀態 解析成功(parsed),正在安裝(installing),安裝成功(installed),正在激活(activating),激活成功(activated),廢棄(redundant)。json
// main.js
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
navigator.serviceWorker.register('/sw.js')
.then(function (registration) {
// 註冊成功
console.log('ServiceWorker registration successful with scope: ', registration.scope);
if (registration.installing) {
// Service Worker is Installing
console.log('Service Worker is Installing')
} else if(registration.waiting) {
// 這是更新新版本或自動更新緩存的絕佳時機
/*
* 當前沒有激活的 worker
* 若是在 Service Worker 的腳本中 self.skipWaiting() 被調用
* 若是用戶訪問其餘頁面並釋放了以前激活的 worker
* 在一個特定的時間過去後,以前一個激活的 worker 被釋放
*/
console.log('Service Worker is Waiting')
} else if(registration.active) {
// 激活成功, Service Worker 是一個能夠徹底控制網頁的激活 worker
console.log('Service Worker is active')
}
})
.catch(function (err) {
// 註冊失敗:(
console.log('ServiceWorker registration failed: ', err);
});
});
}
window.onload = function() {
document.body.append('PWA!')
}
複製代碼
在代碼中的具體實現segmentfault
// sw.js
/*
sw.js 控制着頁面資源和請求的緩存
*/
// 監聽 service worker 的 install 事件,
// 對站點離線訪問最關鍵的資源 URL 列表,它們一般也是關鍵請求鏈包含的文件,並將其緩存進 caches 中
self.addEventListener('install', function (e) {
// 若是監聽到了 service worker 已經安裝成功的話,就會調用 event.waitUntil 回調函數
e.waitUntil(
caches.open('v1').then(cache => {
// 經過 cache 緩存對象的 addAll 方法添加 precache 緩存
return cache.addAll([
'/main.js',
'/index.html',
'/'
]);
}).then(function() {
// 跳過waiting,直接進入active
console.log('Skip waiting!')
return self.skipWaiting()
})
);
});
/*
事件回調是一個管理老舊緩存的好地方
在通常 PWA 中,咱們能夠結合版本號和緩存名,及時刪除過時緩存
*/
self.addEventListener('activate', function(e) {
const cacheStorageKey = 'v1'
e.waitUntil(
Promise.all(
caches.keys().then(cacheNames => {
return cacheNames.map(name => {
if (name !== cacheStorageKey) {
return caches.delete(name)
}
})
})
).then(() => {
console.log('Clients claims.')
// 經過clients.claim方法,更新客戶端上的server worker
return self.clients.claim()
})
)
})
/*
對不一樣資源類型應用不一樣的請求/緩存策略
看看這些請求所請求的文件在咱們的緩存裏有沒有,有的話就直接從緩存裏拿,不用下載了。
這也是PWA最重要的功能之一
*/
self.addEventListener('fetch', function (event) {
event.respondWith(
caches.match(event.request)
.then(function (response) {
// 檢測是否已經緩存過
if (response) {
return response;
}
var fetchRequest = event.request.clone();
return fetch(fetchRequest).then(
function (response) {
// 檢測請求是否有效
if (!response || response.status !== 200 || response.type !== 'basic') {
return response;
}
var responseToCache = response.clone();
caches.open('v1')
.then(function (cache) {
cache.put(event.request, responseToCache);
});
return response;
}
);
})
);
});
// 推送消息
self.addEventListener('message', function(event) {
// Do stuff with postMessages received from document
console.log("SW Received Message: " + event.data);
});
複製代碼