网站开发设置PWA(Progressive Web App,渐进式 Web 应用)

生活日记 工作心得
31
发表时间: 编辑:顾永胜来源:0513.city标签:网站开发

1.下载workbox-v7.4.1本地JS版本:workbox-v7.4.1

将文件解压到public/static/js文件里面。

2.配置manifest.json,最简能用配置:

{
  "name""citya",
  "short_name""citya",
  "start_url""/",
  "display""standalone",
  "background_color""#ffffff",
  "theme_color""#ffffff",
  "icons": [
    {
      "src""/static/img/icon-192x192.png",
      "sizes""192x192",
      "type""image/png"
    },
    {
      "src""/static/img/icon-512x512.png",
      "sizes""512x512",
      "type""image/png"
    }
  ]
}

manifest.json文件放在public文件夹里。

html页面引用:

<link rel="manifest" href="/manifest.json">

3.写一个安装app.js,内容如下:

(function () {
  'use strict';
  if (!('serviceWorker' in navigator)) return;
  window.addEventListener('load'function () {
    navigator.serviceWorker.register('/sw.js')
      .catch(function (err) {
        if (window.Sentrywindow.Sentry.captureException(err);
      });
  });
})();

app.js文件放到public/static/js目录中。

4.创建sw.js文件,内容如下:

importScripts('/static/js/workbox-v7.4.1/workbox-sw.js');
const RUNTIME_VERSION = 'v1';
workbox.setConfig({
  modulePathPrefix: '/static/js/workbox-v7.4.1/'
});
/**
 * 预缓存核心页面(只作为离线兜底,不强制走缓存)
 */
workbox.precaching.precacheAndRoute([
  { url: '文件路径,如:/static/img/logo.png'revision: '1' },
]);
/**
 * HTML 页面:网络优先
 */
workbox.routing.registerRoute(
  ({ request }) => request.mode === 'navigate',
  new workbox.strategies.NetworkFirst({
    cacheName: `html-cache-${RUNTIME_VERSION}`,
    plugins: [
      new workbox.expiration.ExpirationPlugin({
        maxEntries: 500,
       // maxAgeSeconds: 7 * 24 * 60 * 60  // 缓存 7 天
      })
    ]
  })
);
/**
 * 带参数的请求:不缓存
 */
workbox.routing.registerRoute(
  ({ url }) => url.search.length > 0,
  new workbox.strategies.NetworkOnly()
);
/**
 * 图片:先缓存后台更新
 */
 workbox.routing.registerRoute(
  ({ request }) => request.destination === 'image',
  new workbox.strategies.StaleWhileRevalidate({
    cacheName: `image-cache-${RUNTIME_VERSION}`,
    plugins: [
      new workbox.expiration.ExpirationPlugin({
        maxEntries: 500,
        //maxAgeSeconds: 30 * 24 * 60 * 60
      })
    ]
  })
);
/**
 * JS / CSS / 字体:永久缓存(手动版本控制更新缓存)
 */
workbox.routing.registerRoute(
  ({ request }) => 
    request.destination === 'script' ||
    request.destination === 'style'  ||
    request.destination === 'font',
  new workbox.strategies.CacheFirst({
    cacheName: `static-cache-${RUNTIME_VERSION}`,
    plugins: [
      new workbox.expiration.ExpirationPlugin({
        maxEntries: 500,
        //maxAgeSeconds: 365 * 24 * 60 * 60
      }),
      new workbox.cacheableResponse.CacheableResponsePlugin({
        statuses: [0200]
      })
    ]
  })
);
/**
 * 匹配所有 POST/PUT/DELETE 请求:只走网络,不缓存
 */
workbox.routing.registerRoute(
  ({ request }) => ['POST''PUT''DELETE''PATCH'].includes(request.method),
  new workbox.strategies.NetworkOnly()
);
/**
 * API只能通过网络
 */
 workbox.routing.registerRoute(
  ({ url }) => url.pathname.startsWith('/api/'),
  new workbox.strategies.NetworkOnly()
);
/**
 * 激活时清理旧缓存 
 */
 self.addEventListener('activate', (event=> {
   event.waitUntil(
     caches.keys().then((cacheNames=> {
       return Promise.all(
         cacheNames
           .filter((name=> {
             /**
              * 保留 workbox 自身缓存
              */
             if (name.startsWith('workbox-')) return false;
             /**
              * 保留当前版本的缓存(以 -v1 结尾的)
              */
             if (name.endsWith(`-${RUNTIME_VERSION}`)) return false;
             return true;
           })
           .map((name=> caches.delete(name))
       );
     }).then(() => self.clients.claim())
   );
 });

sw.js文件,放在public目录中。

5.Html页面引用app.js文件:

<script src="/static/js/app.js" defer>script>

经过上面的配置,网站就有了基本离线功能,只要打开过的网页,在没有网络的情况下也能够打开预览。