网站首页 > 技术文章 正文
目标:让网站变成可安装应用
要让网站变成可安装,需要满足下面的条件:
- 设置 manifest,manifest 必须要有较为丰富的图标信息,部分尺寸的图标缺失会有影响
- 网站需要是 https 协议,本地开发无法测试
- 与 manifest 匹配的 service worker
下面来逐个解决。
manifest
在 head 标签中添加 manifest 信息:
<link rel="manifest" href="manifest.json" />
manifest.json 的内容大概像这样:
{
"name": "应用完整名称",
"short_name": "应用短名称",
"description": "应用描述信息",
"start_url": "/", // 启动入口地址
"display": "minimal-ui", // 显示模式,minimal-ui 表示让应用有独立窗口,显示尽可能少的控制元素
"theme_color": "#ffffff", // 主题色,应用窗口顶标题栏的背景色
"background_color": "#ffffff", // 样式加载前的页面背景色
"icons": [
// 图标
{
"src": "icons/icon-192.png",
"sizes": "192x192"
}
]
}
关于 manifest 各个选项的详细说明可以参考:Web app manifests | MDN。
图标很重要,某个尺寸的图标缺少可能会导致应用不可安装,如果不想设置那么多个,也可以只设置一个比较大的图标,至少 192x192 以上,能覆盖到浏览器需要的尺寸,实测在 edge 浏览器中可行。
你还可以使用在线构建工具 PWA Image Generator 来生成图标:。
service worker
service worker 你可以看成是一个后台运行的请求代理层,用来管理缓存文件,使用缓存文件来响应请求,减少联网。
注册
在页面上添加脚本,注册 service worker:
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('/sw.js', { scope: '/' })
.then(function (registration) {
console.log('Service worker 注册成功:', registration)
})
.catch(function (error) {
console.log('Service worker 注册失败:', error)
})
}
这里的 scope 需要注意,默认不加参数就是 serviceWorker 脚本所在的目录,如果要设置也只能设置 serviceWorker 脚本所在目录或其子目录。这个 scope 决定了是否能与 manifest 匹配,manifest 中 start_url 必须在 scope 下,否则不能安装,浏览器控制台会有提示:
本地缓存版本管理
下面是 sw.js 代码,我们要完成一个简单的应用版本管理:
// cache-files.js 提供了 cacheName 和 files
self.importScripts('/cache-files.js')
// 安装钩子,缓存所有文件
self.addEventListener('install', e => {
e.waitUntil(
(async () => {
const cache = await caches.open(cacheName)
await cache.addAll(files)
})()
)
})
// 代理 fetch, 如果缓存中有则从缓存中取,没有则直接请求
self.addEventListener('fetch', e => {
e.respondWith(caches.match(e.request).then(response => response || fetch(e.request)))
})
// 在 service worker 激活成功后,检查并删除旧版本
self.addEventListener('activate', function (e) {
e.waitUntil(
caches.keys().then(function (keyList) {
return Promise.all(
keyList.map(function (key) {
// 缓存名称和当前不一致的就是以前的旧版本删除掉
if (cacheName !== key) {
return caches.delete(key)
}
})
)
})
)
})
上面的代码中导入了 cache-files.js ,实际上也可以直接写在 sw.js 中,这样做是为了方便管理,sw.js 中存放程序逻辑,cache-files.js 存放数据, 每次程序有升级,只改动 cache-files.js 即可,cache-files.js 也可以由脚本自动生成。
cache-files.js 代码:
// 缓存名称带有版本号,每次程序发布新版本 cacheName 也跟着变化
const cacheName = 'my-app-v1.0.0'
// files 就是要缓存的文件列表,根据实际情况填写
const files = [
'https://unpkg.com/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js',
'https://unpkg.com/bootstrap@5.1.3/dist/css/bootstrap.min.css',
'/js/app.js',
'/css/app.css',
'/',
'/index.html'
]
需要注意的是引入别的站点的 cdn 文件,需要支持跨域,得设置 cros 消息头,例如上面引入的 bootstrap , 如果不支持跨域,则在安装的时候就会报错,缓存失败。另外站内的文件能否缓存和 service worker 的 scope 是有关的, 文件必须在 scope 下,否则不会触发 fetch 事件,无法被代理。
如果 scope 是 /path/,那么 /path 也是不能被代理的,访问 /path 这个页面的话,service worker 不会工作, 也不能进行任何代理,即使页面中引用的 js 或 css 等文件在 scope 内也不会有效果。而且,如果 service worker 的位置是 /path/ws.js ,scope 是不允许被设置成 /path,只能是 /path/。当然,如果你的 service worker 脚本在站点根目录, 就不必操心 scope 的这些麻烦事了。
想知道 service worker 有没有代理成功,可以在浏览器的控制台中查看网络。
如果代理成功,履行者应该是 ServiceWorker ,并且大小是 0,这表示成功使用了本地缓存,避免了联网。
到此 service worker 就开发完成了,应用已经可以安装了。如果你不需要应用可安装,不设置 manifest ,只单纯的使用 ServiceWorker 来缓存文件提速,也是可以的。
其它参考资料
通过上面的简单操作就可以让我们的网站变成可安装了,但是这太简单了,不一定能满足你的需求。 如果你想做更强大的版本控制,可以考虑使用谷歌的 workbox。
- 上一篇: 前端学起来特别吃力,新人入前端怎么学?
- 下一篇: 2.6万字JS干货分享,带你领略前端魅力【实践篇】
猜你喜欢
- 2024-11-12 前端如何操作文件夹 文件 写入??? #每天一个小知识
- 2024-11-12 手把手教你JS实现魔方模拟器 魔方模拟软件
- 2024-11-12 距离 JS 大神 你还有多远? js计算距离
- 2024-11-12 React Hooks中这样写HTTP请求可以避免内存泄漏
- 2024-11-12 由一道题彻底弄懂 JavaScript继承
- 2024-11-12 JavaScript 错误处理大全「值得收藏」
- 2024-11-12 七爪源码:JavaScript 异步编程演进
- 2024-11-12 强烈推荐用1.2kb 的 idb 来管理 IndexedDB
- 2024-11-12 手把手教你全面分析前端如何网络请求方式
- 2024-11-12 2.6万字JS干货分享,带你领略前端魅力【实践篇】
- 标签列表
-
- content-disposition (47)
- nth-child (56)
- math.pow (44)
- 原型和原型链 (63)
- canvas mdn (36)
- css @media (49)
- promise mdn (39)
- readasdataurl (52)
- if-modified-since (49)
- css ::after (50)
- border-image-slice (40)
- flex mdn (37)
- .join (41)
- function.apply (60)
- input type number (64)
- weakmap (62)
- js arguments (45)
- js delete方法 (61)
- blob type (44)
- math.max.apply (51)
- js (44)
- firefox 3 (47)
- cssbox-sizing (52)
- js删除 (49)
- js for continue (56)
- 最新留言
-