前端吹得这么火的PWA,你真的不来了解下吗?
什么是渐进式Web应用(PWA)?
渐进式Web应用将网络之长与应用之长相结合,在用户随着时间的推移增进与应用的关系后,其功能会变得越来越强大。即使在网络不良的情况下也能快速加载、能够发送相关推送通知、具有桌面图标,并且可采用全屏体验的方式加载。
PWA具备以下特点:
渐进式 - 适用于选用任何浏览器的所有用户,因为它是以渐进式增强作为核心宗旨来开发的。
自适应 - 适合任何机型:桌面设备、移动设备、平板电脑或任何未来设备。
连接无关性 - 能够借助于服务工作线程在离线或低质量网络状况下工作。
类似应用 - 由于是在 App Shell 模型基础上开发,因此具有应用风格的交互和导航,给用户以应用般的熟悉感。
持续更新 - 在服务工作线程更新进程的作用下时刻保持最新状态。
安全 - 通过 HTTPS 提供,以防止窥探和确保内容不被篡改。
可发现 - W3C 清单和服务工作线程注册作用域能够让搜索引擎找到它们,从而将其识别为“应用”。
可再互动 - 通过推送通知之类的功能简化了再互动。
可安装 - 用户可免去使用应用商店的麻烦,直接将对其最有用的应用“保留”在主屏幕上。
可链接 - 可通过网址轻松分享,无需复杂的安装。
Service Workers(服务工作者)
渐进式Web 应用的定义中有部分是这样说的:它必须支持离线工作。
由于允许 Web 应用程序脱机工作的是 Service Worker,这意味着 Service Worker 是渐进式 Web 应用强制要求的部分。
Service Worker 是一个 JavaScript 文件,作为 Web 应用和网络之间的中间人。正因为如此,它可以提供缓存服务,加速应用程序渲染,并改善用户体验。
出于安全原因,只有 HTTPS 站点可以使用 Service Workers,这也是为什么必须通过 HTTPS 提供渐进式 Web 应用的原因之一。
用户首次访问应用程序时,Service Workers 在设备上不可用。在首次访问时,Web Worker 将被安装,在随后访问网站的不同页面时,Service Worker 将被调用。
ServiceWorker的强大在于它允许你控制如何处理来自页面的网络请求,它主要工作流程:注册→安装→提取→激活
注册
// Checks if the browser supports Service workers
if ('serviceWorker' in navigator) {
// registerServiceWorker.js is the file that contains the install, fetch and activativation code.
navigator.serviceWorker.register('registerServiceWorker.js')
.then(registration => {
// Successful registration
console.log('Hooray. Registration successful, scope is:', registration.scope);
}).catch(function(err) {
// Failed registration, service worker won’t be installed
console.log('Oops. Service worker could not be installed, error:', error);
});
}
registerServiceWorker.js
上面代码块中引用的文件通常包含安装,获取和激活代码。
安装
在安装步骤中,您需要缓存一些静态资源。如果所有文件都已成功缓存,则会安装ServiceWorker。如果任何文件无法下载和缓存,则安装步骤将失败,ServiceWorker将不会被安装和激活。
var CACHE_NAME = 'pwa-cache-v1';
var urlsToCache = [
'/',
'/styles/styles.css',
'/script/webpack-bundle.js'
];
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => {
// Open a cache and cache our files
return cache.addAll(urlsToCache);
})
);
});
urlsToCache
是要缓存的文件的数组。通过cache.addAll()
方法获取它们,并将它们添加到缓存中。
提取
每当用户发出请求(导航到页面或刷新页面)时,都会触发ServiceWoker监听的fetch事件,此方法会检查请求并从ServiceWorker创建的缓存中查找命中的结果。
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request)
.then(function(response) {
if (response) {
return response;
}
return fetch(event.request);
}
)
);
});
在上面的代码块中,fetch
定义了事件,并在event.respondWith()
函数中传递promise
caches.match()
方法查看请求并从ServiceWorker创建的缓存中查找命中的结果。
如果存在匹配的响应,则返回缓存的值。否则,返回从网络请求的资源
激活
activate
事件通常用于缓存管理,它在注册后触发。
self.addEventListener('activate', function(event) {
var cacheWhitelist = ['pages-cache-v1', 'blog-posts-cache-v1'];
event.waitUntil(
// Get all the cache keys (cacheName)
caches.keys().then(function(cacheNames) {
return Promise.all(
// Check all caches and delete old caches that are not whitelisted
cacheNames.map(function(cacheName) {
if (cacheWhitelist.indexOf(cacheName) === -1) {
return caches.delete(cacheName);
}
})
);
})
);
});
上面的代码块是activate
事件的示例。它遍历服务工作程序中的所有缓存,并删除缓存白名单中未定义的所有缓存。
在激活步骤之后,ServiceWorker将控制属于其范围的所有页面。
ServiceWorker浏览器支持情况
CanIUse数据显示:谷歌、safari、firefox、IE Edge、Opera最新版都已经支持Service worker。
而从百度lavas(https://lavas.baidu.com/ready)上统计的数据来看,国产浏览器大部分都已支持这一特性。
应用程序外壳(App Shell)
App Shell模型是一个简单的设计概念,它不是Web API或框架,而是开发人员可以选择遵循的设计方法。
使用App Shell模型,我们将应用UI的外壳与其内部的内容分开,并且将它们单独缓存。理想情况下,我们的App Shell会被缓存,以便在用户访问并在以后返回时尽快加载。理论上分别对shell和内容加载可以提高用户对应用程序性能和可用性的感知。
应用外壳的结构分为应用的核心基础组件和承载数据的 UI。所有的 UI 和基础组件都使用一个 service worker缓存在本地,因此在后续的加载中PWA应用其他页面时仅需要加载需要的数据,而不是加载所有的内容。
Web应用程序清单(manifest)
Web应用程序清单控制用户从主屏幕启动时看到的内容,包括启动画面,主题颜色,图标等。
{
"short_name": "PusherCoins",
"name": "PusherCoins",
"icons": [
{
"src": "favicon.ico",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"start_url": "./index.html",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
manifest字段说明:
short_name:
用户主屏幕上的文本段名称name:
在网络应用安装横幅中使用的名称icons:
当用户将您的网站添加到其主屏幕时,将使用这些图标。您还可以为浏览器定义一组图标以供使用。start_url:
指定当用户启动从设备的应用程序加载的URL,支持绝对或者相对URLdisplay:
定义浏览器的显示模式。值可取是standalone(隐藏浏览器UI)
,fullscreen
,browser(网页浏览模式)
,或minimal-ui
。theme_color:
定义了应用程序的默认主题颜色,这会影响操作系统显示应用程序的方式background_color:
定义了Web应用程序预期的背景色。
后台同步(Background Sync)
后台同步是一种Web API,可以将操作推迟直到用户具有稳定网络连接。这对于确保实际发送用户想要发送的内容非常有用,即使在失去网络连接之后也是如此。
例如,后台同步在聊天应用程序中非常有用。你可能已经遇到过在发送消息后连接错误或根本没有连接的情况,通过后台同步功能,它仍然会在网络重连之后继续传递消息。
在PWA中实现后台同步非常简单。以下面的代码为例:
// Register your service worker:
navigator.serviceWorker.register('/sw.js');
// Then later, request a one-off sync:
navigator.serviceWorker.ready.then(function(swRegistration) {
return swRegistration.sync.register('myFirstSync');
});
在上面的代码中,ServiceWorker已注册,然后我们请求一次性同步,其名称为myFirstSync
。然后我们在/sw.js
以下地方监听sync事件:
self.addEventListener('sync', function(event) {
if (event.tag == 'myFirstSync') {
event.waitUntil(doSomeStuff());
}
});
在上面的代码块中,doSomeStuff()
应该返回一个promise,指示它正在尝试做的任何事情的成功/失败。如果满足,则同步完成。如果失败,将重试同步过程。
PWA开发入门视频
视频时长接近40分钟,带你快速入门PWA的开发
PWA相关资源
Lavas,基于 Vue.js 的 PWA 解决方案:https://lavas.baidu.com/
你的第一个PWA应用:https://developers.google.com/web/fundamentals/codelabs/your-first-pwapp/
Lighthouse,谷歌插件,PWA性能检测:https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk?hl=en
如果你喜欢探讨技术,或者对本文有任何的意见或建议,非常欢迎加鱼头微信好友一起探讨,当然,鱼头也非常希望能跟你一起聊生活,聊爱好,谈天说地。鱼头的微信号是:krisChans95 也可以扫码关注公众号,订阅更多精彩内容。