-
node 8.9 版本及以上 (https: // nodejs.org/en/download/).
-
Yarn (https://yarnpkg.com)
-
Git.
git clone https://github.com/petereijgermans11/progressive-web-app
cd pwa-article / pwa-app-manifest-init
Manifest清单文件
创建一个Manifest.json
{
"name": "Progressive Selfies","short_name": "PWA Selfies","icons": [
{
"src": "/src/images/icons/app-icon-192x192.png","type": "image/png","sizes": "192x192"
},{
"src": "/src/images/icons/app-icon-512x512.png","sizes": "512x512"
}
],"start_url": "/index.html","scope": ".","display": "standalone","background_color": "#fff","theme_color": "#3f51b5"
}
告诉浏览器你应用的清单
<link rel=”manifest” href=”/manifest.json”>
Manifest 属性介绍
-
name、short_name:指定Web应用的名称,short_name是该应用的简称,当没有足够空间展示应用的name属性时,系统就会使用short_name 。
- l display:display属性指定Web应用的显示模式,它有四个值可供配置:fullscreen、standalone、minimal-ui和browser,但一般常用的属性就是fullscreen和standalone。
-
fullscreen:全屏显示
-
standalone:这种模式下打开的应用不会出现浏览器的地址栏,所以因此看起来更像是一个原生应用
-
minimal-ui、browser:和使用浏览器访问区别不大。
- l orientation:控制Web应用的显示的方向及禁止手机转屏。
- l icons、background_color:icon用于指定应用图标,background_color是应用加载完成前的背景色,通过设置这两个属性,可组合成应用的Splash Screen。
- l theme_color:定义应用程序的默认主题颜色。
- l description:设置应用的一段描述内容。
-
什么是Service Worker?
Service Worker生命周期
- 首先应注册SW,如果SW已注册,浏览器会根据于安装事件自动开始安装。
- 安装SW后,它将收到激活事件。此激活事件可用于清理SW早期版本的中使用的资源。
window.addEventListener('load',() => {
const base = document.querySelector('base');
let baseUrl = base && base.href || '';
if (!baseUrl.endsWith('/')) {
baseUrl = `${baseUrl}/`;
}
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register(`${baseUrl}sw.js`)
.then( registration => {
// Registration was successful
console.log('ServiceWorker registration successful with scope: ',registration.scope);
})
.catch(err => {
// registration failed :(
console.log('ServiceWorker registration failed: ',err);
});
}
});
- 您的应用程序无法在HTTPS下运行。在开发过程中,你可以通过localhost使用SW 。但如果将其部署在网站上时,则需要启用HTTPS。
- SW的路径不正确。
Service Worker 事件
self.addEventListener('install',event => {
console.log('[Service Worker] Installing Service Worker ...',event);
event.waitUntil(self.skipWaiting());
});
self.addEventListener('activate',event => {
console.log('[Service Worker] Activating Service Worker ...',event);
return self.clients.claim();
});
添加到主屏幕按钮
self.addEventListener('fetch',event => {
console.log('[Service Worker] Fetching something ....',event);
// This fixes a weird bug in Chrome when you open the Developer Tools
if (event.request.cache === 'only-if-cached' && event.request.mode !== 'same-origin') {
return;
}
event.respondWith(fetch(event.request));
});
Service Worker缓存
在Service Worker安装期间进行预缓存
const CACHE_STATIC_NAME = 'static';
const URLS_TO_PRECACHE = [
'/','index.html','src/js/app.js','src/js/feed.js','src/lib/material.min.js','src/css/app.css','src/css/feed.css','src/images/main-image.jpg','https://fonts.googleapis.com/css?family=Roboto:400,700','https://fonts.googleapis.com/icon?family=Material+Icons',];
self.addEventListener('install',event);
event.waitUntil(
caches.open(CACHE_STATIC_NAME)
.then(cache => {
console.log('[Service Worker] Precaching App Shell');
cache.addAll(URLS_TO_PRECACHE);
})
.then(() => {
console.log('[ServiceWorker] Skip waiting on install');
return self.skipWaiting();
})
);
});
self.addEventListener('fetch',event);
event.respondWith(
caches.match(event.request)
.then(response => {
if (response) {
console.log(response);
return response;
}
return fetch(event.request);
})
);
});
后台传输
<button id=”bgFetchButton”>Store assets locally</button>
window.addEventListener(‘load’,() => {
...
bgFetchButton = document.querySelector(‘#bgFetchButton’);
bgFetchButton.addEventListener(‘click’,async event => {
try {
const registration = await navigator.serviceWorker.ready;
registration.backgroundFetch.fetch(‘my-fetch’,[new Request(`${baseUrl}src/images/main-image-lg.jpg`)]);
} catch (err) {
console.error(err);
}
});
...
});
- 用户点击ID为bgFetchButton的按钮
- SW已注册
self.addEventListener(‘backgroundfetchsuccess’,event => {
console.log(‘[Service Worker]: Background Fetch Success’,event.registration); event.waitUntil(
(async function() {
try {
// Iterating the records to populate the cache
const cache = await caches.open(event.registration.id); const records = await event.registration.matchAll(); const promises = records.map(async record => {
const response = await record.responseReady;
await cache.put(record.request,response);
});
await Promise.all(promises);
} catch (err) {
console.log(‘[Service Worker]: Caching error’);
}
})()
);
});
- l 当Background Fetch传输完成,你的SW将收到Background Fetch成功事件。
- l 创建并打开一个与registration.id同名的新缓存。
- l 通过registration.matchAll()获取所有记录并遍历。