From 8a1e44f1fa86d3a460b7e664b3371d461089a959 Mon Sep 17 00:00:00 2001 From: SunWuyuan Date: Sat, 5 Apr 2025 09:23:27 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9C=AC=E5=9C=B0=E7=BC=93=E5=AD=98=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 + dev-dist/sw.js | 59 ++++- public/image/apple-touch-icon-180x180.png | Bin 576 -> 526 bytes public/image/favicon.ico | Bin 367 -> 368 bytes public/image/logo.svg | 16 +- public/image/maskable-icon-512x512.png | Bin 1535 -> 1329 bytes public/image/pwa-192x192.png | Bin 746 -> 670 bytes public/image/pwa-512x512.png | Bin 1622 -> 1503 bytes public/image/pwa-64x64.png | Bin 339 -> 297 bytes public/sw-cache-manager.js | 44 ++++ src/components/CacheManager.vue | 238 ++++++++++++++++++ .../cards/DataProviderSettingsCard.vue | 29 +-- src/pages/CacheManagement.vue | 22 ++ src/sw.js | 141 +++++++++++ vite.config.mjs | 110 ++++++-- 15 files changed, 612 insertions(+), 49 deletions(-) create mode 100644 public/sw-cache-manager.js create mode 100644 src/components/CacheManager.vue create mode 100644 src/pages/CacheManagement.vue create mode 100644 src/sw.js diff --git a/.gitignore b/.gitignore index 997223d..17ab75f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .DS_Store node_modules /dist +/dev-dist # local env files .env.local @@ -21,3 +22,4 @@ pnpm-debug.log* *.njsproj *.sln *.sw? + diff --git a/dev-dist/sw.js b/dev-dist/sw.js index ebc5fa9..48d0c19 100644 --- a/dev-dist/sw.js +++ b/dev-dist/sw.js @@ -67,8 +67,9 @@ if (!self.define) { }); }; } -define(['./workbox-86c9b217'], (function (workbox) { 'use strict'; +define(['./workbox-5ea419d9'], (function (workbox) { 'use strict'; + importScripts("sw-cache-manager.js"); self.skipWaiting(); workbox.clientsClaim(); @@ -81,12 +82,62 @@ define(['./workbox-86c9b217'], (function (workbox) { 'use strict'; "url": "suppress-warnings.js", "revision": "d41d8cd98f00b204e9800998ecf8427e" }, { - "url": "index.html", - "revision": "0.6m682f8mvag" + "url": "/", + "revision": "0.0lkakoc2in8" }], {}); workbox.cleanupOutdatedCaches(); - workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), { + workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("/"), { allowlist: [/^\/$/] })); + workbox.registerRoute(/\.(?:js)$/i, new workbox.StaleWhileRevalidate({ + "cacheName": "js-cache", + plugins: [new workbox.ExpirationPlugin({ + maxEntries: 100, + maxAgeSeconds: 604800 + })] + }), 'GET'); + workbox.registerRoute(/\.(?:css)$/i, new workbox.StaleWhileRevalidate({ + "cacheName": "css-cache", + plugins: [new workbox.ExpirationPlugin({ + maxEntries: 50, + maxAgeSeconds: 604800 + })] + }), 'GET'); + workbox.registerRoute(/\.(?:html)$/i, new workbox.NetworkFirst({ + "cacheName": "html-cache", + plugins: [new workbox.ExpirationPlugin({ + maxEntries: 20, + maxAgeSeconds: 86400 + })] + }), 'GET'); + workbox.registerRoute(/\.(?:png|jpg|jpeg|svg|gif)$/i, new workbox.StaleWhileRevalidate({ + "cacheName": "images-cache", + plugins: [new workbox.ExpirationPlugin({ + maxEntries: 50, + maxAgeSeconds: 2592000 + })] + }), 'GET'); + workbox.registerRoute(/\/cdn-cgi\/.*/i, new workbox.NetworkFirst({ + "cacheName": "cdn-cgi-cache", + "networkTimeoutSeconds": 10, + plugins: [new workbox.ExpirationPlugin({ + maxEntries: 50, + maxAgeSeconds: 86400 + })] + }), 'GET'); + workbox.registerRoute(({ + url + }) => { + return url.origin !== self.location.origin; + }, new workbox.NetworkFirst({ + "cacheName": "external-resources", + "networkTimeoutSeconds": 10, + plugins: [new workbox.ExpirationPlugin({ + maxEntries: 100, + maxAgeSeconds: 86400 + }), new workbox.CacheableResponsePlugin({ + statuses: [0, 200] + })] + }), 'GET'); })); diff --git a/public/image/apple-touch-icon-180x180.png b/public/image/apple-touch-icon-180x180.png index d3d92c01e5ec94a212357012ad09405ed856183a..f70f54174700ced7b4b632dd8c76f982549a53d5 100644 GIT binary patch delta 489 zcmX@W(#JAEzyAOK|3R)=DpD*nJG1f=Wl-n%KE@GS4;UES*2`#1P*$+)=4wOdR#3W>q9 zR~JM4ul$S0G1Kdv?B6fnB~q0Y*C;nze8KZ)c2)`N77IT!vr5uiZ2U~mDrMcG;Ad)9 zX?lx_pUGKetXnwwnV40U-onk#_^fi)Ex7!Q%_>iC!RItN-Wi1^iOVi_NV*xPiSf=1 zG)YyvI78B5h~8S=EwjcO2W#ik95E<8b^eYstMciy4jk)Xtbl86M6!c4m>Hao4glDpJPH z8RyO{bTn>LJ1Zh(>YQ=y%!0%u6U-e tD{l^ZaQ^bXu>1dV^biJy`G2)vtXo@-Exq`+*bNwk44$rjF6*2UngD!P-r@iN delta 540 zcmeBUIlwYOzdp!S>;M1%DpD+6RWW;4cc_#J{9s^U;4JWnEM{O}egVRaTdRYz85kHZ zdb&73`yRNMN?!2dx>W|MKqUvHfzvnIE0l(zb8T zErj^<#rx;KWxddUyMD6mId^%}`Hgltc8s-m?kr|3?o&HsDrI;)a&ZtTm zw`ZKYv(T})P3^3xl&O2hwL1$Ei<_36WtB2#&$#zyG3(|&vomHYZ`@&4Sd;P20}0MVWJF+&{CJ*|<;djEPmf;o%p@&MZI={GfWb8o-cu)C0`tVCVb)e zSz9TC=NX4$77G^lq@B@~GFqN-DrS*kamTYWvQj4L8JA)f1{SxZo#mA>Q_r{+v!JlJ z;n`WcD1+A-hjSK-Ztf{NqZehgI-~w{&LY#z9pBE#MVVx0T+Ue-y1Aw7EMJtFcE;_T z1*MxCzMZwPGI;#rkk4Xae|x@M)r*Dg=)^DMi=y_mQbM;9zsD^H#yW$itDnm{r-UW| Dx-tL= diff --git a/public/image/favicon.ico b/public/image/favicon.ico index 8fe5a934af90b36cacd3677f4c941011bae57b9d..e0db2558fb8a73aaa7c48393ec2f2567fcf0ad3f 100644 GIT binary patch delta 315 zcmV-B0mT0A0`LM4000310RS*C000312mo4<4?uqmNklU`}9C^cbV0pzOE_A@s z0kH#uAz+@yc)wkXH&3HKz&ak50FQWB0lea20q~4RZGd+?Y64osqZXi5JZb=1#-kL_ zIv#%|0EKw$1*pVh4?rm%xd63z+;LA+OKGYu{gRZGYBLDyZ M07*qoM6N<$g0mcfGynhq diff --git a/public/image/logo.svg b/public/image/logo.svg index a33474c..f11a8e5 100644 --- a/public/image/logo.svg +++ b/public/image/logo.svg @@ -1,23 +1,13 @@ + - - + - + - - - - - - - - - - diff --git a/public/image/maskable-icon-512x512.png b/public/image/maskable-icon-512x512.png index e1d0c88550dd771ec4a7c2cfc918f98431ec62c7..049d814b3289b4d225c46ea950cac46346913bd0 100644 GIT binary patch literal 1329 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&w@L)Zt|+CxDb_fKQ0)|NsAQ99i)7!R{be zEfp!2S)Ex9rZNqk=RW}za29w(7Bes~zW`yzt<^!<3=AxXJY5_^DsH{KbDEdQk%#r* z)8tS5GgT%W%?Wo;czN~abyd$vDrBK0OXZ?CfVK`SaA4qIU{qjWX4v|z8Q$Dyqk+_9Mw|ZZ zd%Mr_=dmr=JJbS=s?qx2rs3DWQih*@AJZtPu}AB(&9^Im{}v44XBcRJ$brb&F^|iE f%tA)xWm+v`)2bawoY6YlL7ww;^>bP0l+XkKl+)9l literal 1535 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&w@L)Zt|+CxDb_fKP~PkgJx86wCkr|Gz%i zedEZ2c|ExfrZPo)``!W-a29w(7Bes~zW`yzt<^!<3=FIjJY5_^DsH{KdzzP7QGnI) zkK}XtO~xB)qBfT7Z-pdlzQXo&os!*D^K z;V&aj;>34$g?sW174-~{{xWt9dCq5sSASnKeER#C;Y&XAh5ft^|IHZw-X5wPd(i{0 z%Vr<9n{A)Zw&3pYi6!C_+Ii*`-`6vr_})MCBQu|Q#(BHl@&EsP|M-)UhS?ry^o^as hl60VpIED@Pe>0h_(M=UC@dlOe44$rjF6*2UngF6>5$ON` diff --git a/public/image/pwa-192x192.png b/public/image/pwa-192x192.png index a5a5fc3b64da2a4395a3f62ebd1690fe0b57cbcf..c858a697ce12ec0830100bf47c737c80772f43f9 100644 GIT binary patch delta 612 zcmaLU-Ahwp9KiA4bG9>=n>xXl9M%r9z(7hX!I$D3YsN;yS%`FzOsX68qKv@k<(!AS zupn?^(F@iYW*KJbMP_W(StPh1a7ES-#zu;7b0oMIIP2M|f1th>pMT)HPCueu=ADJj z_LfF_NB4=w-DaaYIO9%4ybo@6o^7o)wmH)S>@K0qW@%`-v=CdcHK{5MmM>71VlTX| zaJjr)*<*D$AzqHoK8|{X$%*Mxh%RX6{*4s7n%A=rR?fT`>_(ju_+l$6Ke-5AF~^-6 zM8EkxT);t>%lE;?=DXKckcAu&@R&%u5`*C3bGe`cm8VOfgGKJxtZIgw#~xFTE7gl+ zzQPyCqif^=IK~HPbd#yQD3jU2 zxCPp}8iq2t7~jg&G9!ZCx+YSmeu+wAK;q67PYVTQKiI+pP00p@kMybZ}-jj zQ$e`_oUEpOqYs9N7EhUAGx-ZGXR3W6i4Lakf}rFY0up78pM!j&W@~J+ygb}~{SVa+36B5( delta 689 zcmYkxOGp%9902hDw=<)wuDYlYK4&5`vmkGsWX2b+_|}aKE0$63|o15-ew+ z!@a?s57I~vKc)#y?Z?M41WinF560lD$l$dLa7XzEO?;xwT}y2dGfZ2<^qvazNK6qH zOXxbe70USVepf9rlVm((rS!fEn3KdHVXXw}ls{nM6Z+kG)Fv_EDK;$KlZ_sW$+pEv zx<$4?1+R0u@=yce@GwiI`?BGiNZZyTp+)gSvl{1gZ)kQ&0iKqEwOiFFO1_A@0u1*; zP0}w);fC#L#_p-sG|BsrNiO4;fq22FGTa+gO3*J$I>Qdn*uAXguk3&}l85bqXu+%^ z?wu5&-D9b8WdN@PPI9ACkk-wjr^*?;6+qm$8ms@MY7P66#_m_?iSItSW7oUh$l%ps zC{-A^#j}EYfLb99Flp5}{mrOdOcNFyv_bBMB0iFH4M@mH&f~XMdfwX%Gh(Q)>Hvch z0*!nU=kBDINFAPFb@Toj^iWK-E%eZpavPNJ5hhnBx=K>!FXz!9lb-9k- zYo%u79#l^T@cTfva9xe%MpSL@ilph<<-zQ8py#AUxT(hI*Lix==YWsol+dKo`kzPZ z=cyTmMcbqVABwXlqVF*=r2;z6Nbucj{#t*ysUv#ii>I*W1g%hdiKv?4a) diff --git a/public/image/pwa-512x512.png b/public/image/pwa-512x512.png index 73730af58607315ecfd288f2f03a9d0c9f860eea..5452d3a3d317a0c302cae55512eb12a59e39cbbf 100644 GIT binary patch literal 1503 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&w@L)Zt|+CxDbtfKQ04PiA3|tCors%Z(!o zzCPGJt20YHaqD5AEMrNKUoeBivm0qZ4rhT!WHAE+^9vAW+*%!!&A`B#=IP=XQgQ3; z-IKfr40u>J#=P49G$irB$pY&QZT0f)Gm(I6S#$!>7%bp{1%m_wTLWXl08?(!ALR^=F!;~SFz?Q@Tg96{oMqVZn_1vJzr!AT zhL8Ukj^N@{GJO44%JB1FA;Yijj4$r9EvT1n_?J7%8A@RQ%+GQE{p;lONh)IC1p+d| mf{)f^)oX?sNag0u_1~DX`K)Xo=(u%(+~Mi!=d#Wzp$P!45KWr^ literal 1622 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&w@L)Zt|+CxDbtfKQ04PiA3|tCors%Z(!o zzCPGJuP66&b%|rr`Da%>efaYKUa_kJu2N(<(c&I>C)NWqC zhtZ*);R`!q;ym+({k#tU%^3dPX84jn${7sfijXpuB{{Qu2a@pvCSQ_5){- bK;2g9uYU?k@>Mq$f>e3B`njxgN@xNA6OFbN diff --git a/public/image/pwa-64x64.png b/public/image/pwa-64x64.png index 9e2f0d5551f447b59509eedb400b4744be1b2fbe..fcd940cfc74105c15141d4a309b4785a72c82f62 100644 GIT binary patch delta 236 zcmcc2w32CpinLIGPl&5eX5rTdyKfv>pd!T*Zd)%p#dE{-7;x87bc zkz)+wXIS6gaFhMO+x!K#&g^V@Z$oPu ycGR_eO=Cbdz>OFaW*20hW&ER?!1$RVc{hU^gUpS8U#%?|fWXt$&t;ucLK6U{AY^&~ delta 278 zcmV+x0qOp!0@DJJBq113OjJcoX>lYP1X4vR_29eM#Gt8|d69u-R!J^%B_wN+KP7+E zNkl_q@dtaH*#-OrFlQ`acf3vl zS)T!Ep8$Cu14JJJOdkPM9{^nM17z<4Z0`Yd?*M#{0ilP0(j!3X0ig9eAod%e_A4Ow z3!wKiQ0OP1(vLu?e*x`1vyPs(Pc>=)c>RWFB#`wPkoF0X_c1{9A;9zzK=lE@^*%uM zF2MF4K=%&7_ZSd*2q--Qq#giTzXM{w0cyVja=!q2KLdq+0xJCol=?Q^1^h2)EKu78 cd { + if (event.data && event.data.type === 'CACHE_KEYS') { + // 获取所有缓存键 + caches.keys().then((cacheNames) => { + event.ports[0].postMessage({ cacheNames }); + }); + } else if (event.data && event.data.type === 'CACHE_CONTENT') { + // 获取特定缓存的内容 + const cacheName = event.data.cacheName; + caches.open(cacheName).then((cache) => { + cache.keys().then((requests) => { + const urls = requests.map(request => request.url); + event.ports[0].postMessage({ cacheName, urls }); + }); + }); + } else if (event.data && event.data.type === 'CLEAR_CACHE') { + // 清除特定缓存 + const cacheName = event.data.cacheName; + caches.delete(cacheName).then((success) => { + event.ports[0].postMessage({ success, cacheName }); + }); + } else if (event.data && event.data.type === 'CLEAR_URL') { + // 清除特定URL的缓存 + const cacheName = event.data.cacheName; + const url = event.data.url; + caches.open(cacheName).then((cache) => { + cache.delete(url).then((success) => { + event.ports[0].postMessage({ success, cacheName, url }); + }); + }); + } else if (event.data && event.data.type === 'CLEAR_ALL_CACHES') { + // 清除所有缓存 + caches.keys().then((cacheNames) => { + Promise.all( + cacheNames.map(name => caches.delete(name)) + ).then(() => { + event.ports[0].postMessage({ success: true }); + }); + }); + } +}); + +console.log('Cache Manager extension loaded'); \ No newline at end of file diff --git a/src/components/CacheManager.vue b/src/components/CacheManager.vue new file mode 100644 index 0000000..2143d78 --- /dev/null +++ b/src/components/CacheManager.vue @@ -0,0 +1,238 @@ + + + \ No newline at end of file diff --git a/src/components/settings/cards/DataProviderSettingsCard.vue b/src/components/settings/cards/DataProviderSettingsCard.vue index 7a2029a..d05c433 100644 --- a/src/components/settings/cards/DataProviderSettingsCard.vue +++ b/src/components/settings/cards/DataProviderSettingsCard.vue @@ -9,11 +9,7 @@ 检查服务器连接 @@ -27,9 +23,7 @@ 清除数据库缓存 - 这将清除所有IndexedDB中的数据 + 这将清除所有IndexedDB中的数据 + + + 查看本地缓存 + + @@ -55,12 +60,8 @@ {{ confirmMessage }} - 取消 - 确认 + 取消 + 确认 diff --git a/src/pages/CacheManagement.vue b/src/pages/CacheManagement.vue new file mode 100644 index 0000000..132d0af --- /dev/null +++ b/src/pages/CacheManagement.vue @@ -0,0 +1,22 @@ + + + \ No newline at end of file diff --git a/src/sw.js b/src/sw.js new file mode 100644 index 0000000..d1fddb4 --- /dev/null +++ b/src/sw.js @@ -0,0 +1,141 @@ +import { precacheAndRoute, cleanupOutdatedCaches } from 'workbox-precaching' +import { registerRoute, setCatchHandler } from 'workbox-routing' +import { CacheFirst, NetworkFirst, StaleWhileRevalidate } from 'workbox-strategies' +import { ExpirationPlugin } from 'workbox-expiration' +import { CacheableResponsePlugin } from 'workbox-cacheable-response' + +// 使用 self.__WB_MANIFEST 是 workbox 的一个特殊变量,会被实际的预缓存清单替换 +precacheAndRoute(self.__WB_MANIFEST) +cleanupOutdatedCaches() + +// JS 文件缓存 +registerRoute( + /\.(?:js)$/i, + new StaleWhileRevalidate({ + cacheName: 'js-cache', + plugins: [ + new ExpirationPlugin({ + maxEntries: 100, + maxAgeSeconds: 60 * 60 * 24 * 7 // 7 天 + }) + ] + }) +) + +// CSS 文件缓存 +registerRoute( + /\.(?:css)$/i, + new StaleWhileRevalidate({ + cacheName: 'css-cache', + plugins: [ + new ExpirationPlugin({ + maxEntries: 50, + maxAgeSeconds: 60 * 60 * 24 * 7 // 7 天 + }) + ] + }) +) + +// HTML 文件缓存 +registerRoute( + /\.(?:html)$/i, + new NetworkFirst({ + cacheName: 'html-cache', + plugins: [ + new ExpirationPlugin({ + maxEntries: 20, + maxAgeSeconds: 60 * 60 * 24 // 1 天 + }) + ] + }) +) + +// 图片缓存 +registerRoute( + /\.(?:png|jpg|jpeg|svg|gif)$/i, + new StaleWhileRevalidate({ + cacheName: 'images-cache', + plugins: [ + new ExpirationPlugin({ + maxEntries: 50, + maxAgeSeconds: 60 * 60 * 24 * 30 // 30 天 + }) + ] + }) +) + +// CDN 缓存 +registerRoute( + /\/cdn-cgi\/.*/i, + new NetworkFirst({ + cacheName: 'cdn-cgi-cache', + plugins: [ + new ExpirationPlugin({ + maxEntries: 50, + maxAgeSeconds: 60 * 60 * 24 // 1 天 + }) + ], + networkTimeoutSeconds: 10 + }) +) + +// 外部资源缓存 +registerRoute( + ({ url }) => url.origin !== self.location.origin, + new NetworkFirst({ + cacheName: 'external-resources', + plugins: [ + new ExpirationPlugin({ + maxEntries: 100, + maxAgeSeconds: 60 * 60 * 24 // 1 天 + }), + new CacheableResponsePlugin({ + statuses: [0, 200] + }) + ], + networkTimeoutSeconds: 10 + }) +) + +// 添加缓存管理消息处理 +self.addEventListener('message', (event) => { + if (event.data && event.data.type === 'CACHE_KEYS') { + // 获取所有缓存键 + caches.keys().then((cacheNames) => { + event.ports[0].postMessage({ cacheNames }); + }); + } else if (event.data && event.data.type === 'CACHE_CONTENT') { + // 获取特定缓存的内容 + const cacheName = event.data.cacheName; + caches.open(cacheName).then((cache) => { + cache.keys().then((requests) => { + const urls = requests.map(request => request.url); + event.ports[0].postMessage({ cacheName, urls }); + }); + }); + } else if (event.data && event.data.type === 'CLEAR_CACHE') { + // 清除特定缓存 + const cacheName = event.data.cacheName; + caches.delete(cacheName).then((success) => { + event.ports[0].postMessage({ success, cacheName }); + }); + } else if (event.data && event.data.type === 'CLEAR_URL') { + // 清除特定URL的缓存 + const cacheName = event.data.cacheName; + const url = event.data.url; + caches.open(cacheName).then((cache) => { + cache.delete(url).then((success) => { + event.ports[0].postMessage({ success, cacheName, url }); + }); + }); + } else if (event.data && event.data.type === 'CLEAR_ALL_CACHES') { + // 清除所有缓存 + caches.keys().then((cacheNames) => { + Promise.all( + cacheNames.map(name => caches.delete(name)) + ).then(() => { + event.ports[0].postMessage({ success: true }); + }); + }); + } +}); \ No newline at end of file diff --git a/vite.config.mjs b/vite.config.mjs index 30c5d86..2570a60 100644 --- a/vite.config.mjs +++ b/vite.config.mjs @@ -19,15 +19,102 @@ export default defineConfig({ Layouts(), Vue({ template: { transformAssetUrls } - }), VitePWA({ + }), + VitePWA({ registerType: 'autoUpdate', devOptions: { - navigateFallback: '/index.html', // 离线支持(navigateFallback) + navigateFallback: '/', enabled: true, - suppressWarnings: true, // 是否抑制 Workbox 的警告 + suppressWarnings: true, + }, + + lang: 'zh-CN', + injectRegister: 'auto', + strategies: 'generateSW', + workbox: { + globPatterns: ['**/*.{js,css,html,png,svg,jpg,jpeg,gif,ico,woff,woff2,ttf,eot}'], + navigateFallback: '/', + runtimeCaching: [ + { + urlPattern: /\.(?:js)$/i, + handler: 'StaleWhileRevalidate', + options: { + cacheName: 'js-cache', + expiration: { + maxEntries: 100, + maxAgeSeconds: 60 * 60 * 24 * 7 // 7 天 + } + } + }, + { + urlPattern: /\.(?:css)$/i, + handler: 'StaleWhileRevalidate', + options: { + cacheName: 'css-cache', + expiration: { + maxEntries: 50, + maxAgeSeconds: 60 * 60 * 24 * 7 // 7 天 + } + } + }, + { + urlPattern: /\.(?:html)$/i, + handler: 'NetworkFirst', + options: { + cacheName: 'html-cache', + expiration: { + maxEntries: 20, + maxAgeSeconds: 60 * 60 * 24 // 1 天 + } + } + }, + { + urlPattern: /\.(?:png|jpg|jpeg|svg|gif)$/i, + handler: 'StaleWhileRevalidate', + options: { + cacheName: 'images-cache', + expiration: { + maxEntries: 50, + maxAgeSeconds: 60 * 60 * 24 * 30 // 30 天 + } + } + }, + { + urlPattern: /\/cdn-cgi\/.*/i, + handler: 'NetworkFirst', + options: { + cacheName: 'cdn-cgi-cache', + expiration: { + maxEntries: 50, + maxAgeSeconds: 60 * 60 * 24 // 1 天 + }, + networkTimeoutSeconds: 10 + } + }, + { + // 匹配除了当前域名以外的所有请求 + urlPattern: ({ url }) => { + return url.origin !== self.location.origin; + }, + handler: 'NetworkFirst', + options: { + cacheName: 'external-resources', + expiration: { + maxEntries: 100, + maxAgeSeconds: 60 * 60 * 24 // 1 天 + }, + networkTimeoutSeconds: 10, + cacheableResponse: { + statuses: [0, 200] + } + } + } + ], + additionalManifestEntries: [], + clientsClaim: true, + skipWaiting: true, + importScripts: ['sw-cache-manager.js'] }, - - lang: 'zh-CN', manifest: { name: 'Classworks作业板', short_name: 'Classworks', @@ -39,18 +126,6 @@ export default defineConfig({ edge_side_panel: { default_path: '/', }, - workbox: { - globPatterns: ['**/*.{js,css,html,png,svg}'], - navigateFallback: '/index.html', // 离线支持(navigateFallback) - runtimeCaching: [ - //所有资源都使用网络优先 - { - urlPattern: /./, - handler: 'NetworkFirst', - }, - ], - }, - icons: [ { src: '/image/pwa-64x64.png', @@ -74,7 +149,6 @@ export default defineConfig({ purpose: 'maskable' } ], - shortcuts: [ { name: '随机点名',