PWA之 workbox 进修

媒介:
我们的运用能够分为两部份,一部份是属于主历程的(包括js(同步,异步),以及dom衬着等等),在一个时候点,只能实行一个,要么先去衬着dom,完了再去实行js;要么实行完js,在去衬着dom,而不能同时实行js和dom衬着。 另一部份属于worker历程,它从新在背景起了一个历程,它和运用的主历程互不影响,能够同时实行。

罕见的worker有,web worker, service worker, shared worker等等。

个中service worker平常作为web运用程序、浏览器和收集(假如可用)之间的代办效劳。他们旨在建立有用的离线体验,阻拦收集要求,以及依据收集是不是可用采纳适宜的行为,更新驻留在效劳器上的资本。他们还将许可接见推送关照和背景同步API。用来构建PWA 运用

运用service-worker前,我们必须要先在主历程中注册它,然后才在service-worker历程中编写逻辑。

主历程

//index.js
if ("serviceWorker" in navigator) {
    // Use the window load event to keep the page load performant
    window.addEventListener("load", () => {
      navigator.serviceWorker.register("/service-worker.js").then(registration=>{
        console.log("register succces...")
      }, err=>{
        console.log("register error...",err)
      });
    });
  }

service-worker历程

//service-worker.js
console.log('Hello from service-worker.js');

service-worker的语法简介

在service-worker.js中,self/this 示意 ServiceWorkerGlobalScope, 即全局的serviceworker工作环境,相称于在主历程中的window。在此文件中,js的其他api没法运用,如DOM,BOM操纵等,然则大部份的js api可用,同时ES6也能够运用。

在service-worker中能够定义监听事宜,然后在对应事宜中举行逻辑处置惩罚。

详细api可检察 service worker MDN

service-worker历程的实行流程

  1. 起首在主历程中最先注册,挪用register要领,进入sw历程,在sw历程中推断假如还没有装置service worker.js,则触发install事宜。最先装置
  2. 一旦sw历程装置完成,会关照主历程register胜利。
  3. 接着在sw历程 触发到activate事宜。
  4. 假如已装置过service-worker.js文件,则在注册时会发明并跳过install事宜,直接进入注册胜利,然后触发activate事宜。
  5. 然后最先在sw历程中经由过程fetch事宜,来监听http要求,并对要乞降相应举行缓存。
//在service worker中监听install
this.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open('v1').then(function(cache) {
      return cache.addAll([
        '/sw-test/',
        '/sw-test/index.html',
        '/sw-test/style.css',
        '/sw-test/app.js',
        '/sw-test/image-list.js',
        '/sw-test/star-wars-logo.jpg',
        '/sw-test/gallery/',
        '/sw-test/gallery/bountyHunters.jpg',
        '/sw-test/gallery/myLittleVader.jpg',
        '/sw-test/gallery/snowTroopers.jpg'
      ]);
    })
  );
});

除了 install以外,另有 activate,message,fetch,sync,push等事宜。

翻开chrome浏览器的application->service workers,会看到
《PWA之 workbox 进修》
能够看到status为 actived and is running,表明service-worker已装置胜利了。

在service-worker中经由过程监听事宜,然后编写对应的逻辑并非一件轻易的事,特别关于文件缓存,能够npm run build后,称号随时会变。

所以chrome官方推出了wokbox框架

《PWA之 workbox 进修》

wokbox 是用于向web运用程序增加离线支撑的JavaScript库。

要运用wokbox,只需在service-worker.js文件中引入workbox-sw.js即可,然后会自动的在service-worker.js中建立workbox对象,

importScripts('https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js');

if (workbox) {
  console.log(`Yay! Workbox is loaded 🎉`);
} else {
  console.log(`Boo! Workbox didn't load 😬`);
}

在wokbox对象中,包括许多模块,比方 workbox.routing模块,workbox.precaching模块,workbox.strategies模块,workbox.expiration模块等等,它们离别负责处置惩罚差别的逻辑。

1、workbox缓存/预缓存

//缓存文件
workbox.routing.registerRoute(
  /\.css$/,   //经由过程正则婚配须要缓存哪些文件
  new workbox.strategies.StaleWhileRevalidate({
    cacheName: 'css-cache',  //缓存名,可在application-> Cache storage下找到
  })
);

workbox.routing.registerRoute(
  /\.(?:js)$/,
  new workbox.strategies.CacheFirst({
    cacheName: 'js-cache',
    plugins: [
      //设置逾期时候和最大数目
      new workbox.expiration.Plugin({
        maxEntries: 20,
        maxAgeSeconds: 7 * 24 * 60 * 60,
      })
    ],
  })
);

workbox.routing.registerRoute表明 当service-worker在装置以后,当页面有发送对应http要求时,最先缓存。

而下面的workbox.precaching.precacheAndRoute能够在service-worker在装置之前,就把对应文件预先缓存下来。

workbox.precaching.precacheAndRoute([
  "/app.0.css",
  "/app.bundle.js",
  { url: "/start.html", revision: "dd75b1ef1ac2d4726b03fe46e90423f1" }
]);

此时我们在chrome下的 application->cache storage,会看到
《PWA之 workbox 进修》

缓存的称号,和缓存的文件列表

2、workbox路由

起首相识下处置惩罚路由的workbox的战略

  • StaleWhileRevalidate, 此战略将对要求运用缓存相应,并在背景运用收集相应更新缓存。假如没有缓存,它将守候收集相应并运用它),这是一种相称平安的战略,由于这意味着用户会按期更新其缓存。
  • NetworkFirst,这将起首尝试从收集猎取要求。假如收到相应,它会将其传递给浏览器并将其保存到缓存中。假如收集要求失利,将运用末了一个缓存的相应。
  • CacheFirst,此战略将起首搜检缓存中的相应,假如有可用则运用该战略。假如要求不在缓存中,则将运用收集,并且在传递给浏览器之前,任何有用相应都将增加到缓存中。
  • NetworkOnly,强迫从收集猎取。
  • CacheOnly,,强迫从缓存猎取。
workbox.routing.registerRoute(
  '/logo.png',    //婚配字符串路由
  new workbox.strategies.NetworkFirst()    //采纳NetworkFirst战略
);
workbox.routing.registerRoute(
  /\.js$/,   // 设置 正则 路由,
  new workbox.strategies.StaleWhileRevalidate(),  //采纳StaleWhileRevalidate战略
); 
//缓存第三方,比方jquery, 则战略最好运用NetworkFirst或许StaleWhileRevalidate, 不要运用CacheFirst
workbox.routing.registerRoute(
  'https://cdn.bootcss.com/jquery/3.4.1/jquery.js',
  new workbox.strategies.StaleWhileRevalidate(),
  //new workbox.strategies.NetworkFirst(),
); 

//假如非要运用CacheFirst战略,则运用workbox.cacheableResponse.Plugin限制
workbox.routing.registerRoute(
  'https://cdn.bootcss.com/jquery/3.4.1/jquery.js',
  new workbox.strategies.CacheFirst({
    plugins: [
      new workbox.cacheableResponse.Plugin({
        statuses: [0, 200]
      })
    ]
  }),
);
//还能够自定义战略的称号,逾期时候等等
workbox.routing.registerRoute(
  /\.(?:js)$/,
  new workbox.strategies.CacheFirst({
    cacheName: 'js-cache',
    plugins: [
      new workbox.expiration.Plugin({
        maxEntries: 20,
        maxAgeSeconds: 7 * 24 * 60 * 60,
      })
    ],
  })
);

在前面我们看到 cache的称号为 workbox-precache-v2-http://127.0.0.1:8081/,下面我们修正下

//最好写在紧贴着importScripts workbox-sw.js的下面,假如写在文件末了,则不见效。
workbox.core.setCacheNameDetails({
  prefix: "my-app",
  suffix: "v1",
  precache: "custom-precache-name",
  runtime: "custom-runtime-name"
});

《PWA之 workbox 进修》

3、workbox插件

  • workbox.backgroundSync.Plugin:假如收集要求失利,请将其增加到背景同步行列,并在触发下一个同步事宜时重试该要求。
  • workbox.broadcastUpdate.Plugin:每当缓存更新调理时,播送频道上的音讯或经由过程 postMessage()。
  • workbox.cacheableResponse.Plugin:仅缓存相符特定条件的缓存要求。
  • workbox.expiration.Plugin:治理缓存中项目的数目和最长限期。
  • workbox.rangeRequests.Plugin:相应包括Range:标头的要求,个中包括来自缓存的部份内容。

4、workbox debug

importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
importScripts("precache-manifest.7df9e91fe595ae52486747ebe221a710.js");

//强迫在service worker中运用debug。如许service worker中的log也能打印到chrome console上
workbox.setConfig({
  debug: true
});

《PWA之 workbox 进修》

4、在webpack中 集成 workbox,来自动的天生service worker

yarn add workbox-webpack-plugin
//webpack.config.js:
const WorkboxPlugin = require('workbox-webpack-plugin');

module.exports = {
  // Other webpack config...

  plugins: [
    // Other plugins...
    
    new WorkboxPlugin.GenerateSW()
  ]
};

然后实行

npm run build

此时在dist目录下会自动天生precache-manifest.<revision>.js 和 service-worker.js文件(为何名字是这个,不是sw.js,由于在注册时register(“/service-worker.js”)写的这个名字),如图:

《PWA之 workbox 进修》

在precache-manifest.<revision>.js文件中,将预缓存列表经由过程全局变量self.__precacheManifest公然,以便在service-worker.js中挪用。
默许会预缓存统统资本。
《PWA之 workbox 进修》

在service-worker.js中,则自动加载workbox cdn和 precache-manifest.<revision>.js文件,如图:
《PWA之 workbox 进修》

霎时觉得方便了许多……..

由于默许会预缓存统统资本,假如你不喜欢预缓存某些文件,如图片,而在运转时缓存,则能够在runtimeCaching中定制它们

// 这些选项协助 ServiceWorkers 疾速启用
new WorkboxPlugin.GenerateSW({
      // 在预缓存中消除 图片
      exclude: [/\.(?:png|jpg|jpeg|svg)$/],

      //定义运转时缓存(可接受多个json对象)
      runtimeCaching: [
        {
          urlPattern: /\.(?:png|jpg|jpeg|svg)$/,
          // 在缓存时运用 StaleWhileRevalidate 战略.
          handler: "StaleWhileRevalidate",
          options: {
            // 定义缓存这些图片的 cache称号
            cacheName: "my-images-cache",

            //设置 expiration
            expiration: {
              maxEntries: 10,
              maxAgeSeconds: 60
            },

            // 设置 background sync.
            backgroundSync: {
              name: "my-queue-name",
              options: {
                maxRetentionTime: 60 * 60
              }
            },

            //设置哪些相应被认为是可缓存的
            cacheableResponse: {
              statuses: [0, 200],
              headers: { "x-test": "true" }
            },

            //设置播送缓存更新插件。
            broadcastUpdate: {
              channelName: "my-update-channel"
            },

            //matchOptions和fetchOptions用于设置handler
            fetchOptions: {
              mode: "no-cors"
            },
            matchOptions: {
              ignoreSearch: true
            }
          }
        }
      ],

      importWorkboxFrom: "cdn", //经由过程cdn加载workbox, 还可经由过程‘local’加载,如许会将全部workbox下载到当地,再从当地援用
      skipWaiting: false, // service worker是不是应当跳过守候生命周期阶段
      clientsClaim: false, //service worker是不是应当在任何现有客户端激活后马上最先掌握它

      cacheId: "my-app-test",
      offlineGoogleAnalytics: true
    })

运转npm run build后,会看到自动天生以下的service-worker.js
《PWA之 workbox 进修》

假如没涌现,则只须要清空cache和service-worker文件即可,在clear storage中勾选unregister service workers和 cache storage,然后点击clear site data即可清算,然后革新页面就会看到最新的service worker和cache storage。
《PWA之 workbox 进修》

我们会发明不论vue照样react,构建后,点开service-worker.js文件发明都和我们适才自动天生的service-worker.js异常类似,差别的是,vue和react都把new WorkboxPlugin.GenerateSW部份封装了起来,除非npm run eject才看到和修正。

    原文作者:寒山寺一禅
    原文地址: https://segmentfault.com/a/1190000019281388
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞