Progressive Web Apps (以下简称 PWA) 是 Google 提出的用前沿的 Web 技术为网页提供 App 般使用体验的一系列方案。
使网页具备了何种功能 ?
1. 可以如同应用程序一般添加快速打开方式, 并且不用通过app store !
2. 另外还支持数据缓存, 离线运行, 后台推送消息等功能 !
一个简单的demo讲解代码结构 ?
完整实例代码可访问我的 github 点击打开链接
index.html
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>test</title> | |
<scriptsrc="sw.js"></script> | |
<link rel="manifest"href="./manifest.json" /> | |
<script>//Service Worker 在网页已经关闭的情况下还可以运行, 用来实现页面的缓存和离线, 后台通知等等功能 | |
if ('serviceWorker'innavigator) { | |
navigator.serviceWorker | |
.register('./sw.js') | |
.then(function() {console.log('Service Worker Registered'); }); | |
} | |
</script> | |
</head> | |
<body style="background-color: aqua"> | |
hello word ! | |
</body> | |
</html> |
manifest.json:为了让 PWA 应用被添加到主屏幕, 使用 manifest.json 定义应用的名称, 图标等等信息。
{ | |
"name":"Weather", | |
"short_name":"Weather", | |
"icons": [{ | |
"src":"https://placekitten.com/128/128", | |
"sizes":"128x128", | |
"type":"image/png" | |
}, { | |
"src":"https://placekitten.com/144/144", | |
"sizes":"144x144", | |
"type":"image/png" | |
}, { | |
"src":"https://placekitten.com/152/152", | |
"sizes":"152x152", | |
"type":"image/png" | |
}, { | |
"src":"https://placekitten.com/192/192", | |
"sizes":"192x192", | |
"type":"image/png" | |
}, { | |
"src":"https://placekitten.com/256/256", | |
"sizes":"256x256", | |
"type":"image/png" | |
}], | |
"start_url":"/index.html", | |
"display":"standalone", | |
"background_color":"#3E4EB8", | |
"theme_color":"#2F3BA2" | |
} |
var dataCacheName = 'weatherData-v1'; | |
var cacheList =[ | |
'/', | |
'/index.html' | |
]// 借助 Service Worker, 可以在注册完成安装 Service Worker 时, 抓取资源写入缓存 | |
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(cacheList); | |
}) | |
); | |
}); | |
// 网页抓取资源的过程中, 在 Service Worker 可以捕获到 fetch 事件, 可以编写代码决定如何响应资源的请求 | |
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) { | |
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); | |
}) | |
); | |
} | |
}); | |
// 缓存的资源随着版本的更新会过期, 所以会根据缓存的字符串名称(这里变量为 dataCacheName, 值用了 "weatherData-v1")清除旧缓存, 可以遍历所有的缓存名称逐一判断决决定是否清除 | |
self.addEventListener('activate',function(e) { | |
console.log('[ServiceWorker] Activate'); | |
if (key !== cacheName && key!== dataCacheName) | |
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); | |
} | |
})); | |
}) | |
); | |
return self.clients.claim(); | |
}); |
demo 运行 ?
进入当前项目目录
http-server
其中 http-server 下载 https://www.npmjs.com/package/http-server
访问:
http://127.0.0.1:8080
点击红色框处,即可添加到桌面!