精华内容
下载资源
问答
  • pwa h5快应用缓存

    2020-11-26 09:58:21
    1.pwa 前后端分离后 manifest的应用(随着 前后端分离缓存 html 和css 使用ajax局部刷新这个问题得到了很好的解决) 简而言之,我crossorigin="use-credentials"在本节中添加了<link rel="manifest">元素<...

    1https://segmentfault.com/a/1190000019414253 // 创建一个pwa 应用
    1.pwa 前后端分离后 manifest的应用(随着 前后端分离缓存 html 和css 使用ajax局部刷新这个问题得到了很好的解决)

    简而言之,我crossorigin="use-credentials"在本节中添加了<link rel="manifest">元素<head>

    参考:https://www.w3.org/TR/2020/WD-appmanifest-20201019/#name-member
    参考:https://www.jianshu.com/p/916a01670a23
    参考 https://blog.csdn.net/hellodake/article/details/84024148
    参考:https://developer.mozilla.org/zh-CN/docs/Web/Manifest
    参考:https://segmentfault.com/a/1190000012353473

    {
     
        // 必须的字段3个
     
        "name": "MyExtension", // 扩展名称
     
        "version": "1.0", // 版本。由1到4个整数构成。多个整数间用"."隔开
     
        "manifest_version": 2, // manifest文件版本号。Chrome18开始必须为2
     
        // 建议提供的字段3个
     
        "description": "",   // 描述。132个字符以内
     
        "icons": {
     
           "16": "image/icon-16.png",
     
           "48": "image/icon-48.png",
     
           "128": "image/icon-128.png"
     
        }, //扩展图标。推荐大小16,48,128
     
        "default_locale": "en", // 国际化
     
        // 以下字段多选一,或者都不提供
     
        "browser_action": {
     
           "default_icon": "image/icon-128.png",
     
            "default_title": "My Test",
     
           "default_popup": "html/browser.html"
     
        }, //地址栏右侧图标管理。含图标及弹出页面的设置等
     
        "page_action": {
     
            "default_icon": "image/icon-48.png",
     
            "default_title": "My Test",
     
            "default_popup": "html/page.html"
     
        }, //地址栏最后附加图标。含图标及行为等
     
        "theme": {}, // 主题,用于更改整个浏览器的外观
     
        "app": {}, // 指定扩展需要跳转到的URL
     
        // 根据需要提供
     
        "background": {
     
           "scripts": [
     
               "lib/jquery-3.3.1.min.js",
     
               "js/background.js"
     
           ] ,
     
            "page":"html/background.html"
     
        }, // 指定扩展进程的background运行环境
     
        "chrome_url_overrides": {
     
           "pageToOverride": "html/overrides.html"
     
        }, //替换页面。详见注释1
     
        "content_scripts": [{
     
          "matches": ["https://www.baidu.com/*"],
     
          "css": ["css/mystyles.css"],
     
          "js": ["lib/jquery-3.3.1.min.js", "js/content.js"]
     
        }], // 指定在web页面运行的脚本。详见注释2
     
        "content_security_policy": "",  // 安全策略
     
        "file_browser_handlers": [],   
     
        "homepage_url": "http://xxx", // 扩展的官方主页
     
        "incognito": "spanning", //"split"。详见注释3
     
        "intents": {}, // 用户操作意图描述
     
        "key": "", // 扩展唯一标识。不需要人为指定
     
        "minimum_chrome_version": "1.0", // 扩展所需chrome的最小版本
     
        "nacl_modules": [],  // 消息与本地处理模块映射
     
        "offline_enabled": true, // 是否允许脱机运行
     
        "omnibox": {
     
           "keyword": "myKey"
     
        }, //ominbox即地址栏。用于响应地址栏的输入事件
     
        "options_page": "aFile.html", // 选项页。用于在扩展管理页面跳转到选项设置
     
        "permissions": [
     
           "https://www.baidu.com/*",
     
           "background",
     
           "tabs"
     
        ], //权限。详见注释4
     
        "plugins": [{
     
           "path": "extension_plugin.dll",
     
           "public": true
     
        }], // 扩展。可调用第三方扩展
     
        "requirements": {}, // 指定所需要的特殊技术。目前只支持"3D"
     
        "update_url": "http://path/to/updateInfo.xml",   // 自动升级
     
        "web_accessible_resources": [] // 指定资源路径,为String数组
     
    }
    
    
    {
      "package": "com.lingan.seeyouxiaomi",
      "name": "美柚",
      "version": "1.2",
      "versionCode": 3,
      "versionName": "1.2",
      "minPlatformVersion": 100,
      "icon": "/Common/resources/logo_180.png",
      "features": [
        {
          "name": "com.miui.hybrid.features.Network"
        },
        {
          "name": "system.fetch"
        },
        {
          "name": "system.storage"
        },
        {
          "name": "system.prompt"
        }
      ],
      "permissions": [
        {
          "origin": "*"
        }
      ],
      "config": {
        "logLevel": "debug"
      },
      "router": {
        "entry": "Home",
        "pages": {
          "Home": {
            "component": "home"
          },
          "Me": {
            "component": "me"
          },
          "Setup": {
            "component": "setup"
          },
          "Records": {
            "component": "records"
          },
          "About": {
            "component": "about"
          },
          "Login": {
            "component": "login"
          },
          "Setpw": {
            "component": "setpw"
          },
          "Tips": {
            "component": "tips"
          }
        }
      },
      "display": {
        "backgroundColor": "#ffffff",
        "titleBar": true,
        "titleBarBackgroundColor": "#ff5073",
        "titleBarTextColor": "#ffffff",
        "pages": {
          "Home": {
            "titleBarText": "美柚"
          },
          "Me": {
            "titleBarText": "美柚"
          },
          "Setup": {
            "titleBarText": "经期设置"
          },
          "Records": {
            "titleBarText": "我的记录"
          },
          "About": {
            "titleBarText": "关于美柚"
          },
          "Login": {
            "titleBarText": "登入"
          },
          "Setpw": {
            "titleBarText": "填写密码"
          },
          "Tips": {
            "titleBarText": "今日贴士"
          }
        }
      }
    }
    

    简而言之,我crossorigin="use-credentials"在本节中添加了元素。

    参考链接:https://github.com/alienzhou/learning-pwa/tree/manifest

    2.php 是后台渲染 因此缓存的模式

    <!DOCTYPE html>
    //缓存文件 demo.appcache 缓存appchache 网络传输是先本地 局域网 广域网 依次往上找(类似原型链)
    <html lang="en" manifest="demo.appcache">
    <head>
        <meta charset="UTF-8">
        <title>10-应用程序缓存</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
        </style>
        <script src="../js/cookie.js"></script>
        <script src="../js/jquery-3.3.1.js"></script>
        <script src="../js/template-web.js"></script>
    
    </head>
    <body>
    
    </body>
    <html>
    

    缓存文件表示

    //demo.appcache
    CACHE MANIFEST
    # 2020-02-21 v1.0.0 备注时间
    /theme.css  //缓存 css
    /logo.gif   //缓存 logo.gif
    /main.js    //缓存 main.js
    
    NETWORK:    //缓存的线上资源
    login.asp
    
    FALLBACK:  //访问资源 第二个是替补资源
    ml5/ /404.html
    

    php 后台渲染 有个问题 每次动态的资源 都会拿缓存本地的得不到更新(弊端) 解决方案:动态manifest文件

    <html  manifest="http://www.sofish.de/sofished.manifest">
    

    nginx 传输缓存(网路请求缓存)

    text/cache-manifest         appcache;
    

    转载:https://www.cnblogs.com/brainmao/archive/2011/09/27/2193495.html
    一、什么是 Cache Manifest
    话说,作为一个 web 开发相关的人员,都不会少听到、看到 cache 这个词。是的,上面也已经说了,它是一种缓存的机制。它可以通过一个 .manifest 文件来配置需要缓存的或者一定要保持联网缓存的文件。而重点就是这个 .manifest 文件,具体的可以 Google 一下,而简单的我帮你整理一下现在可能会希望了解的东西:

    MIME TYPE:text/cache-manifest
    需要由你创建的:NAME.manifest
    作用:主要是配置需要缓存的文件
    二、如何实现
    实现起来倒是非常简单(当然,这也是有问题的,这个我们后面讲解决方案),实现步骤如下:

    在服务器上添加MIME TYPE支:
    比如 Apache 中可在 .htaccess 中添加:

    AddType text/cache-manifest manifest
    创建 NAME.manifest:
    其中第一行的 CACHE MANIFEST 标识是一定要有的,而 CACHE / NETWORK / FACKBACK 都是可选的。如果没有写标识,则默认缓存,CACHE 就不用说了,缓存;NETWORK 指不想缓存的页面,比如登陆页等;FALLBACK 是指当没有响应时的替代方案,比如我想请求某个页面,但这个页面的服务器挂了,那么,我可以显示另外一个指定的页面,文件结构如下:

    配置文件参考

    CACHE MANIFEST
    
    # VERSION 0.3
    
    # 直接缓存的文件
    CACHE:
    abc.html
    images/sofish.png
    js/main.js
    css/layout.css
    
    # 需要在时间在线的文件
    NETWORK:
    /wp-admin/
    
    # 替代方案
    FALLBACK:
    /ajax/ ajax.html
    

    配置文件参考

    CACHE MANIFEST
    # 井号备注,这边可以放版本更新时间,修改备注算更新 manifest 文件
    CACHE:
    # 首次下载 CACHE 后列出来的文件后缓存到本地。
    /favicon.ico
    /main.css
     
    NETWORK:
    # NETWORK 下的文件不可被缓存,必须要与服务器连接。
    login.php
     
    FALLBACK:
    # 一行放两个路径,第一个是访问资源,第二个是替补;当无法访问前一个资源时,用后一个资源代替之。
    /cat/ /404.html
    

    至于如何更新这个配置文件?只要改变文件的内容即可,上面的 # VERSION 0.3 其实只是一行注释,但改变文件可以重新缓存,这样写上版本号,想更新的时候修改版本号来重新缓存,是一种比较推荐的方法,甚至可以是最佳实践。

    给 标签加 manifest 属性:

    是的,就是如此简单,相信你花上30分钟也就了解了。当时我也这样。随后也很快地应用上去。结果。结果就是像这篇文章一样还没写完,但没有时间折腾,而是速速把它撤下,等问题解决后再应用。

    三、Cache Manifest 存在的问题
    经过上面一整,速度当然爽,帮忙测试的人也小震惊了一下,只是,还是存在一些问题,看一下,然后我们尝试解决:

    自动缓存引用了 manifest 文件的页面
    即使在 NETWORK 中指定 “*”(所有的页面都)使用网络,还是不能解决它自动缓存当前页面。这使得这个页面在 manifest 没有变更的情况下,会一直以"类静态"存在。比如,你后台更新了一篇文章,这个动态的首页,还是像第一次缓存的时候一样,没有变。这对于静态页面还好,但应用在一个动态系统就很麻烦了,因为你的内容是时时要更新的。

    Firefox 弹出提示信息
    可能是习惯了弹窗警告之类的,一不小心,用户还以为是网站被人挂马呢,想把不干净的东西存储到他的电脑。

    159445840.jpg

    四、解决方案
    (一)关于自动缓存当前页面

    我查了 w3c 的文档,也看了 《Pro HTML5 Programming》的第10章(Creating HTML5 Offline Web Applications),最后还是 div into HTML5 的那句话,原意大概是:这并不是 Bug,而是机制的需要。

    真是杯具,反正我能理解到的是,这是一种强加的功能。虽然说这样会让页面载入更快,但对于动态页面来说就是恶心了。至少应该有一种让用户选择是否缓存当前页的配置方案(或者说是一个开关)。不过,这是暂时不能解决的,毕竟这还只是一个 Draft,我们要用,就应用找一个合适的方案。

    我的想法是,看看大家有没有更好的办法。结果,查了一下,无果。新的东西,几乎所有文章说的都只是我上面说的那个如何去写一个 manifest 文件,看来还是没办法偷懒。然后,便开始想:

    一定不要缓存动态的页面,当前页一定不能引用 manifest文件
    能不能从其他页面先载入缓存?
    那么,如果有解决方案的话,解决方法应该是:

    不在当前页面引用 manifest
    在用户打开页面之前,需要有一个页面来实现缓存机制
    如果这样,那么为何不试一下 iframe 来引入一个拥有 manifest 的静态文件?但用 iframe 还能会缓存到文件?经过一翻测试,Google Chrome 的调试工具给了答案:

    manifest.png

    太给力啦!!竟然成功缓存。做法是这样的,新建一个 cache.html 文件来当做为当前页面的代理,内容如下:

    <!DOCTYPE html>
    <html  manifest="http://www.sofish.de/sofished.manifest">
    <head>
            <meta charset=utf-8 />
            <title>cache</title>
    </head>
    <body>
    hi sofish!
    </body>
    </html>
    

    然后,在每个页面通过 iframe 来引用这个静态文件,以达到我们不缓存当面页面,只缓存我们希望缓存文件的目的。

    (二)关于 Firefox 弹出警告问题

    这个,浏览器默认的,浏览器厂商的目的是为用户的安全着想,我们暂时也改变不了。其实,也不会有太大的影响,我也没有好好去想。

    五、总结
    测试下来,其实跟缓存当前页面还是有差别的,毕竟像站外的链接,特别是 gravatar 总要请求这么多图片,这点就又多了一点时间了。这现象主要出现在 Firefox 下,而 Webkit 而表示非常棒,速度几乎和缓存当前面一样,第二次打开的页面,都是瞬间响应的, 这点不得不赞啊。

    对于实践的 Demo,本来可以提供一份,不过,瞄了一下,突然发现自己写得太专心了,已凌晨 2:49 了,明天还要上班。所以,打开你的调试工具,把本博当 Demo 看吧,这是最直接的应用了。

    好吧,大概就这样,能为用户省多少就是多少,这是一个前端希望做到的,也是能做到的。这也算是有了 fallback 方案。期待你,看到最后的你,还有更好的方法。也期待 HTML5 的发展,期待这些给力的新技术。

    广积粮,筑高墙,缓称王

    展开全文
  • 主要介绍了PWA介绍及快速上手搭建一个PWA应用的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • PWA介绍及快速上手搭建一个PWA应用

    千次阅读 2020-04-12 21:27:13
    PWA初次体验 ​ 前言:本示例不用安装任何...一个新的前端技术,PWA( 全称:Progressive Web App )也就是说这是个渐进式的网页应用程序。 官网:https://developers.google.com/web/progressive-web-apps/ 是 ...

    PWA初次体验

    ​ 前言:本示例不用安装任何东西

    部分资源来自网络资源及PWA官网,不要把PWA想象的太复杂,跟着示例走一下,你行的。

    PWA介绍

    一个新的前端技术,PWA( 全称:Progressive Web App )也就是说这是个渐进式的网页应用程序。

    官网:https://developers.google.com/web/progressive-web-apps/

    是 Google 在 2015 年提出,2016年6月才推广的项目。是结合了一系列现代Web技术的组合,在网页应用中实现和原生应用相近的用户体验。

    官网上给出 PWA 的宣传是 : Reliable ( 可靠的 )、Fast( 快速的 )、Engaging( 可参与的 )

    Reliable :当用户从手机主屏幕启动时,不用考虑网络的状态是如何,都可以立刻加载出 PWA。

    Fast:这一点应该都很熟悉了吧,站在用户的角度来考虑,如果一个网页加载速度有点长的话,那么我们会放弃浏览该网站,所以 PWA 在这一点上做的很好,他的加载速度是很快的。

    Engaging : PWA 可以添加在用户的主屏幕上,不用从应用商店进行下载,他们通过网络应用程序 Manifest file 提供类似于 APP 的使用体验( 在 Android 上可以设置全屏显示哦,由于 Safari 支持度的问题,所以在 IOS 上并不可以 ),并且还能进行 ”推送通知” 。

    PWA关键技术

    • Service Worker (可以理解为服务工厂)
    • Manifest (应用清单)
    • Push Notification(推送通知)

    Service Worker

    以下用SW来表示

    SW 是什么呢?这个是离线缓存文件。我们 PWA 技术使用的就是它!SW 是浏览器在后台独立于网页运行的脚本,它打开了通向不需要网页或用户交互的功能的大门,因为使用了它,才会有的那个 Reliable 特性吧,SW 作用于 浏览器于服务器之间,相当于一个代理服务器。

    浏览器支持

    顺便带一句:目前只能在 HTTPS 环境下才能使用SW,因为SW 的权利比较大,能够直接截取和返回用户的请求,所以要考虑一下安全性问题。

    image

    事件机制

    image

    功能(还是比较逆天的)

    • 后台数据的同步
    • 从其他域获取资源请求
    • 接受计算密集型数据的更新,多页面共享该数据
    • 客户端编译与依赖管理
    • 后端服务的hook机制
    • 根据URL模式,自定义模板
    • 性能优化
    • 消息推送
    • 定时默认更新
    • 地理围栏

    生命周期

    image

    • Parsed ( 解析成功 ): 首次注册 SW 时,浏览器解决脚本并获得入口点,如果解析成功,就可以访问到 SW 注册对象,在这一点中我们需要在 HTML 页面中添加一个判断,判断该浏览器是否支持 SW 。

    • Installing ( 正在安装 ):SW 脚本解析完成之后,浏览器会尝试进行安装,installing 中 install 事件被执行,如果其中有 event.waitUntil ( ) 方法,则 installing 事件会一直等到该方法中的 Promise 完成之后才会成功,如果 Promise 被拒绝,则安装失败,SW会进入 Redundant( 废弃 )状态。

    • Installed / Waiting (安装成功/等待中):如果安装成功,SW 将会进入这个状态。

    • Activating ( 正在激活 ):处于 waiting 状态的 SW 发生以下情况,将会进入 activating 状态中:

      当前已无激活状态的 worker 、 SW脚本中的 self.skipWaiting()方法被调用 ( ps: self 是 SW 中作用于全局的对象,这个方法根据英文翻译过来也能明白什么意思啦,跳过等待状态 )、用户已关闭 SW 作用域下的所有页面,从而释放了当前处于激活状态的 worker、超出指定时间,从而释放当前处于激活状态的 worker

    • Activated ( 激活成功 ):该状态,其成功接收了 document 全面控制的激活态 worker 。

    • Redundant ( 废弃 ):这个状态的出现时有原因的,如果 installing 事件失败或者 activating 事件失败或者新的 SW 替换其成为激活态 worker 。installing 事件失败和 activating 事件失败的信息我们可以在 Chrome 浏览器的 DevTools 中查看

    一个很不错的全面介绍sw的教程:https://www.villainhr.com/page/2017/01/08/Service%20Worker%20%E5%85%A8%E9%9D%A2%E8%BF%9B%E9%98%B6

    Manifest

    Web App Manifest 是一个 W3C 规范,它定义了一个基于 JSON 的 List 。Manifest 在 PWA 中的作用有:

    ​ 能够将你浏览的网页添加到你的手机屏幕上

    ​ 在 Android 上能够全屏启动,不显示地址栏 ( 由于 Iphone 手机的浏览器是 Safari ,所以不支持哦)

    ​ 控制屏幕 横屏 / 竖屏 展示

    ​ 定义启动画面

    ​ 可以设置你的应用启动是从主屏幕启动还是从 URL 启动

    ​ 可以设置你添加屏幕上的应用程序图标、名字、图标大小

    Push Notification

    Push 和 Notification 是两个不同的功能,涉及到两个 API 。

    ​ Notification 是浏览器发出的通知消息。

    ​ Push 和 Notification 的关系,Push:服务器端将更新的信息传递给 SW ,Notification: SW 将更新的信息推送给用户。

    PWA示例

    准备

    我们先创建一个关于 PWA 的项目文件夹,

    进入文件夹下我们准备一张 120x120的图片一张,作为我们的应用程序图标。

    创建一个 index.html 文件

    创建一个 main.css 文件

    创建一个 manifest.json 文件

    创建一个 sw.js 文件

    image

    index.html

     

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Hello PWA</title>
      <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
      <link rel="stylesheet" href="main.css">
      <link rel="manifest" href="manifest.json">
    </head>
    <body>
      <h3>Hello PWA</h3>
    </body>
    <script>
      // 检测浏览器是否支持SW
      if(navigator.serviceWorker != null){
        navigator.serviceWorker.register('sw.js')
        .then(function(registartion){
          console.log('支持sw:',registartion.scope)
        })
      }
    </script>
    </html>
    

    main.css

     

    h3{
      color: #f00;
    }
    

    manifest.json

    short_name: “ " 用户主屏幕上的应用名字

    display : “standalone" 设置启动样式,让您的网络应用隐藏浏览器的 URL 地址栏

    start_url : “/“ 设置启动网址,如果不提供的话,默认是使用当前页面

    theme_color : “ “ 用来告知浏览器用什么颜色来为地址栏等 UI 元素着色

    background_color: “ ” 设置启动页面的背景颜色

    icons:”” 就是添加到主屏幕之后的图标

     

    {
      "name": "一个PWA示例",
      "short_name": "PWA示例",
      "start_url": "/index.html",
      "display": "standalone",
      "background_color": "#fff",
      "theme_color": "#3eaf7c",
      "icons": [
        {
          "src": "/youhun.jpg",
          "sizes": "120x120",
          "type": "image/png"
        }
      ],
    }
    
    

    sw.js

    看网上很多人都安装的hs和ngrok去调试,在这里为了照顾新手我是直接引用的sw

    处理静态缓存,首先定义需要缓存的路径,以及需要缓存的静态文件的列表。

    借助 SW 注册完成安装 SW 时,抓取资源写入缓存中。使用了一个方法那就是 self.skipWaiting( ) ,为了在页面更新的过程当中,新的 SW 脚本能够立刻激活和生效。

     

    importScripts("https://storage.googleapis.com/workbox-cdn/releases/3.1.0/workbox-sw.js");
    var cacheStorageKey = 'minimal-pwa-1'
    var cacheList=[
      '/',
      'index.html',
      'main.css',
      'youhun.jpg'
    ]
    self.addEventListener('install',e =>{
      e.waitUntil(
        caches.open(cacheStorageKey)
        .then(cache => cache.addAll(cacheList))
        .then(() => self.skipWaiting())
      )
    })
    

    处理动态缓存,我们监听 fetch 事件,在 caches 中去 match 事件的 request ,如果 response 不为空的话就返回 response ,最后返回 fetch 请求,在 fetch 事件中我们可以手动生成 response 返回给页面。

    更新静态资源,缓存的资源会跟随着版本的更新会过期的,所以会根据缓存的字符串名称清除旧缓存。在新安装的 SW 中通过调用 self.clients.claim( ) 取得页面的控制权,这样之后打开页面都会使用版本更新的缓存。旧的 SW 脚本不在控制着页面之后会被停止,也就是会进入 Redundant 期。

     

    self.addEventListener('fetch',function(e){
      e.respondWith(
        caches.match(e.request).then(function(response){
          if(response != null){
            return response
          }
          return fetch(e.request.url)
        })
      )
    })
    self.addEventListener('activate',function(e){
      e.waitUntil(
        //获取所有cache名称
        caches.keys().then(cacheNames => {
          return Promise.all(
            // 获取所有不同于当前版本名称cache下的内容
            cacheNames.filter(cacheNames => {
              return cacheNames !== cacheStorageKey
            }).map(cacheNames => {
              return caches.delete(cacheNames)
            })
          )
        }).then(() => {
          return self.clients.claim()
        })
      )
    })
    

    部署

    我们可以把当前pwa目录的所有内容都扔进服务器中,或者coding Pages和gitHub Pages也是可以的,当然,记得开启https。在上变介绍过SW的权利比较大,为了安全性,我们使用https协议来访问。

    试着访问一下,我们这里用的coding Pages并且绑定了自己的域名

    打开 chrom 的调试工具,打开 application ,点击 service workers 之后我们会发现 sw.js 脚本已经存到了 SW 中 。

    image

    我们打开 Network 刷新页面一下,看看,我们的页面资源来自 SW 而不是其他的地方,在 Console 中也打印出了我们在 index.html 中判断的语句,浏览器支持就会打印出这一句话。

    image

    接下来我们断网操作,在 Application 中给 Offline 打上对勾就行啦。然后刷新页面,我们仍然能看到之前的页面,原因就是我们在上图看到,他的资源是从 SW 上获得到的。当我们第一次打开这个页面的时候,Resopnse 对象被存到了 Cache Storage ( 定义在 SW 规范中 ,相关资料请同学们自行查询啦 )中,我们看下图:

    image

    通过存放到 Cache Storage 中,我们下次访问的时候如果是弱网或者断网的情况下,就可以不走网络请求,而直接就能将本地缓存的内容展示给用户,优化用户的弱网及断网体验。

    这个时候肯定会有同学在想,如果内容更新了,那么页面展示的内容是新内容呢还是旧内容呢?下面我们操作一下,打开 index.html 文件,我们在 body 中添加一个 p 标签 ,然后回到页面刷新。

    image

    image

    我们看到,页面上的内容并没有显示出我刚刚添加的那个 p 标签。这说明了,我们拿到的数据还是从 Cache Storage 中获取到的,Cache Storage中的内容并没有更新,强制刷新也不行哦,那么我们怎么才能让我刚刚添加的那个 p 标签显示出来呢。

    我们打开 sw.js 脚本文件,我们修改一下 cacheStorageKey。

    image

    修改后,我们再次打开该网址,强制刷新下或者关掉浏览器重新打开。

    页面中出现了刚刚添加的P标签,我们再看一下 Cache Storage 中的缓存名字,已经被修改。

    image

    总结

    如果是使用coding或者gitHub提供的pages服务,则需要注意最好绑定下独立域名。如果不绑定则注意下文件请求路径即可。

    研究PWA门槛不低,部署的服务器要求HTTPS,ServiceWorker涉及API众多,需要单独学习,另外npm中也已经有这个包了https://www.npmjs.com/package/web-pwa ,玩玩可以,真正部署到项目生产环境可能坑很多,但有坑填坑,不折腾还叫前端么。



    作者:小申同学
    链接:https://www.jianshu.com/p/fad8aa9e277f
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    展开全文
  • bentostarter全栈开源解决方案可快速构建PWA应用程序
  • PWA是指渐进式web应用,一般由web app manifest, service worker, app shell, notification push等部分组成。这里目前只讨论w...

    PWA是指渐进式web应用,一般由web app manifest, service worker, app shell, notification push等部分组成。

    这里目前只讨论web app manifest, service worker两部分如何应用到项目中。

    web app manifest可以使应用变成可安装式的。可以通过浏览器将应用添加到桌面上,从而可以从桌面上直接访问,同时可以定义桌面图标、应用名称、系统状态栏颜色,通过这些,我们可以让我们的应用像一个原生APP一样。从而给用户更好的体验。

    从产品的角度来看,用户从桌面图标访问我们的应用肯定比通过浏览器去访问便捷的更多,同时还可以让用户访问的时候隐藏浏览器本身的一些控件,比如导航栏、底部设置等控件。而实现这一切只需要很小的代价。这一切只需要添加一个manifest.json文件即可。

    ⚠️注意:在你开始跃跃欲试之前,请先确认你的应用是否全站https。如果不是,那么最好等你的应用全站https后再来尝试。

    Web App Manifest

    我们看下manifest.json文件是什么样的:

    Web App Manifest 文档[1]

    {
      "name": "前端收藏家",
      "short_name": "fedaily",
      "orientation": "portrait",
      "display": "standalone",
      "start_url": "/",
      "description": "只收藏好的,只推荐好的",
      "background_color": "#000",
      "theme_color": "#000",
      "icons": [
        {
          "src": "icon.png",
          "sizes": "96x96",
          "type": "image/png"
        },
        // ... 可以添加多种尺寸的图标
      ]
    }
    

    针对iOS平台,我们需要使用标签的形式添加:

    iOS application 官方文档[2]

    <link rel="apple-touch-icon" href="icon.png">
    <meta name="apple-mobile-web-app-title" content="前端收藏家">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="theme-color" content="#000000">
    

    然后在你的html中引入这个json文件即可。

    <link rel="manifest" href="/manifest.json">
    

    ⚠️注意,这里需要放在项目根目录下,否则会导致安卓不能自动弹出添加到桌面的提示(你可能会问,那iOS会有这个问题吗,没有,iOS根本就不支持这个特性)。

    当你做好这些,一个可以安装到桌面的应用就诞生了。

    你可以用Android的chrome浏览器访问你的应用,然后通过设置-添加到桌面功能,就可以将你的应用添加到桌面了。你可以用iOS的safari浏览器访问你的应用,然后通过底部的分享按钮-添加到主屏幕,就可以将你的应用添加到桌面了。

    Service Worker

    Service worker是一个注册在指定源和路径下的事件驱动worker。它采用JavaScript控制关联的页面或者网站,拦截并修改访问和资源请求,细粒度地缓存资源。你可以完全控制应用在特定情形(最常见的情形是网络不可用)下的表现。

    Service worker运行在worker上下文,因此它不能访问DOM。相对于驱动应用的主JavaScript线程,它运行在其他线程中,所以不会造成阻塞。它设计为完全异步,同步API(如XHR和localStorage)不能在service worker中使用。

    出于安全考量,Service workers只能由HTTPS承载,毕竟修改网络请求的能力暴露给中间人攻击会非常危险。在Firefox浏览器的用户隐私模式,Service Worker不可用。

    service worker具体的API以及详细介绍,大家可以在网上搜相关的资料,都说的很详细,这里介绍一个非常便捷的方法。

    workbox webpack plugin[3]可以和webpack集成,只需要很少的配置,就可以实现大部分我们需要的功能。

    我们看下如何使用:

    new GenerateSW({
      swDest: 'sw.js',
      skipWaiting: true,
      clientsClaim: true,
      cleanupOutdatedCaches: true,
      inlineWorkboxRuntime: true,
      runtimeCaching: [{
        handler: 'NetworkFirst',
        urlPattern: /\/api/,
        method: 'GET',
      }]
    })
    

    这个插件会读取webpack本身构建出来的静态资源文件,比如.js, .css, .png等资源,将其添加到缓存列表中,所以不需要在这里再指定了。

    通过runtimeCaching,我们可以缓存比如api的返回值,这里⚠️建议慎重考虑,如果你不是特别在意应用在断网情况下的体验(作为一个web应用,大多数情况下,断网基本啥都干不了,所以尽量不要缓存api数据,缓存静态资源即可,缓存策略不合适的话,可能会导致一些意想不到的BUG????)

    这个插件会根据你的配置自动生成service worker文件,是不是很简单,然后你需要做的就是去你的html里面注册servie worker就可以了。

    <script>
      if ('serviceWorker' in navigator) {
        window.addEventListener('load', () => {
          navigator.serviceWorker.register(`/sw.js?${Date.now()}`).then(registration => {
            console.log('SW registered: ', registration)
          }).catch(registrationError => {
            console.log('SW registration failed: ', registrationError)
          })
        })
      }
    </script>
    

    ⚠️注意:sw.js文件和manifest.json一样,也需要放在项目根目录下的。

    到这里,其实我们就有一个基本的可以使用的pwa化的应用了。

    如果你还需要一些定制化的需求可以详细阅读workbox文档去实现。

    开发中遇到的问题

    安卓的chrome没有弹添加到桌面的弹窗

    检查你的manifest.json, sw.js文件是否在项目根目录下。以及sw是否注册成功。

    安卓添加到桌面过程很慢

    暂时还没有找到好的解决方案

    如何判断是否从主屏幕访问

    因为埋点等需求,我们需要区分用户是从浏览器访问的还是从主屏幕访问的,可以这样判断:

    export const isFromDesktop = () => {
      // window.navigator.standalone used for safari
      if (window.navigator.standalone) {
        return true;
      }
      if (window.matchMedia && window.matchMedia('(display-mode: standalone)').matches) {
        return true;
      }
      return false;
    };
    

    如何监听添加到桌面事件

    let deferredPrompt
    window.addEventListener('beforeinstallprompt', event => {
      console.log('install event trigger', event);
      // 禁止浏览器自动显示添加到桌面提示框
      e.preventDefault();
      // 存储事件对象,方便后面自定义弹窗时机
      deferredPrompt = e;
    
      // 然后可以显示一个自定义的提示框给用户,告诉用户
      // 可以将应用添加到桌面,同时可以告知如何操作
    })
    
    // 再监听自定义提示框的按钮点击事件
    buttonInstall.addEventListener('click', (e) => {
      // 隐藏我们自定义的弹窗
      hideMyInstallPromotion();
      // 显示添加到桌面提示框(浏览器提供的)
      deferredPrompt.prompt();
      // 这里可以获取到用户的选择,同时做一些埋点相关操作
      deferredPrompt.userChoice.then((choiceResult) => {
        if (choiceResult.outcome === 'accepted') {
          console.log('用户接受');
        } else {
          console.log('用户拒绝');
        }
      })
    });
    

    添加到主屏幕失败

    安卓浏览器添加到主屏幕权限可能没打开,如果没打开,也不会有添加到主屏幕那个提示框的,需要开启权限再次尝试(所以一个自定义的提示框还是很重要的,可以告知用户如何处理失败的情况,经过测试,因为权限导致的失败并没有什么提示给到用户)

    如何捕捉安装成功动作

    window.addEventListener('appinstalled', (evt) => {
      console.log('app installed', evt);
    })
    

    如何注销sw

    // registrations 是注册成功回掉的参数
    for (let registration of registrations) {
      registration.unregister()
    }
    

    如何降级

    建议配置一个接口,根据接口决定是否执行sw注册的流程,否则将已有的sw注销掉。这样可以很方便的处理线上问题。比如:

    fetch('/api/sw/').then(result => {
      if (result) {
        // 注册操作
      } else {
        // 注销操作
      }
    })
    

    写到这里,好像实际开发过程中问题还是挺多的,不过综合来看,PWA还是非常值得尝试的。毕竟体验大不同呀。

    后面遇到其他问题再更新,也欢迎大家积极留言交流。。。

    本公众号全部博文已经整理成一个目录,请在公众号里回复[m]获取!

    推荐阅读
    中国程序员VS美国程序员,太形象了...

    提升效率,必须推荐这12款谷歌插件!

    有个程序员老公到底有多爽???

    如何破解“仅三天可见”的朋友圈?

    我司空降了一名专家后,一半程序员疯了...


    欢迎扫描加我微信一起交流基金理财知识,技术,项目管理
    当前有哪些投资机会?可转债打新,怎么参与?风险怎么样?怎么操作?欢迎加入免费知识星球
    同800+朋友们交流~
    
    
    
    
    
    如有收获,点个在看,诚挚感谢♡
    
    展开全文
  • 内窥镜 对于那些讨厌旋转摄像头的人 Noscope是由Opencv提供支持的桌面应用程序,具有将cr脚的rotoscopes转换为外观不错的遮罩的功能。
  • 具有NgRx商店,效果(HTTP + WebSockets),实体和NestJS的全栈Angular PWA应用 后端位于此处: : 演示: : 此应用程序使用管理应用程序状态,并使用来控制副作用(http + sockets),还使用NgRx分形状态管理...
  • 欢迎来到便当起动器 :waving_hand: :bento_box: bento-starter是开源的全栈解决方案,可帮助您使用Vue.js,Firebase,... 从Google Play商店安装PWA演示 :backhand_index_pointing_right: 灯塔得分: 可选的预先配置
  • 轻松通过简单的配置便可构建功能齐全的 PWA,为用户提供媲美原生 APP 体验的 Web 应用。随着移动用户的增加,在手机上优化用户体验变得至关重要。但目前大多 Web 应用体验依然不佳,脆弱的网络连接与注重实时的交互...

    Rax PWA,基于 Rax 1.x 的 PWA 解决方案。轻松通过简单的配置便可构建功能齐全的 PWA,为用户提供媲美原生 APP 体验的 Web 应用。

    随着移动用户的增加,在手机上优化用户体验变得至关重要。但目前大多 Web 应用体验依然不佳,脆弱的网络连接与注重实时的交互方式,制约了 Web 应用的发展。我们希望通过被称为下一代 Web 应用的 Progressive Web Apps(以下简称 PWA)来改善这一现状。PWA 不是一项具体的技术,它是应用了一系列技术进行使用体验优化后的 Web 应用,目标为具有与原生应用媲美的用户体验。

    我们为 Rax 1.x Web 工程提供了 Rax PWA 解决方案。与其他的 PWA 方案不同,除谷歌 PWA checklist 功能外,我们认为任何一个能够被整合成完整且轻配置的优化体验方案都可被看做是 Rax PWA 的内容。希望通过 Rax PWA 的努力,能够为开发者提供,提升用户体验同时提升开发效率的 PWA 方案,使开发者能够通过极简的配置开启 PWA 优化,增强 Web 应用的体验。

    PS:可通过 npm init rax 快速创建一个 Rax 1.x 应用。

    优化跳转

    在由多个页面组成的 Web 应用中,切换页面时会重新加载并刷新所有资源:

    a19e1b8ecc65c59c583da46d7dc21c38.png

    通过单页应用(Single Page Web Application,以下简称 SPA),使 Web 应用更具响应性和即时性,拥有更流畅的类 APP 体验:

    c07a40e01fb56e2396374e0ed2e0e6c6.gif

    Rax 1.x 工程内置统一的 SPA 方案,无需安装和维护 Router 组件,配置 app.json 即可生成路由和组件对应关系。

    对于移动端 SPA 加载性能是我们必须要考虑的问题,一起打包所有页面的资源必然会产生很大的 JS Bundle,在网络环境较差的情况下,容易阻塞资源加载加长等待时间,影响页面的可用性。

    我们在 Rax 1.x 工程中内置了基于页面组件的代码拆分及按需加载方案:打包时将页面代码分离到不同的 JS Bundle 中,可得到更小的 JS Bundle,极大影响加载时间。 当用户访问一个路由时,动态加载对应页面所需要的文件,动态提高 APP 的性能,控制资源大小同时保证使用体验。

    通过 SPA 方案赋予页面更好的交互体验,但在应用首次访问加载过程中,由于 SPA 渲染强依赖 JS 控制,JS 文件未完成加载时还可能存在白屏等待的情况,所以我们还需关注应用首次加载时的用户体验。

    消除白屏

    可通过 Rax PWA 提供的 App Shell 方案消除白屏等待。App Shell 是指支持页面展示的最小 HTML、CSS 和 JS 的资源集合,内容可为页面结构,页面片段,骨骼图等。它往往是纯 HTML 片段,一般只包括内联 CSS 和 base64 图片,不强依赖于 JS 框架。可以在加载、解析、执行 JS 之前就渲染出来,几乎消除了白屏时间,大大提高用户体验,确保提供即时、可靠的加载交互体验。

    在 Rax 1.x 项目 app.json 文件中增加 shell 配置,通过 source 配置的文件即可快速生成 App Shell。

    {
    "shell": {
    "source": "shell/index"}
    ,
    "hydrate": true}

    相比于谷歌提出的 App Shell 概念,Rax PWA 中的 App Shell 可使用 JSX 进行开发,它会被提前构建并将渲染结果插入 HTML 中,使其可快速加载到用户屏幕。在 JS 运行时,App Shell 会复用 HTML 中的节点绑定事件并激活组件。

    e8ab3096c9c62c7df8432778cc1d5aea.png

    如上图所示,应用正文部分在加载和 JS 控制渲染之前,展示的便是 App Shell 渲染出的 header 和 footer 部分。其中 {props.children} 即是页面的主体内容(App Shell 为应用最顶层组件)。

    App Shell 和其他组件一样,拥有生命周期、可使用 hooks API 、可引用外部依赖等等,可通过 App Shell 实现很多功能,比如:

    TabBar

    App Shell 的内容可为页面最外层通用可交互结构。比如 TabBar,将其注入 HTML 中,可方便用户快速切换页面进行页面预览:

    56d30fa61a5c2999eeff5748fb823503.png

    骨骼图

    如上图所示,中间的空白空分对于用户来说体验非常不好,所以在渲染出数据之前,还可以通过骨骼图在白屏位置占位。骨骼图需要在最短的时间内渲染给用户,期望浏览器在加载完 HTML 之后就能先显示骨架屏,所以在 App Shell 中还可以通过骨骼图提升用户体验。

    // /src/shell/index.jsx
    import { createElement, Fragment, useEffect, useState } from 'rax';

    function Shell(props) {
    const [showSkeleton, setShowSkeleton] = useState(true);
    useEffect(() => {
    setShowSkeleton(false);
    });
    return (
    <>

    {props.children}
    >
    );
    }

    export default Shell;

    效果如下:

    36ad21c34ca5f7efc306d81424ebd528.png

    最外层 App Shell 方案能缓解用户等待的焦虑,消除白屏影响,并进行简单的交互。但当用户网速较差,页面仍迟迟不能完成加载时,我们还可以帮助用户更快渲染出页面内容。

    首屏瞬开

    如下图所示,加载或刷新页面,页面内容瞬间渲染,我们将这种体验称为首屏瞬开

    02c5eb9a4fdb9b81eae8aa1365096920.gif

    我们为 Rax 1.x 工程提供了 rax-plugin-pwa 插件,通过此插件可选择开启对应的 PWA 功能点,通过 快照 缓存控制 功能可快速展示页面。

    PS:可通过 https://rax.js.org/docs/guide/about-rax-scripts ,了解 Rax 1.x 工程插件。

    快照

    用户所处环境网速较差导致 JS 文件加载慢时,白屏时间增长会造成不好的体验。如果在内容变化不大的 Web 应用中可将页面内容填充为用户上一次访问时对应的内容,极速展示页面内容,提升首屏加载速度。

    页面会记录当前页面内容称之为快照,下次访问相同页面时,快速将快照填充渲染至当前空白页面,待 JS 加载完成后再进行状态和事件绑定,完成页面渲染。

    在 build.json 中配置 rax-plugin-pwa 即可开启快照功能:

    {
    "plugins": [
    ["rax-plugin-pwa", { "snapshot": true }]
    ]
    }

    缓存控制

    在 Web 应用中我们可以通过 Service Worker (以下简称 SW) 控制页面缓存,它是 PWA 中最重要的概念之一。它独立于浏览器的主线程运行,不仅可以拦截用户的网络请求,还可以操作缓存,支持 Push 和后台同步等功能。相比使用重型封装框架 Workbox ,我们希望提供给用户更简单轻量透明并且易学习的解决方案。

    在 build.json 中配置 rax-plugin-pwa 设置开启 SW 控制缓存:

    {
    "plugins": [
    [ "rax-plugin-pwa", {
    "serviceWorker": {
    "preCacheUrlList": ["https://img.alicdn.com/tfs/rax.png"], // 预缓存 url 列表
    "savedCachePatternList": ["/my-app\/.+/i"], // 加入缓存的 URL 正则字符串列表
    }
    }
    ]
    ]
    }

    快速配置预缓存和缓存的 URL 正则字符串列表可快速开启 SW ,同时支持离线访问应用。

    我们使用了缓存优先的控制方案,优先从缓存中读取结果,若缓存中不存在结果,则进行网络请求,网络请求成功后,再将结果写入缓存。保证请求可用同时,加速资源获取。

    275d14e58872715229ae111fd5478bcf.png

    优化效果

    对比标准 Rax 1.x 工程和开启快照和 SW 后的页面,加载时间和 Chrome 开发者工具中的 First Contentful Paint 时间都有了大幅度提升:

    方案网络环境FCP时间Load时间
    标准工程Chrome - Slow 3G15558.7 ms15474.7 ms
    开启快照Chrome - Slow 3G2032.5 ms(87%)16317.9 ms
    开启 SWChrome - Slow 3G3096.2 ms(80%)5147.8 ms(66%)

    影响页面交互体验还有非常重要的一个环节-数据获取,数据的加载体验会直接影响页面的使用体验,在完成了首屏加速后,当然我们也准备了数据加速获取方案。

    加速数据请求

    可通过服务端渲染(Server-Side Rendering,以下简称 SSR),加速首屏渲染和数据请求。

    SSR 是指将页面渲染逻辑前置到服务器端执行,由服务器端直接返回渲染好的页面,然后再由浏览器端进行状态和事件绑定,来达到页面的可交互状态。服务端控制数据请求可彻底摆脱弱网环境,将数据请求网络延迟减少到了最小程度。

    SSR 拥有包含数据层面更快的首屏加载速度。使用客户端渲染时,完成首屏渲染一般包括以下步骤:解析 HTML -> 加载 JS -> 获取数据 -> 渲染。设备的运行状态或网络情况,将直接影响到每一个环节的执行时间,最终成倍地影响首屏的呈现时间。而服务端请求数据脱离了弱网环境渲染,将这种数据加载网络延迟减少到了最小程度。

    SSR 还可以解决页面 SEO 问题,由于其页面内容是相对完整的,所以可以更好地被搜索引擎所理解。对于一些有 SEO 需求的业务,SSR 显得尤为重要。

    我们还为 Rax 1.x 工程提供了 rax-plugin-ssr 插件,可以快速开始一个 SSR 应用。在 build.json 配置即可开启 SSR 功能。

    {
    "plugins": [
    [ "rax-plugin-ssr" ]
    ]
    }

    作为 PWA 工程,我们还可以使用户更快速启动应用。

    快速启动应用

    无需打开浏览器并输入 URL 地址访问 Web 应用,通过点击保存至桌面的 PWA,用户可快速定位并启动应用。不仅支持全屏预览应用,还能定制 PWA 的启动画面的图标和颜色等,增强 Web 应用与操作系统的集成能力,提供更好的类 Native 体验。

    通过配置 manifest 可快速生成 Web App Manifest(支持应用在手机主屏上创建图标的技术方案):

    {
    "plugins": [
    [ "rax-plugin-pwa", {
    "manifest": {
    "name": "My Progressive Web App",
    "short_name": "MyPWA",
    "description": "My awesome Progressive Web App!",
    "background_color": "#ffffff",
    "icon": "src/public/icon.png",
    "start_url": "//market.m.taobao.com/app/mtb/rax-pwa-demo/web/index.html#/",
    "display": "standalone"}
    }
    ]
    ]
    }

    应用构建时会将应用图标文件 - icon 自动切割为96x96、128x128、180x180、256x256、512x512 五种尺寸的正方形 Icon 图以满足不同屏幕尺寸的需求,达到高保真的效果,同时兼容不同平台按照浏览器标准生成 Web App Manifest 。

    用户在访问开启 manifest 的 Web 应用后,便可选择将其添加到桌面。

    持续关注移动 Web 体验

    Rax PWA 解决方案充斥着 PRPL (Push/Preload、Render、Precache、Lazy-Load)开发模式。当前 Rax PWA 仍处在进行时,我们将继续探索 PWA 的更多可能性,不断在技术、业务上提升产品体验。

    当前我们也在积极筹备优化开发者的开发体验、提供能有更好交互体验和高性能的组件体系、不同容器中的 Web 应用体验并打通更多链路(比如在手淘中的 Web 页面加速)等等,任何可以切实优化或改进移动 Web 体验的方案我们都将付诸行动,为用户带来更好的移动体验。

    当然我们也将在今年双十一中使用 Rax PWA 方案优化端外页面性能体验。让我们一起努力,再一次带来让用户惊叹的 Web 应用体验吧~

    详细使用请见:https://rax.js.org/pwa

    展开全文
  • PWP应用用于天文天图片 网站和APP 信息 科技类 最佳实践 推荐工具 产品特点 今日图片首页 分页6天和6天,然后选择特定页面 可视化一天可视化图像和视频 日历在日历上选择特定的日期 关于关于项目的页面 下一张...
  • PWA(Progressive Web App)利用TLS,webapp manifests和service workers使应用程序能够安装并离线使用。 换句话说,PWA就像手机上的原生应用程序,但它是使用诸如HTML5,JavaScript和CSS3之类的网络技术构建的。 ...
  • 快速了解理解pwa

    千次阅读 2017-10-11 16:18:46
    什么是PWA先说一下全名,progressive web app: 渐进式网页应用。这是谷歌推出的,我是这样理解的: 我们一般写web应用,在 pc 上是没有缓存的,打开页面的时去请求数据。 第二个也没有像 app 一样的小图标放在桌面...
  • Angular 11示例PWA 具有和的Angular入门工具包 它是旨在使用Angular创建渐进式Web应用的回购系列的一部分 Web应用程序实时演示 快速开始 # choose a repo # download the example or clone the repo from github ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 385
精华内容 154
关键字:

pwa快应用