前置学问贮备
PWA ( Progressive Web Apps )是收集上议论最多的手艺革新之一,在IT界从业者中获得了亘古未有的势头。假如你是为web构建的,我置信PWA是增加到你的事情辞汇中的最新“流行语”。这并不新鲜,由于PWA已完成了在手机上装置web运用程序的遥不可及的妄想。
关于PWA的建立和它的上风,已有了许多的中心和“极客之谈”。大多数引见PWA的尝试,特别是对新手来讲,好像都是行话,或许代码太多,能够会使他们不敢迈出第一步。在这篇文章中,我想要以一个简朴的案例来教会列位怎样起步。
关于PWA的观点以及宿世此生我这边不会过量赘述,收集上有许多越发专业的文章供你进修,这篇文章只担任教会你怎样运用它。
比升引一篇文章消除你的一切关于PWA的疑心来讲我更愿望你能简朴相识观点以后将我的案例敲打一遍后再回过甚去深切相识PWA。
什么是PWA
下一代 Web 运用模子 —— Progressive Web App
PWA官网
起步
// 建立一个简朴的项目
mkdir pwa-project
cd pwa-project
touch index.html
touch app.js
touch style.css
置信列位都是运用chrome最新版的高端手艺人才,这里为了省略webpack一些烦琐的设置我们直接编写es6代码运行在chrome即可
编写代码
假定我们有一个消息站点,须要展现题目,图片,文章,而且依据差别的泉源切换内容
依据这个要求我们能够编写以下代码
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>News</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<header>
<h1>News</h1>
<select id="sourceSelector"></select>
</header>
<main></main>
<script src="./app.js"></script>
</body>
</html>
// style.css
html {
line-height: 1.15;
/* 1 */
-webkit-text-size-adjust: 100%;
/* 2 */
}
body {
margin: 0;
}
h1 {
font-size: 2em;
margin: 0.67em 0;
}
a {
background-color: transparent;
text-decoration: none;
}
button,
select {
text-transform: none;
}
这里为了模仿实在用户数据我们能够去👇这里要求apikey猎取一些实在数据
列位也能够直接copy代码来进修,代码逻辑很简朴这里不做解说。
// app.js
const apiKey = 'fa35a325ddfa4c4798102ebb76809bbb';
const main = document.querySelector('main');
const sourceSelector = document.querySelector('#sourceSelector');
const defaultSource = 'techcrunch'
// 页面加载后实行逻辑
window.addEventListener('load', async e => {
updateNews();
await updateSources();
sourceSelector.value = defaultSource;
sourceSelector.addEventListener('change', e => {
updateNews(e.target.value);
});
// 推断浏览器是不是支撑serviceWorker
if ('serviceWorker' in navigator) {
try {
// 尝试注册serviceWorker到sw.js文件中
navigator.serviceWorker.register('sw.js');
console.log('SW registered');
} catch (error) {
console.log('SW reg failed');
}
}
});
// 猎取消息泉源
async function updateSources() {
const res = await fetch(`https://newsapi.org/v2/sources?apiKey=${apiKey}`);
const json = await res.json();
sourceSelector.innerHTML = json.sources
.map(src => `<option value="${src.id}">${src.name}</option>`)
.join('\n');
}
// 依据泉源猎取消息数据
async function updateNews(source = defaultSource) {
const res = await fetch(`https://newsapi.org/v2/top-headlines?sources=${source}&apiKey=${apiKey}`);
const json = await res.json();
main.innerHTML = json.articles.map(createArticle).join('\n');
}
// 建立文章
function createArticle(article) {
return `
<div class="article">
<a href="${article.url}">
<h2>${article.title}</h2>
</a>
<img src="${article.urlToImage}" />
<p>${article.description}</p>
</div>
`;
}
启动
如今启动我们的项目
实行npx http-server
翻开我们的localhost:8080
端口(端口号依据详细情况而定)
我们点开掌握台看看是不是是报错了?
在点开这里我们能够发明找不到sw.js这个文件,由于我们基础没有嘛!😂
既然没有那我们写一个不就好了-_-!!
编写sw.js
起首我们什么都不写,直接建立sw.js文件到项目中就不会报错了,然则什么都没写就意味着你什么都没有做。
那我们究竟能够用这个文件做什么事呢?
缓存我们的静态资本文件
// sw.js
const staticAssets = [
'./',
'./style.css',
'./app.js'
];
// sw.js初次被注册时刻触发
self.addEventListener('install', async event => {
const cache = await caches.open('news-static');
cache.addAll(staticAssets);
})
如今我们再次革新页面(记得清算缓存哈)就能够看到我们的静态资本都被缓存起来了。
什么?没有缓存起来?
那你肯定是没有通知浏览器革新时刻要更新你的sw.js
文件。能够勾选这里,然后再次革新。
然则缓存是缓存起来了,我们如果不拿来用那也没啥卵用。
所以我们要阻拦要求并通知浏览器我们要运用这些缓存。
// sw.js (增加以下代码)
// sw监听到fetch事宜时刻触发
self.addEventListener('fetch', event => {
const req = event.request;
event.respondWith(cacheFirst(req));
});
// 运用浏览器缓存
async function cacheFirst(req) {
const cachedResponse = await caches.match(req);
return cachedResponse || fetch(req);
}
编写完这些以后我们能够先勾选offline
按钮,以后革新页面,发明我们的站点依旧有数据。
我们点开network
看看要求。
我们发明我们阻拦了http要求而且将浏览器的缓存数据返回回去了!
是不是是很奇异😊!
到这一步,置信你已见地到了PWA的一些才能了。
准确运用缓存
在上面的代码中实际上是有一些问题的,我们在离线状况下运用缓存是ok的,但是假如我们处于联网状况情况下,我们还须要返回缓存吗?固然不须要,不仅不须要,我们还应当用服务器的最新数据更新我们的缓存。
所以我们要依据收集优先的准绳修改下sw逻辑。
self.addEventListener('fetch', event => {
const req = event.request;
const url = new URL(req.url);
// 当当地开辟时刻能够这么设置
if (url.origin === location.origin) {
event.respondWith(cacheFirst(req));
} else if ((req.url.indexOf('http') !== -1)) {
// chrome的https协定限定,接口必需满足https
event.respondWith(networkFirst(req));
}
});
// 缓存优先
async function cacheFirst(req) {
const cachedResponse = await caches.match(req);
return cachedResponse || fetch(req);
}
// 收集优先
async function networkFirst(req) {
// 将要求到的数据缓存在id为news-dynamic中
const cache = await caches.open('news-dynamic');
try {
const res = await fetch(req); // 猎取数据
cache.put(req, res.clone()); // 更新缓存
return res;
} catch (error) {
return await cache.match(req); // 报错则运用缓存
}
}
至此我们的案例基本上完成了,然则照样能够再次优化一下。
假定用户还没有检察过我们的站点页面其他内容,也就是说我们的缓存不完整,这个时刻能够供应一个mock数据提醒用户守候能够联网的时刻再来检察当前页面。(详细文件能够从我的github堆栈中猎取)
PWA就这么点才能吗?
实在PWA还供应给我们将web站点以app图标情势安排在桌面以及挪动手机中。
这里设置与编写浏览器插件历程有点相似。
我们须要一个manifest.json
文件,并在index.html
中引入。
manifest.json
能够在这个站点中天生。
// html文件须要引入一行代码
<link rel="manifest" href="manifest.json">
设置胜利后我们能够在掌握台中检察
有了这个文件和响应图标后我们就能够增加至桌面端了,是不是是很酷炫~
未完待续
停止项目代码可在我的堆栈中猎取。(可否给个小星星勉励下呢😂)
后续会补充在详细项目中应当怎样集成pwa,这篇文章只剖析了pwa的中心代码~