service workers
因為 js 是單線程的,如果有前端部分數據大量渲染和計算的情況下,會導致頁面渲染非常慢,會遭到阻塞。因為 js 是會阻塞頁面渲染的。有沒有辦法,用 service workers 在背后進行大規模的運算。比如 webgl 這樣的 3d 渲染,但是 3d 存在一個很大的問題,就是 3d 模型, 3d 數據非常大。一個數據就好幾M, 這種情況下就可以用 service workers,用 workers 進行渲染再進入主線程。
Service Worker是一個腳本,瀏覽器獨立於當前網頁,將其在后台運行,為實現一些不依賴頁面或者用戶交互的特性打開了一扇大門。在未來這些特性將包括推送信息,背景后台同步,geofencing(地址圍欄定位),但它將推出的第一個首要特性,就是攔截和處理網絡請求的能力,包括以編程方式來管理被緩存的相應。就是離線應用。
Service Worker 兩點應用
1、使用攔截和處理網絡請求的能力,去實現一個
離線應用
2、使用 Service Worker
在后台運行同時能和頁面通信的能力,去實現大規模后台數據的處理
PWA
Progressive Web Apps 是一種 Web App 新模型,並不是具體指某一種前沿的技術或者某一個單一的知識點,我們用英文縮寫來看就能看出,這是一個漸進式的 Web App,是通過一系列新的 Web 特性,配合優秀的 UI 交互設計,逐步的增強 Web App 的用戶體驗。
所謂漸進式就是手機在弱網的情況下,頁面能不能加載出來。如果你的手機在離線的情況下,你的 app 能不能加載出來。
pwa 現在大概有3點的方向
1、可靠:在沒有網絡的環境中也能提供基本的頁面訪問,而不會出現‘未連接到互聯網’的頁面。之前這是 web app 遜色於安卓的
2、快速:針對網頁渲染及網絡數據訪問有較好優化。比如安卓app在過度頁面的時候有個好的渲染,web app 也支持
3、融入,應用可以被增加到手機桌面,並且和普通應用一樣有全屏,推送等特性。這也是相較於原生 app 提出來的。
1、離線應用,service worker 只能在 https 下使用
serviceWorker.html
<!DOCTYPE html> <html lang="en"> <head> <link rel="stylesheet" href="./main.css"> </head> <body> <div class="container">service worker</div> <script src="./app.js"></script> </body> </html>
main.css
.container{ color: red; }
app.js
// 注冊 serviceWorker if (navigator.serviceWorker) { navigator.serviceWorker.register('./service-worker.js', { scope: './' // 作用域 }).then(function (reg) { console.log(reg); }).catch(function (e) { console.log(e); }) } else { alert('Service Worker is not supported') }
service-worker.js
// 監聽 serviceWorker install 事件 self.addEventListener('install', function(e) { // 會接受一個 promise 對象,返回成功后才會進行后續的運行 e.waitUntil( // caches 就是開啟一個 cacheStorage caches.open('app-v1').then(function(cache){ console.log('open cache'); return cache.addAll([ './app.js', './main.css', './serviceWorker.html' ]) }) ) }) self.addEventListener('fetch', function(event) { // 讀緩存 event.respondWith( caches.match(event.request).then(function(res) { if (res) { return res; } else { // 通過 fetch 方法向網絡發起請求 fetch(url).then(function() { if (res) { // 對於新請求到資源存儲到我們的 cachestorage中 } else { // 用戶提示 } }) } }) ) })
2、使用 Service Worker 在后台運行同時能和頁面通信的能力,去實現大規模后台數據的處理
msg-demo.html
<!DOCTYPE html> <html lang="en"> <head> </head> <body> <ul id="msg-box"></ul> <input type="text" id="msg-input" /> <button id="send-msg-button">發送</button> <script src="./msgapp.js"></script> </body> </html>
msgapp.js
// 注冊 serviceWorker if (navigator.serviceWorker) { var sendBtn = document.getElementById('send-msg-button'); var msgInput = document.getElementById('msg-input'); var msgBox = document.getElementById('msg-box'); sendBtn.addEventListener('click', function(){ // 點擊btn ,主頁往 servicework 發事件 navigator.serviceWorker.controller.postMessage(msgInput.value); }) navigator.serviceWorker.addEventListener('message', function(event){ msgBox.innerHTML = msgBox.innerHTML + ('<li>' + event.data.message + '</li>') }) navigator.serviceWorker.register('./msgsw.js', { scope: './' // 作用域 }).then(function (reg) { console.log(reg); }).catch(function (e) { console.log(e); }) } else { alert('Service Worker is not supported') }
msgsw.js
// 監聽 serviceworker message 事件 self.addEventListener('message', function(event) { var promise = self.clients.matchAll().then(function(clientList){ var senderID = event.source ? event.source.id : 'unknown'; clientList.forEach(client => { if(client.id == senderID) { return } else { client.postMessage({ client: senderID, message: event.data }) } }); }) event.waitUntil(promise); })
