干货 | 10分钟玩转PWA

摘要:
关于PWAPWA,即渐进式web应用程序。PWA本质上是一个web应用程序,旨在通过许多新技术为用户提供安全、性能、体验和其他方面的本地应用程序体验。目前,PWA还不够成熟,无法一蹴而就。在安全性、性能和体验方面仍有很大的改进空间,以实现本机应用程序的效果。在本文中,我将指导您从网站缓存、http请求拦截、推送到主屏幕和其他功能,结合实例操作,一步一步快速使用PWA技术。

关于PWA

PWA(Progressive Web App), 即渐进式web应用。PWA本质上是web应用,目的是通过多项新技术,在安全、性能、体验等方面给用户原生应用的体验。而且无需像原生应用那样繁琐的下载、安装、升级等操作。

这里解释下概念中的“渐进式”,意思是这个web应用还在不断地进步中。因为目前而言,PWA还没有成熟到一蹴而就的程度,想在安全、性能、体验上达到原生应用的效果还是有很多的提升空间的。一方面是构建PWA的成本问题,另一方面是目前各大浏览器、安卓和IOS系统对于PWA的支持和兼容性还有待提高。

本文我将从网站缓存、http请求拦截、推送到主屏等功能,结合实例操作,一步步引领大家快速玩转PWA技术。

Service Worker

Service Worker是PWA的核心技术,它能够为web应用提供离线缓存功能,当然不仅如此,下面列举了一些Service Worker的特性:

  • 基于HTTPS 环境,这是构建PWA的硬性前提。(LAMP环境网站升级HTTPS解决方案

  • 是一个独立的 worker 线程,独立于当前网页进程,有自己独立的 worker context

  • 可拦截HTTP请求和响应,可缓存文件,缓存的文件可以在网络离线状态时取到

  • 能向客户端推送消息

  • 不能直接操作 DOM

  • 异步实现,内部大都是通过 Promise 实现

Service Worker生命周期

serviceworker的使用流程可以简单总结为注册--安装--激活。

注册

注册其实就是告诉浏览器serviceworkerJS文件存放在什么位置,然后浏览器下载、解析、执行该文件,进而启动安装。这里我创建一个app.js文件,注册代码如下,将该文件在网站的head标签里引入。

if ('serviceWorker' in navigator) {
    window.addEventListener('load', function () {
        navigator.serviceWorker.register('/sw.js')
            .then(function (registration) {
                // 注册成功
                console.log('ServiceWorker registration successful with scope: ', registration.scope);
            })
            .catch(function (err) {
                // 注册失败:(
                console.log('ServiceWorker registration failed: ', err);
            });
    });
}

安装

当执行serviceworkerJS文件时,首先触发的是install事件,进行安装。安装的过程就是将指定的一些静态资源进行离线缓存。下面是我的sw.js文件中的安装代码:

var CACHE_VERSION = 'sw_v8';
var CACHE_FILES = [
    '/js/jquery/min.js',
    '/js/zui/min.js',
    '/js/chanzhi.js',
];
self.addEventListener('install', function (event) {
    event.waitUntil(
        caches.open(CACHE_VERSION)
          .then(cache => cache.addAll(CACHE_FILES)
    ));
});

激活

当安装成功后,serviceworker就会激活,这时就会处理 activate 事件回调 (提供了更新缓存策略的机会)。并可以处理功能性的事件 fetch (请求)、sync (后台同步)、push (推送)。

self.addEventListener('activate', function (event) {
    event.waitUntil(
        caches.keys().then(function(keys){
            return Promise.all(keys.map(function(key, i){
                if(key !== CACHE_VERSION){
                    return caches.delete(keys[i]);
                }
            }));
        })
    );
});

serviceworker的缓存功能

安装时,serviceworker将我们指定的静态资源进行缓存(即预缓存),你也许会问,如果是实时的动态内容怎么办,我们不可能预先将所有的文件资源提前指定好,让serviceworker缓存。这就要提到serviceworker的拦截HTTP请求响应的特性了。

serviceworker拦截http请求,首先去检查请求的资源在缓存中是否存在,如果存在,则直接从缓存中调用,而且即便是无网络情况下,serviceworker也能调用缓存中的资源。如果缓存中没有请求的资源,则通过网络去服务器上检索,而且在找到并响应时,serviceworker会将其存入缓存中,以备下次再请求时直接从缓存中调用。

干货 | 10分钟玩转PWA第1张

serviceworker缓存流程

serviceworker文件中fetch事件代码如下:

self.addEventListener('fetch', function (event) {
    event.respondWith(
        caches.match(event.request).then(function(response){
            if(response){
                return response;
            }
            var requestToCache = event.request.clone();
            return fetch(requestToCache).then(
              function(response){
                if(!response || response.status !== 200){
                  return response;
                }
                var responseToCache = response.clone();
                caches.open(CACHE_VERSION)
                  .then(function(cache){
                    cache.put(requestToCache, responseToCache);
                  });
                return response;
              }
            );
        })
    );
});

在网站前台通过浏览器开发者工具,我们可以看下从缓存中调用资源的效果:

干货 | 10分钟玩转PWA第2张

干货 | 10分钟玩转PWA第3张

我这里操作演示用的是谷歌浏览器,下面是各大浏览器对于serviceworker的支持情况:

干货 | 10分钟玩转PWA第4张

serviceworker浏览器支持情况

添加到主屏

PWA支持将web应用在主屏桌面上添加一个快捷方式,以方便用户快速访问,同时提升web应用重复访问的几率。你也许会说,现在移动端上的浏览器功能列表里一般都提供了“添加到桌面”的功能呀,但是PWA与浏览器自带的添加到桌面的实现方式不同。

PWA不需要用户刻意去功能列表中使用这个功能按钮,而是在用户访问web应用时,直接在界面中提示一个添加到主屏桌面的横幅,从web应用角度而言,这其实就是主动与被动的区别。

PWA实现该功能非常简单,只需要一个manifest.json文件,文件中用户可以自定义应用的启动页面、模板颜色、图标等内容。下面是我的manifest.json文件设置,大家可作参考:

{
  "short_name": "蝉知资源站",
  "name": "蝉知资源站",
  "icons": [
    {
      "src": "chanzhiicon.png",
      "type": "image/png",
      "sizes": "48x48"
    },
    {
      "src": "192.png",
      "type": "image/png",
      "sizes": "192x192"
    },
    {
      "src": "512.png",
      "type": "image/png",
      "sizes": "512x512"
    },
    {
      "src": "144.png",
      "type": "image/png",
      "sizes": "144x144"
    }
  ],
  "start_url": "/index.html",
  "display": "standalone",
  "background_color": "#2196F3",
  "orientation": "landscape",
  "theme_color": "#2196F3"
}

需要提醒的是,目前移动端IOS系统的支持并不好,安卓手机上须使用57版本以上的谷歌浏览器可以支持该功能,下面是我在安卓手机上的操作演示:

干货 | 10分钟玩转PWA第5张

添加到主屏

小结

PWA技术正被广大企业及开发者们关注,虽然目前各设备的支持兼容有待提高,但这些都正在不断的改善进步。我也相信在不久的将来,PWA技术会逐步广泛普及,为广大企业和用户带来便利。本文和大家一起分享了PWA的相关技术与实例操作,后面还会就消息推送、数据同步等功能做进一步探讨交流。如果大家在学习PWA的过程中遇到其他问题,欢迎一起讨论交流。

更多技术文章,欢迎关注公众号:

干货 | 10分钟玩转PWA第6张

干货 | 10分钟玩转PWA第7张

免责声明:文章转载自《干货 | 10分钟玩转PWA》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇小程序:商品分类,实现滑块视图解决某些Android Permission denied下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Android中的依赖问题(五种依赖、eclipse、AS、添加第三方库、jar)

这篇文章的主题是: 依赖是什么 eclipse中的依赖 AS中的依赖(有一篇详细的文章讲得非常好,这里就不再写了http://blog.csdn.net/yy1300326388/article/details/46422939) 另外相关的话题有↓,可以自行查看: 安卓的support包的历史 AS中grandle具体的内容 怎么做一个给别人用的J...

六款免费网络延迟测试工具

六款免费网络延迟测试工具 网络安全编程与黑客程序员 1周前 内容来源:释然IT杂谈 6款免费网络延迟测试工具   作为网络管理员或网络工程师,时刻关注网络的交付速度至关重要。不仅需要确保自己有良好的响应时间,还需要确保网络的速度足以满足用户通信所需的每一条路径。而手动测试每个路径将占用你所有的时间。所以需要获得一个测试工具,以确保延迟不会影响网络的性能。...

一个鼠标键盘控制两台甚至多台主机的方法--Synergy

     在多台主机,不同系统中操作。避免了更换键鼠的麻烦。即使下面图中的功能。   鼠标同时在三台或者多台主机之间进行移动,而且是无缝滑动,鼠标直接从左滑倒右,而且支持,这台电脑复制,另一台黏贴。非常的方便实用。       要实现以上功能有多个方法,第一是使用硬件,购买KVM转换器。第二种是使用软件,这里介绍一种非常使用的软件Synergy。使用Syn...

webpack 多应用项目搭建

前言: 多应用在实际的项目中使用场景也是比较多的,话不多说,直接进入搭建过程 项目搭建: 请参考之前的webpack项目搭建笔记,此处不再过度讲解,项目结构如下 app1.html 1 <!DOCTYPE html> 2 <html style="font-size:20px"> 3 <head> 4 <...

如何通过Html网页调用本地安卓app?

如何使用html网页和本地app进行传递数据呢?经过研究,发现还是有方法的,总结了一下,大致有一下几种方式 一、通过html页面打开Android本地的app 1、首先在编写一个简单的html页面 <html> <head> <meta http-equiv="Content-Type" c...

HashMap实现缓存

package com.cache; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; pub...