PWA(Progressive Web App)入门系列:安装 Web 应用

前言

在传统的 Web 应用中,通常只能通过在浏览器的地址栏里输入相应的网址才能进行访问,或者把网页地址创建到桌面上通过点击,然后在浏览器里打开。

传统模式下,图标、启动画面、主题色、视图模式、屏幕方向等等都无法去自定义和控制。

而目前可以通过 PWA 标准中的特性来完成上面这些功能,使得访问 Web 应用的路径更短、曝光性更大,下面说一下这一块。


安装

安装 Web 应用需要一些前期准备。

安装条件

首先需要在网站下建立 manifest.json 文件,并在页面中引入:

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

manifest.json 文件中必须配置如下字段:

{"short_name": "短应用名","name": "长应用名","icons": [{"src": "icons/192.png","sizes": "144x144","type": "image/png"}],"start_url": ".","display": "standalone",
}

要求:

  • 运行在 https 环境。
  • 必须注册并运行 serviceworker。
  • manifest 中必须有 icons,且至少为 144x144PNG 图像。
  • manifest 中 display 设置为 standalone 或者 fullscreen
  • manifest 中必须有 name 或者 short_name
  • manifest 中必须有 start_url
  • manifest 中 prefer_related_applications 未设置或设置为 false

manifest 的详细设置信息,可以参考前面写的 manifest 专题文章。

显示安装提示

按要求配置好后,在浏览器端打开网站。

Android Chrome 端

从 Chrome 68 以后,当满足安装应用的条件时,会立即在浏览器底部弹出 “Mini信息条”,用户单击信息条时,弹出“添加到主屏幕”的对话框,点击“添加”后,完成安装,此时页面上就出现在应用图标。

注意:Chrome 68 - 75 的Mini 信息条是无法通过代码来控制是否展示的,Chrome 76 之后版本支持通过代码控制显示。
当用户点击 Mini 信息条上的 “X” 时,至少三个月浏览器不会再出现 Mini 条的提示,但事件层不受影响,可以通过代码实现。

PC Chrome 端

Chrome 73 开始支持 PC 端安装 Web 到桌面

自定义安装时机

当 Web 应用符合安装时,会触发 beforeinstallprompt 事件,并弹出安装到屏幕的提示,我们可以基于这个事件来控制是否展示安装提示及何时安装。

beforeinstallprompt 事件在此应用未安装的情况下会每次进入页面都触发,如果已安装则不会触发。当用户卸载应用后,则会继续触发此事件。

安装提示事件捕获逻辑:

var installPromptEvent = null;window.addEventListener('beforeinstallprompt', (event) => {event.preventDefault();  // Chrome <= 67 可以阻止显示installPromptEvent = event; // 拿到事件的引用document.querySelector('#btn-install').disabled = false; // 更新安装 UI,通知用户可以安装
});

显示 prompt 对话框

手动显示安装对话框,可以通过调用捕获的 beforeinstallprompt 事件引用中的prompt() 方法来触发。

通过事件 userChoice 属性的 Promise 结果中的 outcome 来获取。

用户点击安装逻辑:

document.querySelector('#btn-install').addEventListener('click', () => {if( !installPromptEvent ) {return;}installPromptEvent.prompt();installPromptEvent.userChoice.then( choiceResult => {if (choiceResult.outcome === 'accepted') {console.log('用户已同意添加到桌面')} else {console.log('用户已取消添加到桌面')}})
})

已安装事件处理

可以通过 appinstalled 来监听应用是否安装:

window.addEventListener('appinstalled', (evt) => {console.log('已安装到桌面屏幕');
});

环境判断

当前应用是通过在浏览器里输入网址打开的,还是通过桌面图标打开的,可以通过 display-mode 属性来判断,然后根据需求设置不同的交互样式。

假设 manifest 中设置的 displaystandalone

js 层判断:

if (window.matchMedia('(display-mode: standalone)').matches) {console.log('display-mode 是 standalone');
}

css 层判断:

@media all and (display-mode: standalone) {/** 自定义样式 **/
}

Safari 判断:

if (window.navigator.standalone === true) {console.log('display-mode 是 standalone');
}

应用的更新

Web 应用安装到桌面后,对于后面修改 manifest 后的更新问题,目前每个平台的表现不一样。

Android 端

在 Android 上,当启动 Web 应用时,Chrome 会根据实时 manifest 来检查当前安装的 manifest。如果需要更新,则在 wifi 环境下自动进入更新队列。

触发更新规则:

  • 更新检查仅在启动 Web 应用时发生。直接启动 Chrome 不会触发给定 Web 应用的更新检查。
  • Chrome 会每隔 1 天或每 30 天检查一次更新。每天检查更新大多数时间都会发生。在更新服务器无法提供更新的情况下,它会切换到30天的时间间隔。
  • 清除 Chrome 的数据(通过Android设置中的“清除所有数据”)会重置更新计时器。
  • 如果 Web Manifest URL 未更改,Chrome 将仅更新 Web 应用。如果你将网页的 manifest 路径修改,如从 /manifest.json 更改为 /manifest2.json,则 Web 应用将不再更新。(非常不建议这样做)
  • 只有正式版 Chrome(Stable / Beta / Dev / Canary)创建的 Web 应用才会更新。它不适用于 Chromium(org.chromium.chrome)。
  • 更新检查可能会延迟,知道连接可用 wifi。

PC 端

PC 端暂时不支持更新,后续可能会支持。


兼容

目前此特性在各平台的兼容性如下:


像 IOS 下的 Safari 是支持安装到桌面的特性,但并没有走 manifest 的规范。

IOS 上的适配

IOS 针对桌面图标、启动画面、应用文本及主题色需要单独的特性 Meta 进行设置。

apple-touch-icon:应用图标

需要在网页中增加:

<link rel="apple-touch-icon" href="/custom_icon.png">

不同分辨率的适配:

<link rel="apple-touch-icon" href="touch-icon-iphone.png">
<link rel="apple-touch-icon" sizes="152x152" href="touch-icon-ipad.png">
<link rel="apple-touch-icon" sizes="180x180" href="touch-icon-iphone-retina.png">
<link rel="apple-touch-icon" sizes="167x167" href="touch-icon-ipad-retina.png">

apple-touch-startup-image:启动画面

需要在网页中增加:

<link rel="apple-touch-startup-image" href="/launch.png">

apple-mobile-web-app-title:应用 icon 的标题

默认情况下使用 <title></title> 中的值,需要修改的话需要指定 meta。

<meta name="apple-mobile-web-app-title" content="应用标题">

apple-mobile-web-app-status-bar-style:应用状态栏的外观样式

例如设置为黑色:

<meta name="apple-mobile-web-app-status-bar-style" content="black">

兼容适配库

正常来说,所有的特性都要按照规范中的约束来使用,但向上面的 Safari 并没有按照规范来,这样会增加开发者的开发成本。

所以这里做一下适配脚本,只写规范中 manifest 的那些定义部分,剩下的交由脚本来完成。

(function(){function h(){var a=document.head.querySelector('link[rel="manifest"]'),b=a?a.href:"",d=A([b,window.location]);Promise.resolve().then(function(){if(!b)throw'can\'t find <link rel="manifest" href=".." />\'';var a={};"use-credentials"===b.crossOrigin&&(a.credentials="include");return window.fetch(b,a)}).then(function(a){return a.json()}).then(function(a){return B(a,d)}).catch(function(a){return console.warn("pwacompat.js error",a)})}function A(a){for(var b={},d=0;d<a.length;b={c:b.c},++d){b.c=a[d];try{return new URL("",b.c),function(a){return function(b){return(new URL(b,a.c)).toString()}}(b)}catch(n){}}return function(a){return a}}function t(a,b){a=document.createElement(a);for(var d in b)a.setAttribute(d,b[d]);document.head.appendChild(a);return a}function c(a,b){b&&(!0===b&&(b="yes"),t("meta",{name:a,content:b}))}function B(a,b){function d(b,d,f){var k=b.width,c=b.height,e=window.devicePixelRatio;b=u({width:k*e,height:c*e});b.scale(e,e);b.fillStyle=a.background_color||"#f8f9fa";b.fillRect(0,0,k,c);b.translate(k/2,(c-32)/2);b.font="24px HelveticaNeue-CondensedBold";b.fillStyle=r?"white":"black";k=b.measureText(v).width;f&&(c=f.width/e,e=f.height/e,128<e&&(c/=e/128,e=128),48<=c&&48<=e&&(b.drawImage(f,c/-2,e/-2,c,e),b.translate(0,e/2+32)));b.fillText(v,k/-2,0);f=document.createElement("link");f.setAttribute("rel","apple-touch-startup-image");f.setAttribute("media","(orientation: "+d+")");f.setAttribute("href",b.canvas.toDataURL());return f}function n(a){var b=d(window.screen,"portrait",a);a=d({width:window.screen.height,height:window.screen.width},"landscape",a);w.forEach(function(a){return a.remove()});document.head.appendChild(b);document.head.appendChild(a);w.add(b);w.add(a)}var g=a.icons||[];g.sort(function(a,b){return parseInt(b.sizes,10)-parseInt(a.sizes,10)});var x=g.map(function(a){a={rel:"icon",href:b(a.src),sizes:a.sizes};t("link",a);if(p)return a.rel="apple-touch-icon",t("link",a)}),q=a.display;g=-1!==C.indexOf(q);c("mobile-web-app-capable",g);D(a.theme_color||"black");E&&(c("msapplication-starturl",a.start_url||"/"),c("msapplication-TileColor",a.theme_color));document.head.querySelector('[name="theme-color"]')||c("theme-color",a.theme_color);var h=F(a.orientation);c("x5-orientation",h);c("screen-orientation",h);"fullscreen"===q?(c("x5-fullscreen","true"),c("full-screen","yes")):g&&(c("x5-page-mode","app"),c("browsermode","application"));if(p){var r=y(a.background_color||"#f8f9fa"),v=a.name||a.short_name||document.title;(q=G(a.related_applications))&&c("apple-itunes-app","app-id="+q);c("apple-mobile-web-app-capable",g);c("apple-mobile-web-app-title",v);var w=new Set;n(null);if(x.length){var m=x[0],l=new Image;l.crossOrigin="anonymous";l.onload=function(){n(l);if(a.background_color){var b=z(l,a.background_color);null!==b&&(m.href=b,x.slice(1).forEach(function(b){var d=new Image;d.crossOrigin="anonymous";d.onload=function(){var c=z(d,a.background_color,!0);b.href=c};d.src=b.href}))}};l.src=m.href}}}function G(a){var b;(a||[]).filter(function(a){return"itunes"===a.platform}).forEach(function(a){a.id?b=a.id:(a=a.url.match(/id(\d+)/))&&(b=a[1])});return b}function F(a){a=String(a||"");a=a.substr(0,3);return"por"===a?"portrait":"lan"===a?"landscape":""}function D(a){if(p||H){var b=y(a);if(p)c("apple-mobile-web-app-status-bar-style",b?"black":"default");else{try{var d=Windows.UI.ViewManagement.ApplicationView.getForCurrentView().titleBar}catch(n){d=null}null===d?console.debug("UWP no titleBar"):(d.foregroundColor=r(b?"black":"white"),d.backgroundColor=r(a))}}}function r(a){a=m(a);return{r:a[0],g:a[1],b:a[2],a:a[3]}}function m(a){var b=u();b.fillStyle=a;b.fillRect(0,0,1,1);return b.getImageData(0,0,1,1).data}function y(a){a=m(a).map(function(a){a/=255;return.03928>a?a/12.92:Math.pow((a+.055)/1.055,2.4)});return 3<Math.abs(1.05/(.2126*a[0]+.7152*a[1]+.0722*a[2]+.05))}function z(a,b,d){d=void 0===d?!1:d;var c=u(a);c.drawImage(a,0,0);if(!d&&255==c.getImageData(0,0,1,1).data[3])return null;c.globalCompositeOperation="destination-over";c.fillStyle=b;c.fillRect(0,0,a.width,a.height);return c.canvas.toDataURL()}function u(a){a=void 0===a?{width:1,height:1}:a;var b=a.height,c=document.createElement("canvas");c.width=a.width;c.height=b;return c.getContext("2d")}if("fetch"in window){var C=["standalone","fullscreen","minimal-ui"],p=navigator.vendor&&-1!==navigator.vendor.indexOf("Apple"),E=navigator.userAgent&&-1!==navigator.userAgent.indexOf("Edge"),H="undefined"!==typeof Windows;"complete"===document.readyState?h():window.addEventListener("load",h)}})();

调用地址:http://unpkg.alipay.com/pwacompat@2.0.9/pwacompat.min.js

使用:

<link rel="manifest" href="./manifest.json" />
<script src="http://unpkg.alipay.com/pwacompat@2.0.9/pwacompat.min.js" crossorigin="anonymous"></script>

博客名称:王乐平博客

CSDN博客地址:http://blog.csdn.net/lecepin

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/401620.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

「工具」IndexDB 版备忘录

前言 工作日常需要做一些备忘录&#xff0c;记录一些要做的事。在 Mac 上有使用系统的备忘录&#xff0c;但功能偏弱且文本格式调整不方便。再就是使用浏览器找专门的备忘录网站&#xff0c;功能是满足了&#xff0c;但是链路长&#xff0c;没有桌面软件直接。 所以最后干脆自…

「工具」PWA Manifest图标及 favicon.ico 生成工具

PWA 其中有一个能力就是把网站安装到系统桌面&#xff0c;以原生应用的体验来运行网站&#xff0c;使用户无需再找开浏览器输入网址进入网站&#xff0c;而是可以直接点击安装好的应用直接运行&#xff0c;给使网站访问缩短路径及增加网站的曝光度。 其中有一个问题就是需要生…

各种浏览器缓存浅析

前言 目前浏览器的缓存类型众多&#xff0c;HTTP Cache、Disk Cache、Memory Cache、ServiceWorker Cache、Push Cache 等等&#xff0c;这些缓存是如何产生的&#xff1f;命中优先级是怎么样&#xff1f;又该如何去使用它们&#xff1f; Disk Cache、Memory Cache Disk Cac…

[工具]TS 视频合并工具

简介 当下载 m3u8 资源时&#xff0c;通常产生的是多个 ts 视频文件&#xff0c;所以需要借助某些工具来将这些 ts 视频片段整合为一个视频文件。 本软件主要解决的就是这个问题&#xff0c;底层基于ffmpeg&#xff0c;可正常运行在 Windows 和 Mac 平台。不仅可以合并 ts 为单…

[会议分享]2020全球软件大会分享-PWA在项目中的最佳实践

大会地址&#xff1a;https://www.bagevent.com/event/1233659# PPT下载&#xff1a;https://download.csdn.net/download/lecepin/12871373

「浏览器插件」非常好用的JSON-View

Chrome 商店&#xff1a;地址 下载地址&#xff1a;地址 Github&#xff1a;https://github.com/lecepin/lp-json-view 查看/格式化 二合一。 功能 自动识别 JSON 内容&#xff0c;并在页面右下角创建切换按钮。支持展开/折叠节点。支持全部展开、全部折叠、展开一二三层节点…

Github Action 快速构建 Electron 应用

前言 在开发 Electron 应用时&#xff0c;比较耗时的部分应该是构建打包的过程&#xff0c;像用 electron-builder 这种打包工具来说&#xff0c;它会根据你要打包的系统来下载应用的系统镜像打包工具&#xff0c;由于这些镜像的源文件托管在 Github 上&#xff0c;且 nodejs …

「浏览器插件」网址小尾巴终结者

前言 在我们日常的开发调试中&#xff0c;会在 URL 上添加一些特殊的小尾巴 用来显示调试界面或者开启一些特殊功能&#xff0c;当你接触了越来越多的系统后&#xff0c;你需要使用的小尾巴就变得越来越多&#xff0c;记忆和使用成本非常大&#xff0c;以及含有小尾巴的网址 在…

什么是低代码?

低代码 是一种软件开发方法&#xff0c;可以减少手工编码的过程&#xff0c;尽可能快的交付应用程序。 低代码平台 是工具的合集&#xff0c;这些工具可以通过建模和图形界面来进行应用程序的可视化开发。低代码使开发人员可以跳过手工编码&#xff0c;从而加快了应用程序的开…

什么是 LOW-CODE ?

低代码平台的特征 可视化建模工具 使用可视化方法和模型创建应用程序比使用代码进行开发要快。具有可视化建模功能的低代码平台&#xff0c;使用内置的组件&#xff0c;以任何人都可读的形式表示任何信息&#xff0c;从没有技术技能的常规企业用户到专业开发人员。 开箱即用…

简简单单 上传下载

背景 我们经常会有手机向电脑传文件 或者 电脑像手机传文件的需求。 而通常的解决方案是&#xff1a;手机上安装一个聊天软件&#xff08;如微信&#xff09;&#xff0c;电脑上安装一个聊天软件&#xff0c;然后自己给自己传输&#xff0c;然后进行下载。 这种方式是很麻烦的…

「VSCode插件」提效工具 - 快捷面板

前言 做为一个开发人员&#xff0c;在日常的开发过程中&#xff0c;经常会在 Terminal 中输入各种命令&#xff0c;如&#xff1a;npm i、npm start、git init、rm -rf、node_modules 等命令&#xff0c;看似方便&#xff0c;实则高频率的输入很烦人。那有什么方法可以把这些高…

VSCode摸鱼插件 — FreeWindow

背景 在一些不是很忙的时候&#xff0c;想高效利用下时间&#xff0c;看看书丰富一下自己&#xff0c;但是大庭广众下长时间看一本实体书&#xff0c;或者看手机的电子书&#xff0c;或者在电脑上看网页书都不太合适&#xff0c;显得自己很闲的样子&#xff0c;那该如何看起来…

在线生成文本图片 CFC函数计算版

百度云函数计算 CFC 运行环境。 使用 sharp 图处理&#xff08;文档&#xff09;。 使用 图片参数&#xff1a; widthheightrgba 文本参数&#xff1a; textfColorfSizefTopfLeft {HTTP触发器地址}?width1000&height300&fSize120&fColor%23d9333f&text奥利…

调试利器:浏览器 Logger

1. 前言 在一些业务系统中&#xff0c;由于集成的平台产物或工具较多&#xff0c;而这些产物的 log 不收敛&#xff0c;很多时候打开控制台就是满屏的 log&#xff0c;自己的 log 需要在满屏的 log 中查找&#xff0c;或者在 log 上加一些前缀用 Filter 去过滤&#xff0c;严重…

主动型页面性能利器:Page Status

1. 背景 当页面出现性能问题&#xff0c;如加载慢、页面卡顿等现象时&#xff0c;大多是用户主观上的感受。而要真正客观的去评测性能和定位问题原因&#xff0c;通常需要专业的前端同学通过 DevTools 中的 Performance 等工具来查看&#xff08;如图 1 所示&#xff09;&…

前端状态机:XState 首个中文文档上线了

XState 做为一个非常好用的前端状态机库&#xff0c;但官网文档却只有英文版&#xff0c;为了阅读体验&#xff0c;我这里翻译了中文版。 仓库地址&#xff1a;https://github.com/lecepin/xstate-docs-cn文档地址&#xff1a;https://lecepin.github.io/xstate-docs-cn/zh 由…

降低前端业务复杂度新视角:状态机范式

无论做业务需求还是做平台需求的同学&#xff0c;随着需求的不断迭代&#xff0c;通常都会出现逻辑复杂、状态混乱的现象&#xff0c;维护和新增功能的成本也变的十分巨大&#xff0c;苦不堪言。下图用需求、业务代码、测试代码做对比&#xff1a; 图中分了 3 个阶段&#xff1…

Mac 摸鱼神器

这是一个 Mac 系统的摸鱼应用&#xff0c;仿真了大多数的 Mac 系统黑屏故障。开启摸鱼功能后&#xff0c;可以给自己一段休息的时间~ 软件使用 Electron 开发&#xff0c;源码&#xff08;欢迎 Star ⭐ &#xff09;&#xff1a;https://github.com/lecepin/mac-fish 1. 主界…

前端状态机系列:SCXML与XState对应关系

1. 前置说明 这次再说明下自己对状态图的看法。状态图虽然有非常多的优势&#xff08;参考上篇文章&#xff09;&#xff0c;如果你想使用&#xff0c;关于是否对整个旧项目进行全量状态图化&#xff0c;这里给一个适应范围是&#xff1a;项目中复杂的部分进行状态图建模是非常…