简介
●此处将“优雅”的含义定义为两个方面:
(1)应用webpack生态简化ServiceWorker的配置;
(2)ServiceWorker的开关控制与相关库的按需加载;
●第一方面具体是offline-plugin插件的应用;
●第二方面是动态获取前端配置与webpack的Code Spliting机制的应用;
offline-plugin插件的应用
○webpack生态提供了offline-plugin用于方便地使用ServiceWorker,首先在项目内安装此依赖;
○然后对offline-plugin进行配置与引入,分为以下两部分:
(1)作为webpack插件在项目webpack配置文件中增加此plugins的配置;
(2)作为js库在main.js中引入与实例化运行时对象;
○在ServiceWorker更新安装完成后强制生效通过在以上(1)部分配置”events:true”和在以上(2)部分中处理onUpdateReady和onUpdated两个事件回调实现;
动态获取前端配置
■为方便线上环境下必要时候关闭ServiceWorker机制,将ServiceWorker的开关配置在服务端,当前是否启用由从服务器获取到的开关取值决定;
■当获取到的开关值为false则进行ServiceWorker的注销以保证ServiceWorker的彻底关闭;
Code Spliting机制的应用
▲通过splitChunks将offline-plugin显式拆分为独立的chunk;
▲main.js中使用动态import的方式引入offline-plugin的运行时class;
▲如此实现了对offline-plugin的按需加载;
代码实例
◆webpack配置文件增加如下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| var OfflinePlugin = require('offline-plugin');
module.exports = { …… optimization: { …… splitChunks: { minSize: 0, // 关掉独立chunk最小大小的限制 cacheGroups: { offline: { // 将offline-plugin显式拆分成独立的chunk test: /offline-plugin/, name: 'offline', chunks: 'all', priority: 3 }, …… } …… plugins: [ …… new OfflinePlugin({ AppCache: false, //`offline-plugin`默认支持`AppCache`,但是`AppCache`草案已经被web标准所废弃,不建议使用。但是由于仍然有部分浏览器支持,所以插件默认提供这个功能。 safeToUseOptionalCaches: true, // 去除`additional | optional`路径检查不确定时打印的警告 ServiceWorker: { events: true //用于当前控制页面的sw的强制更新 }, caches: { //缓存内容的精细控制 main: ['index.html', '*/vconsole.min.js'], additional: ['*/js/common.*.js', '*/js/app.*.js', '*/js/vendor.*.js'], optional: [':rest:'] } }) ] };
|
◆main.js文件增加如下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| // Service Worker if ('serviceWorker' in navigator) { if (config.serviceWorker) {// 从服务器获取到的ServiceWorker开关值 setTimeout(() => {// 防止干扰主程序初始化速度,将ServiceWorker的初始化放到主线程执行队列的队尾 console.log('serviceWorker init'); import('offline-plugin/runtime').then(swRuntime =>{ swRuntime.install({ onUpdateReady: () => { console.log('sw onUpdateReady'); swRuntime.applyUpdate(); // 作用相当于原生ServiceWorker的self.skipWaiting() }, onUpdated: () => { // 作用相当于原生ServiceWorker的监听 controllerchange 事件 console.log('sw onUpdated'); window.location.reload(); } }); }, 0); } else { // 注销Service Worker时,使用如下片段: navigator.serviceWorker.getRegistration().then(registration => { registration && registration .unregister() .then(boolean => { boolean ? console.log('Service Worker注销成功') : console.log('Service Worker注销失败'); }) .catch(error => { console.log(`Service Worker注销异常:${error}`); }); }); } }
|