简介PWA与Service Worker

1.关于PWA

PWA,全称Progressive web apps,即渐进式Web应用。PWA技术主要作用为构建跨平台的Web应用程序,并使其具有与原生应用程序相同的用户体验。
早在2014年,W3C就已经公布了PWA的相关技术草案,Chrome于2015年在生产环境下落地支持,但是由于兼容性的问题,PWA技术并没有引起广泛的关注。一直到2018年,苹果在IOS 11.3中正式支持PWA,PWA才又重新回到了广大技术开发人员的视野中。

2.为什么使用PWA

传统Web存在的问题:

1.缺乏直接性的入口。打开网站需要记住它的域名,即使将它保存在收藏夹,寻找起来也不够直接,不够简便。
2.依赖于网络。只要客户机处于断网状态,整个Web系统就处于瘫痪状态,在客户机上无法使用。
3.无法向Native APP一样推送消息。

传统Native APP存在的问题:

1.需要下载与安装。哪怕我只是使用这款APP的一个功能,或者临时使用一下这个APP,我也需要全盘下载并安装APP。
2.开发成本高。你需要准备安卓和IOS两个版本。
3.发布需要审核。在APP Store或者安卓应用市场进行发布,都需要提交审核。
4.更新成本高。即使很小的程序更新,也会需要重新发版,重新提交应用商店审核。
5.内容无法被索引。由于其封闭性,Native APP的内容无法被预先索引,无法进行基于内容的APP检索,只能根据介绍去推断APP的内容。

PWA的存在,就是为了解决以上问题给用户带来的麻烦。
它的优势包括:

1.桌面入口,打开便捷。
2.离线可用,不过度依赖网络。
3.安装简便。
4.一次开发,无需审核,所有平台可用。
5.能够进行消息的推送。

3.PWA技术包括了什么

PWA并不是指某一个具体的技术,要实现PWA应用,需要多种技术的支持。
其中的核心技术包括了:Web App Manifest、Service worker、Cache API、Indexed DB、Push API、Notification API等等。

4.Service Worker与Cache API

读完了上边的内容,相信很多人还是云里雾里的,只是知道了个关于PWA的大概,但是对于如何构建一个PWA应用,还是一无所知。我就是这样的,当初为了学习PWA,参阅了很多资料,很多都是在讲类似于上边的内容,具体的内容却没有说的很明白。这里,我们就如何构建一个PWA应用,进行一下说明。
本质上,PWA就是一个网站,其根本的内容,还是通过HTML + CSS + Javascript去构建的Web页面。为了让它实现添加桌面入口、离线使用、消息推送等PWA特有的功能,就需使用一些Web API为我们的网站添加一些额外的代码。而其中最根本、最基本的,就是Service Worker以及在其内部使用的Cache API。只要通过Service Worker与Cache API,实现了对网站页面的缓存、对页面请求的拦截、对页面缓存的操纵,我认为一个简易的PWA应用就算搭建完成了。

1.什么是Service Worker

Service Worker是一个注册在指定源和路径下的事件驱动型Web Worker。它充当了Web应用程序与浏览器之间的代理服务器,进行资源在文件级别下的缓存与操控,拦截页面请求,实现在不同的情况下对不同请求的响应策略。

2.Service Worker的特点

首先,Service Worker本质上就是一个Web Worker,因此它具有Web Worker的特点:

1.无法操作DOM;
2.脱离主线程;
3.独立上下文;

除此之外,Service Worker还具有以下特点:

4.只能在Https下使用;
5.运行在浏览器后台,不受页面刷新影响;
6.更强大的离线缓存能力(使用Cache API);
7.请求拦截能力;
8.完全异步,不能使用同步API;
9.持续运行,第一次访问页面后,Service Worker就会安装激活并持续运行,直到手动销毁;
3.在页面中注册一个Service Worker
    if('serviceWorker' in navigator){
        window.addEventListener('load', function(){
            navigator.serviceWorker.register('/sw.js', {scope: '/' }).then(function(registration){
                console.log('ServiceWorker registration successful with scope: ' + registration.scope);
            }, function(err){
                console.log('ServiceWorker registration failed: ' + err);
            });
        });
    }

我们使用navigator.serviceWorker.register函数来注册Service Worker。其中,第一个参数为要执行的worker逻辑文件路径,注意这个路径是基于origin的,而非当前文件。第二个参数为Service Worker所能控制的文件范围,如果不填,则默认控制与sw.js文件同级范围下的所有文件。

4.Service Worker的生命周期

WechatIMG15.png
完成注册后,Service Worker开始进行安装,安装成功之后,会在worker中触发install事件;如果安装失败,则进入废弃状态。
安装成功之后,Service Worker开始进行激活。激活成功之后,会在worker中触发activate事件,这个时候,Service Worker就能够控制页面了,我们可以通过Service Worker去进行文件的缓存、请求的监听等操作。如果Service Worker激活失败,则会进入废弃状态。
如果Service Worker逻辑文件更新(相关资源文件变动或者内部逻辑更新等),Service Worker会重新安装,如果这个时候,页面依然存在激活状态下的worker(旧的Service Worker),那么新的worker会进入waiting状态进行等待,直到我们主动去操作worker强制其更新,或者等待用户关闭所有页面,这个时候新的worker才会进入到激活状态。

5.install事件
    //sw.js
    const CACHE_NAME = 'myCache';
    let urlsToCache = [
        '/html/index.html',
        'css/index.css'
    ];
    self.addEventListener('install', function(event){
        event.waitUntil(
            caches.open(CACHE_NAME).then(function(cache){
                console.log('Open cache');
                return cache.addAll(urlsToCache);
            }).then(function(){
                self.skipWaiting();
            })
        );
    });

在install事件中,我们使用caches.open方法打开cache对象,并通过cache.addAll缓存所有我们列出的文件。
如果Service Worker存在更新,我们使用skipWaiting跳过等待,直接强制新的worker进入激活状态。

6.fetch事件
    //sw.js
    self.addEventListener('fetch', function(event){
        if(event.request.method !== 'GET') return;
        event.respondWith(
            caches.match(event.request).then(function(response){
                if(response){
                    console.log('return caches');
                    return response;
                }else{
                    return fetch(event.request).catch(function(){
                        if(/\.html$/.test(event.request.url))
                            return caches.match('/html/neterror.html');
                    });
                }
            })
        )
    });

这里我们只监听了get请求,即我们只希望控制资源请求。通过caches.match检查请求是否命中了缓存,如果命中,则直接返回缓存给用户,防止重复请求,节约资源。如果没有命中,则将使用fetch方法请求网络资源并返回给用户。当网络状态异常时(fetch().catch()),返回404页面的缓存给用户,告知用户当前处于无网络状态,不能访问相关页面。
这种写法适用的情况为:我们指定了一些页面进行缓存,我们希望用户在无网络的情况下只能访问到我们指定缓存的页面。
当然,还有一种情况为,我们指定了一些页面进行缓存(常用页面),当用户访问到一些不常用页面时,再对其进行缓存。这样,我们对资源配置进行了优化,不过多的占用用户本地资源去缓存所有页面,对于非所有用户的常用页面,按需缓存。

    self.addEventListener('fetch', function(event){
        if(event.request.method !== 'GET') return;
        event.respondWith(
            caches.match(event.request).then(function(response){
                if(response){
                    console.log('return caches');
                    return response;
                }else{
                    return fetch(event.request).then(function(res){
                        var responseToCache = res.clone();
                        caches.open(CACHE_NAME).then(function(cache){
                            catch.put(event.request, responseToCache);
                        })
                        return res;
                    });

                }
            })
        )
    });
7.至此,一个简易的PWA应用,就算是完成了。

5.结束语

作为一个PWA的初学者,我也仅仅是把现阶段学到的部分总结在这里,还有很多的问题和情况都没有想到、遇到。这些等以后再慢慢的补充。文章或者代码中肯定也有许多讲的不合适、不规范的地方,如果有大佬看到了,还望提点。

Image placeholder
Brad
未设置
  44人点赞

没有讨论,发表一下自己的看法吧

推荐文章
workerman源码-workerman启动流程

前面我们跟着代码看了一遍workerman的初始化流程.但对于如何监听端口.等操作还没有具体的实现.我们这次就来看一下.workerman是如何监听端口并运行的.runAll在前面我们初始化方法过后,

Scss与Sass是什么?

之间的区别是什么?下面本篇文章就来给大家介绍一下。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。Sass是什么?Sass是一门高于CSS的元语言,它能用来清晰地、结构化地描述文件样式

php常用字符串查找函数strstr()与strpos()实例分析

这篇文章主要介绍了php常用字符串查找函数strstr()与strpos(),结合具体实例形式分析了php字符串查找函数strstr()与strpos()的具体功能、用法、区别及相关操作注意事项,需要

sass与scss的区别是什么?

Sass是采用Ruby语言编写的一款CSS预处理语言,它诞生于2007年,是最大的成熟的CSS预处理语言。最初它是为了配合HAML(一种缩进式HTML预编译器)而设计的,因此有着和HTML一样的缩进式

笨办法学 Linux 学习处理文件,`pwd`,`ls`,`cp`,`mv`,`rm`,`touch`

Bash:处理文件,pwd,ls,cp,mv,rm,touch 在Linux中,一切都是文件。但是什么是文件?现在完全可以说,它是一个包含一些信息的对象。它通常定义如下: 计算机文件是用于存储信息的

StopWatch —— 让 Spring 来帮你计算接口时间

课程推荐:前端开发工程师--学习猿地精品课程 是否还为接口计时而烦恼?是否还在无脑的复制System.currentTimeMillis()?是否还在为定位“慢代码瓶颈”而苦苦思索?我为大家来介绍一个

SQL Server 2014的数据库引擎新增功能(参考sqlserver官方文档)

SQLServer2014数据库引擎引入了一些新功能和增强功能,这些功能可以提高设计、开发和维护数据存储系统的架构师、开发人员和管理员的能力和工作效率。  以下是 数据库引擎已增强的方面。数据库引擎功

使用 Workerman 做一个聊天室

为什么要写这篇文章? 我学习Workerman好几次了,每次都失败(没做成想要的功能,原谅我比较笨)。但是这次也花了好几个小时,把之前没做成的功能实现了。其实就是两个简单的功能:一对一发送消息,广

基于内存和文件存储的 queue worker, 不用 Redis 适合单进程使用没有外部依赖

因为最近要做一个简单的并发任务系统,在github上面找了一圈并没有简单可依赖的库,所以自己写了一个。欢迎大家Review贡献代码。项目地址https://github.com/iflamed/mfw

聊聊chronos的DeleteBgWorker

序本文主要研究一下chronos的DeleteBgWorkerDeleteBgWorkerDDMQ/carrera-chronos/src/main/java/com/xiaojukeji/chron

Python入门教程_3. Python 简介

在下面的例子中,输入和输出分别由大于号和句号提示符(>>>和...)标注:如果想重现这些例子,就要在解释器的提示符后,输入(提示符后面的)那些不包含提示符的代码行。需要注意的是在练习中遇到的从属提示符

Go编程语言教程_1.0. Go编程语言(简介)

介绍 Go是一种过程编程语言。它由Google的RobertGriesemer,RobPike和KenThompson于2007年开发,但于2009年作为一种开放源代码编程语言发布。程序通过使用软件包

Git教程_3.1 Git 分支 - 分支简介

几乎所有的版本控制系统都以某种形式支持分支。使用分支意味着你可以把你的工作从开发主线上分离开来,以免影响开发主线。在很多版本控制系统中,这是一个略微低效的过程——常常需要完全创建一个源代码目录的副本。

Go语言高级编程_5.1 Web 开发简介

5.1Web开发简介 因为Go的net/http包提供了基础的路由函数组合与丰富的功能函数。所以在社区里流行一种用Go编写API不需要框架的观点,在我们看来,如果你的项目的路由在个位数、URI固定且不

基于Tcp协议与基于Http协议的RPC简介笔记

前言:之前对于RPC方面的学习多限于对RMI原理的学习,直到今天在看陈康贤前辈的《大型分布式网站架构-设计与实践》这本书的时候,才发现原来RPC可以基于TCP协议也可以基于HTTP协议(这里所说的TC

JavaScript基础之 DOM简介

JavascriptDOM(文档对象模型)是一个允许开发人员操纵页面内容、结构和风格的接口。在本文中,我们将理解什么是DOM以及如何用Javascript去操作它。本文还可以作为基本DOM操作的参考。

Vue生命周期挂钩简介

在本文中,我们来学习可用于VueJS工作流程的所有hooks。VueVueJS是一个非常先进的JavaScript框架,由尤雨溪和Vue核心团队创建,超过230个开源社区爱好者贡献了代码。Vue的用户

容器管理工具 ctop 简介

如果你经常在linux下工作,那你肯定对top以及它的增强版htop非常熟悉。如果说top是管理进程的,而ctop则是管理容器的。安装在centos下安装ctop$wgethttps://github

个人服务器架构简介

首先需要说一下服务器配置,只要你的服务器配置高于1核2G,均可使用该基础设施来管理你的个人服务器,你可以在服务中部署几个应用,并且把该服务器作为你的测试服务器来使用。但是你的应用过多,或者QPS稍大,

【数据结构】 10_C++异常简介

C++内置了异常处理的语法元素try...catch... try语句处理正常代码逻辑 catch语句处理异常代码逻辑 try语句中的异常由对应的catch语句处理 try { doubler=

XSS漏洞简介

课程推荐《前端工程师--赠送8个商业项目--学习猿地精品推荐》XSS漏洞简介跨站脚本攻击(XSS),是最普遍的Web应用安全漏洞。这类漏洞能够使得攻击者嵌入恶意脚本代码到正常用户会访问到的页面中,当正

JavaScript 简介

JavaScript简介 让我们来看看JavaScript有什么特别之处,我们可以用它实现什么,以及哪些其他技术可以与其搭配产生奇妙的效果。 什么是JavaScript? JavaScript最初被创

REST framework JWT Auth

JWT认证的REST框架 概述 这个包提供对DjangoRESTframework的JSONWebToken认证支持。 需要满足条件 Python(2.7,3.3,3.4,3.5) Django(1.

【翻译】REST framework JWT Auth

JWT认证的REST框架原文链接概述这个包提供对DjangoRESTframework的JSONWebToken认证支持。需要满足条件Python(2.7,3.3,3.4,3.5) Django(1.

看!闲鱼在ServiceMesh的探索和实践

背景在阿里服务端开发以Java为主的大背景下,其他异构语言业务如何调用现有Java服务,如何与集团中间件打通,就成为使用非Java语言团队必须要解决的首要问题。现状在ServiceMesh方案成熟之前