改善PWA页面加载

时间:2019-01-05 00:20:55

标签: progressive-web-apps

我有一个PWA,本质上是一本书的读者。结果,它需要大量数据(即书籍文本)进行操作。由Lighthouse分析时,它在页面加载检查中得分很低。

我的问题是:在确保离线功能的同时,我可以采用哪些方法来改善页面负载?

我的起始页面可能很小(例如,仅显示“请稍等,正在下载文本”消息),然后动态地(通过注入的脚本标签或AJAX)下载JSON数据文件。但是,我不确定随后如何确保从缓存中提取数据。

只是想知道其他人如何处理此问题...

1 个答案:

答案 0 :(得分:0)

由于这个问题风风雨雨,我决定发布尝试的结果。

基于Jake's article,我使用以下脚本和Chrome DevTools研究服务工作者事件:

'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);
};

在整个过程中,我了解到注册了服务工作者后,它将立即开始下载所有缓存的资源。我以为资源仅在页面加载后才被缓存。我还发现了一些确定的事件模式,以指示发生了哪个生命周期阶段。

对于新安装,上述脚本中记录了以下事件:

window.onload -> reg.updatefound -> sw.ready -> nw.activated

在这种情况下,当sw.ready触发时,所有资源都已缓存。此时,我可以从“请稍候”阶段切换应用程序,并动态加载缓存的资源并启动应用程序。

要进行简单的页面刷新,将记录以下事件:

window.onload -> sw.ready

如果已经下载了该应用并且没有可用的更新,则将是事件序列。此时,我可以再次切换相位并启动应用程序。

要在更新Service Worker脚本后刷新页面,将记录以下事件:

window.onload -> sw.ready -> reg.updatefound -> nw.activated

在这种情况下,当nw.activated触发时,所有缓存的资源都已更新。需要重新刷新页面才能实际加载更改。此时,可以提示用户进行更新。否则,该应用将在下次启动时自行更新。

通过跟踪这些事件模式,很容易知道服务人员处于哪个生命周期阶段并采取适当的措施。