目录
IOS无法获取webpack-pwa-manifest中配置的icon
前言
= — = 以下结论和方法均为个人摸索,涵盖从度娘那儿找到的方法,欢迎大佬们指点。
PWA的简单了解和需求
PWA(Progressive web apps,渐进式 Web 应用)运用现代的 Web API 以及传统的渐进式增强策略来创建跨平台 Web 应用程序。通俗来说,PWA应用是指那些使用指定技术和标准模式来开发的web应用,这将同时赋予它们web应用和原生应用的特性。
需求是根据参数的不同,将所代表的不同项目的icon和名称,以应用的方式自动保存在手机主屏幕上。
这里就需要
- manifest.json 网页清单,通过json形式列举了网站的所有信息
- service workers 浏览器和网络之间的虚拟代理,它的功能很强大,我这里目前是需要它能提供离线功能(再深层次的功能也暂时没有时间去了解了)
具体可以参考:渐进式 Web 应用(PWA)
项目manifest.json和sw的无脑生成神器
首先,先说结论,省略了中间的探索步骤会在后面补上。
最方便的,没有什么问题的方法,就是使用webpack的插件。pwa是谷歌近几年一直在推进的 web 应用新模型。相应的,谷歌当然也会发布关于这个的web插件——Workbox webpack Plugins。
workbox 是由谷歌浏览器团队发布,用来协助创建 PWA 应用的 JavaScript 库。当然直接用 workbox 还是太复杂了,这个插件就很贴心的发布了一个 webpack 插件,能够自动生成 Service Worker 和 静态资源列表。
安装
const worboxWebpackPlugin = require("workbox-webpack-plugin");
new worboxWebpackPlugin.GenerateSW({
clientsClaim: true, // 强制等待中的 Service Worker 被激活
skipWaiting: true, // Service Worker 被激活后使其立即获得页面控制权
}),
注册
if ("serviceWorker" in navigator) {
window.addEventListener("load", () => {
navigator.serviceWorker
.register("/service-worker.js")
.then((registration) => {
console.log("SW registered: ", registration);
})
.catch((registrationError) => {
console.log("SW registration failed: ", registrationError);
});
});
}
打包时就能生成service-worker.js和workbox.js两个文件(不包括.js.map)
另一个插件是webpack-pwa-manifest,用于生成manifest.json文件
// 以下代码来自https://www.npmjs.com/package/webpack-pwa-manifest
// 安装
npm install --save-dev webpack-pwa-manifest
// 使用
// ES6+
import WebpackPwaManifest from 'webpack-pwa-manifest'
// ES5
var WebpackPwaManifest = require('webpack-pwa-manifest')
...
plugins: [
new WebpackPwaManifest({
name: 'My Progressive Web App',
short_name: 'MyPWA',
description: 'My awesome Progressive Web App!',
background_color: '#ffffff',
crossorigin: 'use-credentials', //can be null, use-credentials or anonymous
icons: [
{
src: path.resolve('src/assets/icon.png'),
sizes: [96, 128, 192, 256, 384, 512] // multiple sizes
},
{
src: path.resolve('src/assets/large-icon.png'),
size: '1024x1024' // you can also use the specifications pattern
},
{
src: path.resolve('src/assets/maskable-icon.png'),
size: '1024x1024',
purpose: 'maskable'
}
]
})
]
// 输出 manifest.<fingerprint>.json
{
"name": "My Progressive Web App",
"orientation": "portrait",
"display": "standalone",
"start_url": ".",
"short_name": "MyPWA",
"description": "My awesome Progressive Web App!",
"background_color": "#ffffff",
"icons": [
{
"src": "icon_1024x1024.<fingerprint>.png",
"sizes": "1024x1024",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "icon_1024x1024.<fingerprint>.png",
"sizes": "1024x1024",
"type": "image/png"
},
{
"src": "icon_512x512.<fingerprint>.png",
"sizes": "512x512",
"type": "image/png"
},
{
"src": "icon_384x384.<fingerprint>.png",
"sizes": "384x384",
"type": "image/png"
},
{
"src": "icon_256x256.<fingerprint>.png",
"sizes": "256x256",
"type": "image/png"
},
{
"src": "icon_192x192.<fingerprint>.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icon_128x128.<fingerprint>.png",
"sizes": "128x128",
"type": "image/png"
},
{
"src": "icon_96x96.<fingerprint>.png",
"sizes": "96x96",
"type": "image/png"
}
]
}
大部分字段无需解释,但是让我们分解一下文档并且详细解释这些字段:
name
: 网站应用的全名。short_name
: 显示在主屏上的短名。description
: 一两句话解释你的应用的用途。icons
: 一串图标信息 — 源URL,大小和类型。确保包含一些图标,这样有一个最合适用户设备的图标可以被选中。start_url
: 启动应用的index文档。display
: 应用的显示方式;可以是全屏,独立,最小UI或者浏览器。theme_color
: UI的主颜色,这是操作系统使用的。background_color
: 背景色,用于安装程序时和显示启动画面时。
一份网页清单最少需要name和一个图标 (带有 src, size 和 type)。description, short_name, 和start_url最好要提供。还有在上述列表之外的字段你可以使用 — 请查看网页应用清单参考获得详细情况。
当然,不用插件生成也是可以的,简单的项目可以直接手动创建。
{
"name": "js13kGames Progressive Web App",
"short_name": "js13kPWA",
"icons": [
{
"src": "/img/icons/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/img/icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"start_url": "/index.html",
"display": "standalone",
"background_color": "#B12A34",
"theme_color": "#B12A34"
}
再将文件引入在入口文件html内
<link rel=manifest href=/manifest.json>
用插件就不用加这句,另外用插件的的好处就是会自动帮你把一张图片切成各种格式尺寸。(下图Icons处可看出)
可以从开发者工具上看我们的配置: (图片为参考网站的示例)
如果配置文件不生效,这里就只会显示No manifest detected,同样的,sw也能在浏览器看出来
如果sw没有生效,status的那个绿色小点大概是红色的(我忘了哈哈。。)也可以点击后面的stop停止服务。
在谷歌浏览器的右上角,符合PWA可保存在桌面的网站,会出现黄色框框住的图标
当谷歌浏览器上出现这个添加图标时,在兼容pwa的浏览器中,可以自动弹出安装在左面的弹窗。
手机浏览器目前是发现华为手机(非荣耀)、小米手机的默认浏览器可以自动弹出,其他的就是我在前言说的兼容性问题,均无法自动弹出。 (解决的方案:弹出提示图指引用户手动保存在桌面)
还有很多奇奇怪怪的因素会导致连华为(非荣耀)和小米手机都无法默认弹出的问题,后面看情况补上~
动态配置manifest.json
根据需求,需要根据项目参数的不同动态更改manifest配置清单,这就是坑的开始~~
无论是使用webpack-pwa-manifest创建的还是手动创建的,都是在项目打包上线前就需要写好的配置,上线后就固定了。要根据参数的不同就得在项目运行的时候获取到后端数据来更改覆盖manifest.json。
在网上就找到了一种方法,是讲新的manifest文件写成二进制流,替换原来的文件。
能正常使用,但是出现了两个问题
- 华为(非荣耀)和小米手机都无法自动弹窗了 = = (后来采取了全部都使用弹出引导用户手动操作的方式)
- 安卓机型无法读取manifest.json :保存时可以获取到名字是因为在更改的时候也改了document.title,icon除了小米默认获取favicon.ico,其他都是奇奇怪怪的icon (到后面也没解决,哈哈哈哈。。)
动态的网页清单,icon下面会解决,解决后反而不见了哈哈哈 尴尬
IOS无法获取webpack-pwa-manifest中配置的icon
一开始以为是ios也无法读取,毕竟官方网站上没写Safari支持。以为和安卓一样是默认读取的docum.title,无关配置文件问题
解决方法: webpack-pwa-manifest自动生成的icon后面都带了hash值,模板文件添加icon路径:
<link rel="apple-touch-icon" href="icon.png" />
// 我这里图方便就不加哈希值了
在根目录下放个icon.png ios就能获取到icon了。
但是每次更改后打包都要加这个就很容易忘,所以我又去翻webpack-pwa-manifest官方文档(manifest.json的官方配置是没有的),发现有个ios的配置参数。
加上后果然是在ios也能获取到icon了,后面还有ios其他的使用方法,但是可以用我就没继续看下去了(实在是脑阔痛。。)
动态的网页清单无法被读取
来自因为需求而产生的静态manifest.json的坑
前面写的使用webpack-pwa-manifest创建和还是手动创建的网页清单我都叫静态的。通看下来,只要是单一网站,即固定的icon和名称,静态的就似乎没有什么问题。于是需求由 根据参数不同来判断 改成 根据路径不同来判断,这样可以设置不同的manifest来引入对应的入口文件。
但是这个项目还是需要携带参数的,start_url默认是写的当前页面地址(不带参数),或者是写固定的参数。但这都不符合要求,于是最后的最后还是因为这个问题改回了动态manifest的方法。(= = 中间略过了同套代码打包成不同目录的各种问题)