Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PWA笔记 #21

Open
isNeilLin opened this issue May 24, 2018 · 0 comments
Open

PWA笔记 #21

isNeilLin opened this issue May 24, 2018 · 0 comments
Labels
浏览器 浏览器相关

Comments

@isNeilLin
Copy link
Owner

Progressive Web Apps

  • 渐进增强 - 能够让每位用户使用,无论用户使用什么浏览器
  • 不依赖网络连接 - 通过ServiceWorker可以在离线或网速极差的环境下工作
  • 类原生应用 - 有像原生应用般的交互和导航给用户原生应用般的体验,因为它是建立在 app shell 模型上的。
  • 持续更新 - 受益于ServiceWorker的更新进程,应用能够始终保持更新
  • 安全 - 通过HTTPS来提供服务
  • 可发现 - 得益于 manifest 元数据和 ServiceWorker 的登记,让搜索引擎可以找到web应用
  • 再次访问 - 通过消息推送等特性让用户再次访问变得容易
  • 可安装 - 允许用户保留对他们有用的应用在主屏幕上,不需要通过应用商店
  • 可连接性 - 通过URL可以轻松分享应用,不用复杂的安装即可运行

浏览器支持

ServiceWorker 是什么

service worker 是独立于当前页面的一段运行在浏览器后台进程里的脚本。

service worker不需要用户打开 web 页面,也不需要其他交互,异步地运行在一个完全独立的上下文环境,不会对主线程造成阻塞。

service worker提供一种渐进增强的特性,使用特性检测来渐渐增强,不会在老旧的不支持 service workers 的浏览器中产生影响。可以通过service workers解决让应用程序能够离线工作,让存储数据在离线时使用的问题。

ServiceWorker 特点

  • 网站必须使用 HTTPS。除了使用本地开发环境调试时(如域名使用 localhost)
  • ServiceWorker是一个可编程的网络代理,允许开发者控制页面上处理的网络请求
  • 单独的作用域范围,单独的运行环境和执行线程。运行在它们自己的完全独立异步的�全局上下文中
  • 不能操作页面DOM,但可以通过 postMessage 方法与Web页面通信,让页面操作DOM
  • 浏览器可能随时回收ServiceWorker,在不被使用的时候他会自己终止,而当他再次被用到的时候,会被重新激活
  • ServiceWorker的生命周期是由事件驱动的而不是通过 Client

ServiceWorker 生命周期

install -> installed -> activating -> activate -> activated -> redundant

lifecycle

install

// 用于标注创建的缓存,也可以根据它来建立版本规范
const CACHE_NAME = "cache_v1.0.0";
// 列举要默认缓存的静态资源,一般用于离线使用
const urlsToCache = [
    '/offline.html',
    '/offline.png'
];

// self 为当前 scope 内的上下文
self.addEventListener('install', event => {
    // event.waitUtil 用于在安装成功之前执行一些预装逻辑
    // 但是建议只做一些轻量级和非常重要资源的缓存,减少安装失败的概率
    // 安装成功后 ServiceWorker 状态会从 installing 变为 installed
    event.waitUntil(
        // 使用 cache API 打开指定的 cache 文件
        caches.open(CACHE_NAME).then(cache => {
            console.log(cache);
            // 添加要缓存的资源列表
            return cache.addAll(urlsToCache);
        })
    );
});

只有urlsToCache中的文件全部安装成功,ServiceWorker才会认为安装成功。否则会认为安装失败,失败则进入redundant�(�废弃)状态。所以应当尽量少地缓存资源(一般认为离线时需要,联网时不会访问到的内容),以提升成功率。

ServiceWorker 更新

有更新的ServiceWorker完成安装后会进入waiting状态。直到所有已打开的页面都关闭,旧的 Service Worker 自动停止,新的 Service Worker 才会在接下来打开的页面里生效。
如果希望在有系版本时所有的页面都得到更新,可以在install事件中执行skipWaiting方法跳过waiting状态,然后回会直接进入activate阶段。接着在activate事件发生时,通过执行self.clients.claim()方法,更新所有客户端上的ServiceWorker

// 安装阶段跳过等待,直接进入 active
self.addEventListener('install', function(event) {
    event.waitUntil(self.skipWaiting());
});

self.addEventListener('activate', evnet => event.waitUntil(
    Promise.all([
        // 更新客户端
        clients.claim(),
        // 清理旧版本
        caches.keys().then(cacheList => Promise.all(
            cacheList.map(cacheName => {
                if (cacheName !== CACHE_NAME) {
                    caches.delete(cacheName);
                }
            })
        ))
    ])
));

添加到主屏幕(显示应用安装横幅)

显示应用安装横幅的条件:

  • 站点部署manifest.json,该文件需配置如下属性
    • short_name 用于主屏幕显示
    • name 用于安装横幅显示
    • icons 其中必须包含一个 mime 类型为 image/png 的图标声明
    • start_url 应用启动地址
    • display 必须为standalone�或fullscreen
  • 站点注册ServiceWorker
  • 站点支持HTTPS访问
  • 站点在同一浏览器中被访问至少两次,两次间隔至少5分钟

manifest.json的配置

{
    "short_name": "短名称",
    "name": "这是一个完整名称",
    "icon": [
        {
            "src": "../../images/logo-144x144.png",
            "type": "image/png",
            "sizes": "144x144"
        }
    ],
    "start_url": "./index.html"
}

应用横幅安装事件

beforeinstallprompt返回一个名为userChoice的Promise对象,并在用户对横幅�进行操作时进行解析,Promise会返回属性outcome,该属性的值为dismissedaccepted,如果用户将网页添加到主屏幕则返回accepted

window.addEventListener('beforeinstallprompt', function(e){
    e.userChoice.then(function(choiceResult){
        if(choiceResult.outcome==='dismissed'){
            console.log('用户取消�了安装')
        }else{
            console.log('用户安装了应用')
        }
    })
})

取消或延迟安装横幅的触发事件

网站虽然不能主动触发安装横幅的显示事件,但是当该事件被浏览器触发之后,可以对其进行取消或者延迟。

通过阻止 beforeinstallprompt 事件的默认行为,即可取消横幅弹出:

window.addEventListener('beforeinstallprompt', function (e) {
    e.preventDefault();
    return false;
});

beforeinstallprompt 事件返回一个名为prompt的方法,通过执行该方法可以触发安装横幅的显示。

var deferPrompt = null;
window.addEventListener('beforeinstallprompt',function(e){
    deferPrompt = e;
    e.preventDefault();
    return false;
})

button.addEventListener('click', function(){
    if(deferPrompt!=null){
        deferPrompt.prompt();
        deferPrompt.userChoice.then(function(choiceResult){
            console.log(choiceResult.outcome);
        })
        deferPrompt = null;
    }
})
@isNeilLin isNeilLin added 浏览器 浏览器相关 and removed 读书笔记 labels Jun 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
浏览器 浏览器相关
Projects
None yet
Development

No branches or pull requests

1 participant