WPA-渐进式 web 应用

PWA 是什么

渐进式 Web 应用,提升 web app 浏览体验。

manifest

应用程序清单

基本介绍:

  • web app manifest是 PWA 技术集合中的一部分

  • web app manifest可以让网站安装到设备的主屏幕,而不需要用户通过应用商店下载

  • web app manifest,在一个 JSON 文本文件中提供有关应用程序的信息(名称,作者,图标和描述等等)

  • 传统的 web app 入口

    • 网站
    • 书签,收藏夹
    • 直接搜索
  • Web app manifest:

    • 可以添加到桌面,有唯一的图标和名称
    • 有启动时的界面,避免生硬的过渡
    • 隐藏浏览器相关的 UI,比如地址栏等等
  • 适用步骤:

    • 在项目根目录创建一个 manifest.json 文件
    • 在 index.html 引入 manifest.json 文件
    • 在 manifest.json 文件中提供常见的配置
    • 需要在 https 协议或者在 http://localhost 下访问项目
    • <link rel="manifest" href="manifest.json" />
  • 常见配置清单

    • name:应用的指定名称,安装横幅的文字,启动画面的文字
    • short_name:应用的短名称,用于主屏幕显示
    • start_url:指定用户从设备启动应用程序时加载的 URL。可以是绝对路径和相对路径
    • icons:用于指定可在各种环境中用作应用程序图标的图像
    • background_color:用户启动时的背景色
    • theme_color:用于配置应用程序的主题颜色
    • display:用于指定 web app 的显示模式
      • fullscreen:全屏显示
      • standalone
      • minimal-ui

service worker

  • 基本介绍
  • 标准的 PWA 程序,包括 3 个部分
    • https 服务器或者 http://localhost
    • manifest.json
    • service worker
  • service worker 和 web worker
  • web worker 的使用
    • 创建:web worker  var worker = new Worker('work.js')
    • 在 web work 中进行复杂的计算
    • 在 web work 计算结束,通过 self.postMessage(msg)给主线程发消息
    • 主线程通过 worker.onmessage=function(msg){}监听消息
    • 主线程也可以用同样的方式给 web worker 进行通讯
  • service worker 介绍
    • 一旦 install 就会永远存在,除非手动 unregister
    • 用到的时候可以直接唤醒,不用的时候 自动睡眠
    • 可以变成拦截代理请求和返回,缓存文件,缓存的文件可以被网页进程取到,包括网络离线状态
    • 离线内容开发者可控
    • 必需在 HTTPS 环境下才能工作
    • 异步实现,内部大都是 Promise 实现
  • sevice worker 适用对象
    • 在 window.onload 中注册 service worker,防止与其他资源竞争
    • navigator 对象中内置了 serviceWorker 属性
    • service worker 在老版本的浏览器中不支持,需要进行浏览器兼容
      • if('serviceWorker in navigator'){}
    • 注册 service worker navigator.serviceWorker.register('./sw.js'),返回一个 promise 对象
<script>
//需要在localhost 或者 HTTPS中才能使用
// 网页加载完成时注册
window.addEventListener("load", () => {
// 能力检测
if ("serviceWorker" in navigator) {
navigator.serviceWorker.register("./sw.js").then((res) => {
console.log(res);
});
}
});
</script>
  • service worker 声明周期

    • install 事件会在 service worker 注册成功时候触发,主要用于缓存资源
    • activate 事件会在 service worker 激活的时候触发,主要用于删除旧的资源
    • fetch 事件会在发送请求的时候触发,主要用于操作缓存或者读取网络资源
    • 如果 sw.js 发生了改变,install 事件会重新触发
    • activate 事件会在 install 事件后触发,但是如果现在已经存在 service worker,就会处于等待状态直到 service worker 终止
    • 可以通过self.skipWaiting()方法跳过等待,返回一个 promise 对象
    • 可以通过event.WautUntil()方法扩的参数是一个 promise 对象,会在 promise 结束后才会结束当前生命周期函数,防止浏览器在一步操作之前就停止了生命周期
    • service worker 激活后,会在下一次刷新页面的时候生效,可以通过self.clients.claim()立即活的控制权
self.addEventListener("install", (event) => {
console.log("install", event);
});
self.addEventListener("activate", (event) => {
console.log("activate", event);
});
self.addEventListener("fetch", (event) => {
console.log("fetch", event);
});
self.addEventListener("install", (event) => {
console.log("install", event);
// skipWaiting 会让serviceworker跳过等待,直接进入activate
//waitUntil 等待skipWaiting结束才进入到activate
event.waitUntil(self.skipWaiting());
});
self.addEventListener("activate", (event) => {
console.log("activate", event);
// 表示service worker激活后,立即活的控制权
event.waitUntil(self.clients.claim());
}); //fetch事件会在请求发送的时候触发
self.addEventListener("fetch", (event) => {
console.log("fetch", event);
});

promise

  • 基本适用
  • Promise 是异步编程的一种解决方案,比传统的解决方法,回调函数和事件更强大
  • Promise 可以以链式的方式来进行异步编程,解决了回调地狱的问题
  • Promise 常用的静态方法
    • Promise.resolve()返回一个解析过带着给定值的 Promise 对象,如果返回值是一个 Promise 对象,则直接返回这个 Promise 对象
    • Promise.reject()静态函数 Promise.reject()返回一个被拒绝的 Promise 对象
    • Promise.all() 返回一个 Promise 实例,等所有 promise 对象都成功了,才成功
    • Promise.race()竞速,只要有一个 Promise 对象成功了或者失败了,结果就是成功或者失败了

async/await

  • 基本适用
  • ES2017(ES8)标准引入了 async 函数,使得异步操作变得更加方便
  • async 用于修饰一个函数  async function fn(){},await 函数会返回一个 promise 对象
  • await 只能出现在 async 函数中,await 后面跟一个 promise 对象,用于获取 promise 对象成功的结果,如果不是 promise 对象,直接返回值
  • await 会阻塞 async 函数的执行
  • await 后面的 promise 如果没有成功,那么会抛出异常需要用 try catch 语法

fetch api

在 service worker 如果想要发送请求,必需适用 fetch api

基本使用:

fetch("./manifest.json")
.then((res) => {
return res.json();
})
.then((data) => {
console.log(data);
});

cache storage

cacheStorage 接口表示 Cache 对象的储存,配合 service worker 来实现资源的缓存

  • cache api 类似于数据库的操作

    • caches.open(cacheName).then(res=>{}),用于打开缓存,返回 一个匹配 cacheName 的 cache 对象的 Promise,类似于连接数据库
    • caches.key() 返回一个 promise 对象,包括所有的缓存 key
    • caches.delete(key) 根据 key 删除对应的缓存
  • cache 对象常用方法:
    • cache 接口为缓存的 Request/Response 对象对提供存储机制
    • cache.put(req,res)把请求当成 key,并且把对应的响应存储起来
    • cache.add(url)根据 url 发起请求,并且吧响应结果储存起来
    • cache.addAll(urls) 抓取一个 url 数组,并且把结果都储存起来
    • cache.match(req) 获取 req 对应的 response

开启缓存:

<!-- index.html -->
<script>
// 网页加载完成时注册
window.addEventListener("load", async () => {
// 能力检测
if ("serviceWorker" in navigator) {
try {
const registration = await navigator.serviceWorker.register("/sw.js");
console.log("注册成功");
} catch (error) {
console.log("注册成功", error);
}
}
});
</script>
//sw.js
// 主要用来缓存内容
const CACHE_NAME = "cache_v1";
self.addEventListener("install", async (event) => {
// 开启一个cache 得到一个cache对象
const cache = await caches.open(CACHE_NAME);
// 等待cache把所有的资源存储
await cache.addAll(["/", "/img/icon.png", "/manifest.json", "/index.css"]);
// 会让service worker跳过等待,直接进入activate
// 等待skipWaiting结束才进入到activate
await self.skipWaiting();
});
// 主要清除旧的缓存
self.addEventListener("activate", async (event) => {
const keys = await caches.keys();
// 判断key 删除旧的资源
keys.forEach((key) => {
if (key !== CACHE_NAME) {
caches.delete(key);
}
});
// 表示service worker激活后,立即活的控制权
await self.clients.claim();
}); // fetch事件 会在请求发送的时候触发
// 判断资源是否能够请求成功,如果能请求成功,就响应成功的结果,如果断网,请求失败了,读取cache缓存即可
self.addEventListener("fetch", (event) => {
// console.log('fetch', event)
const req = event.request;
event.respondWith(networkFirst(req));
});
// 网络优先
async function networkFirst(req) {
try {
// 优先网络读取最新的资源
const fresh = await fetch(req);
return fresh;
} catch (e) {
// 去缓存中读取
const cache = await caches.open(CACHE_NAME);
const cached = await cache.match(req);
return cached;
}
}

notification api

  • 基本使用:
  • Notification API 的通知接口用于向用户配置和显示桌面通知
  • Notification.permission 可以获取当前用户的授权情况
    • Default:默认,未授权
    • Denied:拒绝的,拒绝无法再次授权
    • Granted:授权的,可以弹窗提醒
  • 通过Notification.requestPermission()可以请求用户的授权
  • 通过new Notification('title',{body:'',icon:''}) 可以显示通知
  • 在授权通过得情况下,可以在 service worker 中显示通知self.registration.showNotification('你好',{body:'msg'})
// 通知消息
if (Notification.permission === "default") {
Notification.requestPermission();
}
if (navigator.onLine) {
new Notification("提示", {
body: "欢迎使用耶温记账本~,此应用为PWA应用支持离线使用~",
});
}

JavaScript深入理解-PWA渐进式应用的更多相关文章

  1. Javascript中理解发布--订阅模式

    Javascript中理解发布--订阅模式 阅读目录 发布订阅模式介绍 如何实现发布--订阅模式? 发布---订阅模式的代码封装 如何取消订阅事件? 全局--发布订阅对象代码封装 理解模块间通信 回到 ...

  2. 第一百二十九节,JavaScript,理解JavaScript库

    JavaScript,理解JavaScript库 学习要点: 1.项目介绍 2.理解JavaScript库 3.创建基础库 从本章,我们来用之前的基础知识来写一个项目,用以巩固之前所学.那么,每个项目 ...

  3. 《javascript个人理解,个人整理。》

    万事开头难. 本人做前端工程师,已几年,没有特别大的,已文字方式去做总结. 前段时间,早已经想好,但是迟迟没有去下笔!好在现在陆陆续续的写下去. 我知道这是一个很大的工程,但是我还是想做下去,不为别的 ...

  4. 【转】Javascript中理解发布--订阅模式

    Javascript中理解发布--订阅模式 阅读目录 发布订阅模式介绍 发布---订阅模式又叫观察者模式,它定义了对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时 ...

  5. JavaScript深入理解sort()方法

    一. 基本用法 let arr1 = [3, 5, 7, 1, 8, 7, 10, 20, 19] console.log(arr1.sort()) // [1, 10, 19, 20, 3, 5, ...

  6. javascript深入理解js闭包(转)

    javascript深入理解js闭包 转载  2010-07-03   作者:    我要评论 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. ...

  7. PWA 渐进式Web应用程序 - 解释

    想象一下,如果一个网站上所有的功能都能够作为一个移动应用程序为用户所用——任何设备上都可以使用.可接收所有的通知.离线模式可用,为了实现这个愿景,2015年,谷歌创造了渐进式Web应用程序(PWA). ...

  8. javascript的理解及经典案例

    js的简介: JavaScript是一种能让你的网页更加生动活泼的程式语言,也是目前网页中设计中最容易学又最方便的语言. 你可以利用JavaScript轻易的做出亲切的欢迎讯息.漂亮的数字钟.有广告效 ...

  9. javascript深入理解js闭包

    一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...

随机推荐

  1. Python爬虫_百度贴吧

    # 本爬虫为爬取百度贴吧并存储HTMLimport requests class TiebaSpider: def __init__(self, tieba_name): self.tieba_nam ...

  2. vue子组件的样式没有加scoped属性会影响父组件的样式

    scoped是一个vue的指令,用来控制组件的样式生效区域,加上scoped,样式只在当前组件内生效,不加scoped,这个节点下的样式会全局生效. 需要注意的是:一个组件的样式肯定是用来美化自己组件 ...

  3. 如何将IHttpHandler和IHttpModule迁移到ASP.NET Core中间件

    ASP.NET Core是一个跨平台.开源的框架,用于在Windows.Mac和Linux操作系统(OS)上开发web应用程序.你可以使用以下任何IDE开发ASP.NET Core 应用程序: Vis ...

  4. 基于docker搭建DNSmasq

    一.概述 DNSmasq是一个小巧且方便地用于配置DNS和DHCP的工具,适用于小型网络,它提供了DNS功能和可选择的DHCP功能.它服务那些只在本地适用的域名,这些域名是不会在全球的DNS服务器中出 ...

  5. Docker安装Openvas

    目录 安装 在本机内运行 在局域网内运行 关闭 参考 安装 ➜ ~ docker search openvas NAME DESCRIPTION STARS OFFICIAL AUTOMATED mi ...

  6. brew安装Nginx

    目录 安装流程 常用命令记录 典型配置方式 查看启动状态是否有报错 php 启动 参考 安装流程 这里使用 brew 来安装软件. 安装 brew install nginx 查看安装信息(经常用到, ...

  7. IDEA中部署servlet

    配置和不是servlet 第一种方法:(两种方法不能混用,使用第一种方法后,尽量删除第二种方法的注解方式) 使用xml文件配置: name没有什么特别的,就是需要统一即可.url-pattern中的地 ...

  8. 解决:layUI数据表格+简单查询

    解决:layUI数据表格+简单查询 最近在用layui写项目,在做到用户查询时,发现在layui框架里只有数据表格,不能增加查询.于是自己摸索了一下,写个笔记记录一下. 我想要的效果: 1.定义查询栏 ...

  9. 手工实现一个ThreadPoolExecutor

    以下代码的实现逻辑出自于公众号 码农翻身 <你管这破玩意叫线程池?> - PS:刘欣老师在我心中是软件技术行业的大刘. 线程池接口 public interface Executor { ...

  10. SpringBoot项目创建与单元测试

    前言   Spring Boot 设计之初就是为了用最少的配置,以最快的速度来启动和运行 Spring 项目.Spring Boot使用特定的配置来构建生产就绪型的项目. Hello World 可以 ...