我有一个PWA,它本质上是一个图书阅读器。因此,它需要大量的数据(即书籍文本)来操作。当由Lighthouse分析时,它在页面加载检查中得分很低。
我的问题是:我可以采用哪些方法来改善页面加载,同时仍确保离线功能?
我可以有一个最小的起始页(例如,只显示“请稍候,正在下载文本”消息),然后动态下载(通过注入的脚本标签或 AJAX)JSON 数据文件。但是,我不确定随后如何确保从缓存中获取数据。
只是想知道其他人是如何处理这个问题的......
我有一个PWA,它本质上是一个图书阅读器。因此,它需要大量的数据(即书籍文本)来操作。当由Lighthouse分析时,它在页面加载检查中得分很低。
我的问题是:我可以采用哪些方法来改善页面加载,同时仍确保离线功能?
我可以有一个最小的起始页(例如,只显示“请稍候,正在下载文本”消息),然后动态下载(通过注入的脚本标签或 AJAX)JSON 数据文件。但是,我不确定随后如何确保从缓存中获取数据。
只是想知道其他人是如何处理这个问题的......
由于这个问题已经成为风滚草,我决定发布我的尝试结果。
根据Jake 的文章,我使用以下脚本和 Chrome DevTools 来研究 service worker 事件:
'use strict';
let container = null;
let updateFound = false;
let newInstall = false;
window.onload = () => {
container = document.querySelector('.container');
let loading = document.createElement('div');
loading.classList.add('loading');
loading.innerHTML = 'Downloading application.<br>Please wait...';
container.appendChild(loading);
console.log(`window.onload: ${Date.now()}`);
swEvents();
};
let swEvents = () => {
if (navigator.serviceWorker) {
navigator.serviceWorker.ready.then(() => {
console.log(`sw.ready: ${Date.now()}`);
if (!updateFound) {
loadApp();
return;
}
newInstall = true;
console.log(`new install: ${Date.now()}`);
}).catch((error) => {
console.log(`sw.ready error: ${error.message}`);
});
}
navigator.serviceWorker.register('/sw.js').then((reg) => {
reg.onupdatefound = () => {
updateFound = true;
console.log(`reg.updatefound: ${Date.now()}`);
const newWorker = reg.installing;
newWorker.onstatechange = (event) => {
if (event.target.state === 'activated') {
console.log(`nw.activated: ${Date.now()}`);
if (newInstall) {
loadApp();
return;
}
refresh();
}
};
};
}).catch((error) => {
console.log(`reg.error: ${error.message}`);
});
};
let refresh = () => {
console.log(`refresh(): ${Date.now()}`);
// window.location.reload(true);
};
let loadApp = () => {
console.log(`loadApp(): ${Date.now()}`);
let child;
while (child = container.firstChild) {
container.removeChild(child);
}
let message = document.createComment('p');
message.textContent = 'Application loading';
container.appendChild(message);
let tag = document.createElement('script');
tag.src = './app.js';
document.body.appendChild(tag);
};
一路走来,我了解到,一旦注册了 service worker,它就会立即开始下载所有缓存的资源。我曾假设资源仅在页面加载后才被缓存。我还发现了一些明确的事件模式来指示正在发生的生命周期阶段。
对于新安装,上述脚本中记录了以下事件:
window.onload -> reg.updatefound -> sw.ready -> nw.activated
对于这种情况,当sw.ready触发时,所有资源都已被缓存。此时,我可以将应用从“请稍候”阶段切换并动态加载缓存资源并启动应用。
对于简单的页面刷新,将记录以下事件:
window.onload -> sw.ready
如果应用程序已经下载并且没有可用的更新,这将是事件序列。此时,我可以再次切换阶段并启动应用程序。
对于服务工作者脚本更新后的页面刷新,将记录以下事件:
window.onload -> sw.ready -> reg.updatefound -> nw.activated
在这种情况下,当nw.activated触发时,所有缓存的资源都已更新。需要再次刷新页面才能实际加载更改。此时,可能会提示用户进行更新。或者应用程序将在下次启动时自行更新。
通过跟踪这些事件模式,很容易判断 Service Worker 处于哪个生命周期阶段并采取适当的措施。