前言
百度百科PWA:PWA(Progressive Web App)
是一种理念,使用多种技术来增强web app的功能,可以让网站的体验变得更好,能够模拟一些原生功能,比如通知推送。在移动端利用标准化框架,让网页应用呈现和原生应用相似的体验。
优点
*一个PWA应用首先是一个网页,可以通过Web技术编写出一个网页应用,随后添加上App Manifest和
Service Worker来实现PWA的安装和离线等功能*
解决了哪些问题?
- 可以添加至主屏幕,陆主屏幕图标可以实现启动动画以及隐藏地址栏
- 实现离线缓存功能,即使用户手机没有网络,依然可以使用-些离线功能
- 实现了消息推送
它解决了。上述提到的问题,这些特性将使得Web应用渐进式接近原生App。
关于PWA大家可以百度或者打开这个详细了解,不过没什么用
效果图
网站开启PWA教程
- 开启Https-强制跳转——
这个是基本必须
- 根目录上传
sw.js
,这个文件自己创建,内容看下面(注意要修改里面需要缓存的xhr请求!!) - 根目录上传
manifest.json
并修改内容
name和short_name是标题‖description是描述‖src是icon图标
sw.js内容
// sw.js
var apiCacheName = 'api-0-1-1';
self.addEventListener('fetch', function (e) {
// 需要缓存的xhr请求
var cacheRequestUrls = [
'./index.html',
'./main.css'
];
console.log('现在正在请求:' + e.request.url);
// 判断当前请求是否需要缓存
var needCache = cacheRequestUrls.some(function (url) {
return e.request.url.indexOf(url) > -1;
});
/**** 这里是对XHR数据缓存的相关操作 ****/
if (needCache) {
// 需要缓存
// 使用fetch请求数据,并将请求结果clone一份缓存到cache
// 此部分缓存后在browser中使用全局变量caches获取
caches.open(apiCacheName).then(function (cache) {
return fetch(e.request).then(function (response) {
cache.put(e.request.url, response.clone());
return response;
});
});
}
/* ******************************* */
else {
// 非api请求,直接查询cache
// 如果有cache则直接返回,否则通过fetch请求
e.respondWith(
caches.match(e.request).then(function (cache) {
return cache || fetch(e.request);
}).catch(function (err) {
console.log(err);
return fetch(e.request);
})
);
}
});
// sw.js
// 监听activate事件,激活后通过cache的key来判断是否更新cache中的静态资源
self.addEventListener('activate', function (e) {
console.log('Service Worker 状态: activate');
var cachePromise = caches.keys().then(function (keys) {
return Promise.all(keys.map(function (key) {
if (key !== cacheName) {
return caches.delete(key);
}
}));
})
e.waitUntil(cachePromise);
return self.clients.claim();
});
function getApiDataFromCache(url) {
if ('caches' in window) {
return caches.match(url).then(function (cache) {
if (!cache) {
return;
}
return cache.json();
});
}
else {
return Promise.resolve();
}
}
function queryBook() {
// ……
// 远程请求
var remotePromise = getApiDataRemote(url);
var cacheData;
// 首先使用缓存数据渲染
getApiDataFromCache(url).then(function (data) {
if (data) {
loading(false);
input.blur();
fillList(data.books);
document.querySelector('#js-thanks').style = 'display: block';
}
cacheData = data || {};
return remotePromise;
}).then(function (data) {
if (JSON.stringify(data) !== JSON.stringify(cacheData)) {
loading(false);
input.blur();
fillList(data.books);
document.querySelector('#js-thanks').style = 'display: block';
}
});
// ……
}
manifest.json内容
{
"name": "不冷's Blog",
"short_name": "不冷's Blog",
"description": "迷失的人迷失了,相逢的人会再相逢",
"icons": [
{
"src": "https://q1.qlogo.cn/g?b=qq&nk=2085886325&s=640",
"sizes": "64x64",
"type": "image/png"
},
{
"src": "https://q1.qlogo.cn/g?b=qq&nk=2085886325&s=640",
"sizes": "120x120",
"type": "image/png"
},
{
"src": "https://q1.qlogo.cn/g?b=qq&nk=2085886325&s=640",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "https://q1.qlogo.cn/g?b=qq&nk=2085886325&s=640",
"sizes": "152x152",
"type": "image/png"
},
{
"src": "https://q1.qlogo.cn/g?b=qq&nk=2085886325&s=640",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "https://q1.qlogo.cn/g?b=qq&nk=2085886325&s=640",
"sizes": "384x384",
"type": "image/png"
},
{
"src": "https://q1.qlogo.cn/g?b=qq&nk=2085886325&s=640",
"sizes": "512x512",
"type": "image/png"
}
],
"start_url": "/",
"display": "standalone",
"background_color": "#2196f3",
"theme_color": "#2196f3",
"lang": "en"
}
下一步
- 在主题
header.php
文件里插入
<link rel="manifest" href="/manifest.json">
注意以下JS需写在<!DOCTYPE HTML>前面(我没写也实现了)
<?php
if ($_SERVER['HTTP_X_REQUESTED_WITH'] == "XMLHttpRequest" && ($this->is('post')||$this->is('page')) && stripos($_SERVER['HTTP_REFERER'], $_SERVER['SERVER_NAME'])) {
header('HTTP/1.1 200 OK');
ini_set("display_errors", 1);
$this->response($this->need('comments.php'));
}
?>
- 在主题
footer.php
文件里插入JS(handsome主题可以直接在后台外观中设置此处代码)
<script>
if (navigator.serviceWorker) {
navigator.serviceWorker.register('/service-worker.js')
.then(function(registration) {
console.log('service worker 注册成功');
})
.catch(function (err) {
console.log('servcie worker 注册失败');
});
}
</script>
总结
这东西真的挺复杂的!!!
参考文章:
- https://catni.cn/archives/17/
- http://www.hellojava.com/a/80352.html
- https://www.jianshu.com/p/fad8aa9e277f
- https://www.jianshu.com/p/25331bf16543
- https://segmentfault.com/a/1190000012353473
版权属于:不冷
本文链接:https://www.buleng.xyz/archives/75/
转载时须注明出处及本声明
感觉很酷的功能,但是好像太复杂了,不会搞啊
慢慢来
这个很nb
这个挺有用
哈哈哈,不过配置不容易哦