前言
前面说过,让Web App能够达到Native App外观体验的主要实现技术就是PWA中的manifest技术,本章会详细说明manifest的实现,及各个参数的具体含义,还将了解如何定义Web App的启动图标、启动样式等。
简介
manifest是一种简单的json数据风格的配置文件,通过对其相应的属性进行配置,才实现相应的功能,这里可以称manifest为WEB应用清单。WEB应用清单可以实现自定义启动画面、打开URL、设置界面颜色、设置桌面图标等等。
大概就是下面这样:
{"short_name": "短名称","name": "这是一个完整名称","icons": [{"src": "144x144.png","type": "image/png","sizes": "144x144"}],"background_color": "#2196f3","display": "standalone","start_url": "index.html"
}
部署到浏览器
好么manifest.js如何让浏览器去执行呢?
只需要用link
标记引用即可:
<link rel="manifest" href="manifest.js">
目前各大浏览器对manifest的支持程度:
成员
下面对manifest涉及到的各个属性详细说一下。
name
name: {string}
,用来描述应用的名称,会显示在各类提示的标题位置和启动画面中。
short_name
short_name: {string}
,用来描述应用的短名字。当应用的名字过长,在桌面图标上无法全部显示时,会用short_name
中定义的来显示。
start_url
start_url: {string}
,用来描述当用户从设备的主屏幕点击图标进入时,出现的第一个画面。
- 如果设置为空字符串,则会以manifest.js的地址做为URL
- 如果设置的URL打开失败,则和正常显示的网页打开错误的样式一下(可以通过后面讲的ServiceWorker改善)
- 如果设置的URL与当前的项目不在一个域下,也不能正常显示
start_url
必须在scope的作用域范围内- 如果
start_url
是相对地址,那么根路径基于manifest
的路径 - 如果
start_url
为绝对地址,则该地址将永远以/
作为根路径
scope
scope : {string}
,用来设置manifest
对于网站的作用范围。
下面列一下,scope
的作用范围及对start_url
的影响:
manifest的文件位置 | start_url | scope配置 | 计算好的scope | 计算好的start_url | 是否有效 |
---|---|---|---|---|---|
/inner/manifest.json | ./index.html | undefined | /inner/ | /index.html | 有效 |
/inner/manifest.json | ./index.html | ../ | / | /index.html | 有效 - 但作用域泄露到了更高层级 |
/inner/manifest.json | / | / | / | /index.html | 有效 - 但作用域泄露到了更高层级 |
/inner/manifest.json | / | undefined | /inner/ | / | 无效 - start url不在作用域范围内 |
/inner/manifest.json | ./inner/index.html | undefined | /inner/ | /inner/inner/index.html | 有效 - 但start url明显不符合预期 |
/manifest.json | ./inner/index.html | undefined | / | /inner/index.html | 有效 - 广作用域 |
/manifest.json | ./inner/index.html | inner | /inner/ | /inner/index.html | 有效 - 窄作用域 |
icons
icons: {Array.<ImageObject>}
,用来设置Web App的图标集合。
ImageObject
包含属性:
src: {string}
,图标的地址type {string}
,图标的 mime 类型,可以不填写。这个字段会让浏览器不使用定义类型外的图标sizes {string}
,图标的大小,用来表示width
xheight
,单位为px,如果图标要适配多个尺寸,则第个尺寸间用空格分割,如12x12 24x24 100x100
。
sizes适配规则:
- 在PWA添加到桌面的时候,浏览器会适配最合适尺寸的图标。浏览器首先会去找与显示密度相匹配且尺寸调整到 48dp 屏幕密度的图标,例如它会在 2 倍像素的设备上使用 96px,在 3 倍像素的设备上使用 144px。。
- 如果没有找到任何符合的图标,则会查找与设备特性匹配度最高的图标。
- 如果匹配到的图标路径错误,将会显示浏览器默认 icon。
需要注意的是,图标中必须要有一张尺寸为144x144
的,图标的 mime 类型为 image/png
的。
background_color
background_color: {Color}
,值为CSS的颜色值,用来设置Web App启动画面的背景颜色。
可以像正常写CSS颜色那样定义:
// 完整色值
"background_color": "#0000ff"
// 缩写
"background_color": "#00f"
// 预设色值
"background_color": "yellow"
// rgb
"background_color": "rgb(0, 255, 255)"
// transparent 背景色显示为黑色
"background_color": "transparent"
其他的定义rgba
、hsl
、hsla
等颜色定义方式浏览器不支持,未设置时,背景色均显示白色。
theme_color
theme_color: {Color}
,定义和background_color
一样的CSS颜色值,用于显示Web App的主题色,显示在banner位置。
display
display: {string}
,用来指定 Web App 从主屏幕点击启动后的显示类型
显示类型 | 描述 | 降级显示类型 |
---|---|---|
fullscreen | 应用的显示界面将占满整个屏幕 | standalone |
standalone | 浏览器相关UI(如导航栏、工具栏等)将会被隐藏 | minimal-ui |
minimal-ui | 显示形式与standalone类似,浏览器相关UI会最小化为一个按钮,不同浏览器在实现上略有不同 | browser |
browser | 浏览器模式,与普通网页在浏览器中打开的显示一致 | (None) |
对于不同的显示样式,可以通过CSS的媒体查询进行设置:
@media all and (display-mode: fullscreen) {div {padding: 0;}
}@media all and (display-mode: standalone) {div {padding: 1px;}
}@media all and (display-mode: minimal-ui) {div {padding: 2px;}
}@media all and (display-mode: browser) {div {padding: 3px;}
}
orientation
orientation: {string}
,Web App的在屏幕上的显示方向。
landscape-primary
,当视窗宽度大于高度时,当前应用处于“横屏”状态landscape-secondary
,landscape-primary
的180°方向landscape
,根据屏幕的方向,自动横屏幕180°切换portrait-primary
,当视窗宽度小于高度时,当前应用处于“竖屏”状态portrait-secondary
,portrait-primary
的180°方向portrait
,根据屏幕方向,自动竖屏180°切换natural
, 根据不同平台的规则,显示为当前平台的0°方向any
,任意方向切换
dir
dir: {string}
,设置文字的显示方向。
- ltr
,文本显示方向,左到右
- rtl
,文本显示方向,右到左
- auto
,根据系统的方向显示
related_applications
related_applications: {Array.<AppInfo>}
,用于定义对应的原生应用,类似应用安装横幅的形式去推广、引流。
AppInfo
结构:
- platform: {string}
, 应用平台
- id: {string}
应用id
如安卓可以这么定义:
"related_applications": [{"platform": "play","id": "com.app.xxx"}
]
prefer_related_applications
prefer_related_applications:{Boolean}
,用于设置只允许用户安装原生应用。
实例
下面写一下相关的常用实例。
目录结构
项目结构:
根路径 /||----manifest.json // 清单文件||----index.html||----144x144.png // 图标文件||----sw.js
因为浏览器要安装manifest中的定义,需要一些其他的代码环境条件,以上目录中,我们只讨论manifest.json
文件,其他文件后面会做说明。
index.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Manifest</title><link rel="manifest" href="./manifest.json"> <!-- 引用manifest文件 -->
</head>
<body><h1>Manifest Page</h1><script>// 此处代码 后面相关章节会去说明if ('serviceWorker' in navigator) {window.addEventListener('load', function() {navigator.serviceWorker.register('sw.js').then(function(registration) {}).catch(function(err) {})})}</script>
</body>
</html>
sw.js
// 此处代码 后面相关章节会去说明
var cacheName = 'helloWorld'self.addEventListener('install', event => {event.waitUntil(caches.open(cacheName).then(cache => cache.addAll(['index.html'])))
})self.addEventListener('fetch', function (event) {event.respondWith(caches.match(event.request).then(function (response) {if (response) {return response;}return fetch(event.request);}))
})
144x144.png
将应用添加到桌面
manifest.js
{"short_name": "短名称","name": "这是一个完整名称","icons": [{"src": "144x144.png","type": "image/png","sizes": "144x144"}],"display": "standalone","start_url": "index.html"
}
按照上面方式配置,在移动端Chrome上访问,效果如下:
浏览器会提示一个“添加到主屏幕”的提示。提示的标题显示的是在manifest中定义的name,当点击时,就会将应用添加到桌面:
桌面图标上显示的文本为manifest中定义的short_name。
点击应用图标,打开应用:
可以看到根据设置的display属性,打开的应用去除了浏览器的地址栏。
注意
浏览器“添加到主屏幕”的提示是需要满足下面条件才会显示的:
- 需要manifest文件
- manifest中需要定义
start_url
- 需要包含144x144的png图标文件
- 网站是通过Https访问的
- 并且网站中运行ServiceWorker
- 用户需要至少浏览过网站两次,并且两次的间隔大于5分钟
- 如果修改了 manifest 的配置,已添加到主屏幕的名称并不会改变,只有当用户重新添加到桌面时,更改后的配置才会生效。但是在未来版本的 Chrome 浏览器将支持自动更新
关于上面提到的第4点,我们可以建立一个https网站或者可以直接用github的pages服务来实现。
关于第6点,是为了防止每次打开网址都有这个提示,对用户造成较差的体验。
设置主题色
"theme_color": "red"
给主题色设置个红色:
可以发现App的header上已经变成了设置的红色。
设置启动界面
启动界面是由icon、background_color和name构成的。
"background_color": "#2196f3"
效果:
icon也会根据屏幕的尺寸,浏览器来适配最佳的图标。
添加到主屏幕 触发的事件
当执行”添加到主屏幕“的操作时,内部会触发相应的事件beforinstallprompt
。可以利用这个事件做一些事情,例如App判断流量入口:
window.addEventListener('beforeinstallprompt', function(e) {e.userChoice.then(function (result){if (result.outcome === 'dismissed'){// 发送数据进行分析} else {// 发送数据进行分析}})
})
事件中的userChoice
对象用来返回用户的选择信息,处理是基于Promise的,这个后面章节会详说。
本地调试
上面是为了实现真是效果,所以在真是移动端上实现的。其实在测试的时候,是可以通过Chrome的开发者工具来测试的。
首先,打开上一章里下载的”WebServer for Chrome”本地服务器工具,并把项目加下到里面,然后开始服务
然后,在Chrome浏览器中访问”Web Server URL(s)“下的地址http://127.0.0.1:8887
然后,打开开发者工具,打开Application选项卡,选择Manifest,就可以后到配置的信息了。
并可以通过点击”Add to homescreen“触发添加图标到桌面的事件。
授权后即可添加到桌面
线上manifest验证
除去本地调试外,还可以通过在线清单验证工具来实现验证,例如:Web Manifest Validator
总结
到这里,总结一下:
- manifest是一种简单的JSON文件,通过对属性进行相应的配置,可以实现很多类Native的体验
- 添加到主屏幕会触发相应的事件,可以基于这些事件做相应的处理
- 调试的时候,可以基于Chrome的开发者工具,或者通过线上的测试验证工具
- https可以借助github pages功能实现
博客名称:王乐平博客
CSDN博客地址:http://blog.csdn.net/lecepin