@@ -51,7 +51,7 @@ workbox.precaching.precacheAndRoute(self.__WB_MANIFEST, {
51
51
52
52
// CDN
53
53
workbox . routing . registerRoute (
54
- / \. (?: j s | c s s ) $ / ,
54
+ / \. (?: j s | c s s | j s o n ) $ / ,
55
55
new workbox . strategies . StaleWhileRevalidate ( {
56
56
cacheName : 'assets' ,
57
57
plugins : [
@@ -87,13 +87,13 @@ workbox.routing.registerRoute(
87
87
) ;
88
88
89
89
// Catch routing errors, like if the user is offline
90
- // setCatchHandler(async ({ event }) => {
91
- // // Return the precached offline page if a document is being requested
92
- // if (event.request.destination === 'document') {
93
- // return matchPrecache('/404.html');
94
- // }
95
- // return Response.error();
96
- // });
90
+ workbox . routing . setCatchHandler ( async ( { event } ) => {
91
+ // Return the precached offline page if a document is being requested
92
+ if ( event . request . destination === 'document' ) {
93
+ return matchPrecache ( '/404.html' ) ;
94
+ }
95
+ return Response . error ( ) ;
96
+ } ) ;
97
97
98
98
// Fonts
99
99
// workbox.routing.registerRoute(
@@ -152,8 +152,143 @@ workbox.routing.registerRoute(
152
152
// })
153
153
// );
154
154
155
+ workbox . precaching . cleanupOutdatedCaches ( ) ;
155
156
157
+ // workbox.googleAnalytics.initialize();
156
158
157
- workbox . precaching . cleanupOutdatedCaches ( ) ;
159
+ const cdn = {
160
+ gh : {
161
+ jsdelivr : 'https://cdn.jsdelivr.net/gh' ,
162
+ fastly : 'https://fastly.jsdelivr.net/gh' ,
163
+ gcore : 'https://gcore.jsdelivr.net/gh' ,
164
+ testingcf : 'https://testingcf.jsdelivr.net/gh' ,
165
+ test1 : 'https://test1.jsdelivr.net/gh' ,
166
+ tianli : 'https://cdn1.tianli0.top/gh'
167
+ } ,
168
+ combine : {
169
+ jsdelivr : 'https://cdn.jsdelivr.net/combine' ,
170
+ fastly : 'https://fastly.jsdelivr.net/combine' ,
171
+ gcore : 'https://gcore.jsdelivr.net/combine' ,
172
+ testingcf : 'https://testingcf.jsdelivr.net/combine' ,
173
+ test1 : 'https://test1.jsdelivr.net/combine' ,
174
+ tianli : 'https://cdn1.tianli0.top/combine'
175
+ } ,
176
+ npm : {
177
+ jsdelivr : 'https://cdn.jsdelivr.net/npm' ,
178
+ fastly : 'https://fastly.jsdelivr.net/npm' ,
179
+ gcore : 'https://gcore.jsdelivr.net/npm' ,
180
+ testingcf : 'https://testingcf.jsdelivr.net/npm' ,
181
+ test1 : 'https://test1.jsdelivr.net/npm' ,
182
+ eleme : 'https://npm.elemecdn.com' ,
183
+ unpkg : 'https://unpkg.com' ,
184
+ tianli : 'https://cdn1.tianli0.top/npm'
185
+ }
186
+ }
187
+
188
+ // self.addEventListener('install', async () => {
189
+ // await self.skipWaiting()
190
+ // })
191
+
192
+ // self.addEventListener('activate', async () => {
193
+ // await self.clients.claim()
194
+ // })
195
+
196
+ self . addEventListener ( 'fetch' , async ( event ) => {
197
+ try {
198
+ // 如果用户当前网速慢,或是开启了省流模式,则不使用sw处理请求
199
+ const nav = navigator
200
+ const { saveData, effectiveType } = nav . connection || nav . mozConnection || nav . webkitConnection || { }
201
+ if ( saveData || / 2 g / . test ( effectiveType ) ) return
202
+
203
+ // 劫持请求
204
+ event . respondWith ( handleRequest ( event . request ) )
205
+ // eslint-disable-next-line
206
+ } catch ( e ) { }
207
+ } )
208
+
209
+ // 返回响应
210
+ async function progress ( res ) {
211
+ return new Response ( await res . arrayBuffer ( ) , {
212
+ status : res . status ,
213
+ headers : res . headers
214
+ } )
215
+ }
216
+
217
+ function handleRequest ( req ) {
218
+ const urls = [ ]
219
+ const urlStr = req . url
220
+ let urlObj = new URL ( urlStr )
221
+ // 为了获取 cdn 类型
222
+ // 例如获取gh (https://cdn.jsdelivr.net/gh)
223
+ const path = urlObj . pathname . split ( '/' ) [ 1 ]
158
224
159
- // workbox.googleAnalytics.initialize();
225
+ // 匹配 cdn
226
+ for ( const type in cdn ) {
227
+ if ( type === path ) {
228
+ for ( const key in cdn [ type ] ) {
229
+ const url = cdn [ type ] [ key ] + urlObj . pathname . replace ( '/' + path , '' )
230
+ urls . push ( url )
231
+ }
232
+ }
233
+ }
234
+
235
+ // 如果上方 cdn 遍历 匹配到 cdn 则直接统一发送请求
236
+ if ( urls . length ) return fetchAny ( urls )
237
+ throw new Error ( 'failure' )
238
+ }
239
+
240
+ // Promise.any 的 polyfill
241
+ function createPromiseAny ( ) {
242
+ Promise . any = function ( promises ) {
243
+ return new Promise ( ( resolve , reject ) => {
244
+ promises = Array . isArray ( promises ) ? promises : [ ]
245
+ let len = promises . length
246
+ let errs = [ ]
247
+ if ( len === 0 ) return reject ( new AggregateError ( 'All promises were rejected' ) )
248
+ promises . forEach ( ( p ) => {
249
+ if ( p instanceof Promise ) {
250
+ p . then (
251
+ ( res ) => resolve ( res ) ,
252
+ ( err ) => {
253
+ len --
254
+ errs . push ( err )
255
+ if ( len === 0 ) reject ( new AggregateError ( errs ) )
256
+ }
257
+ )
258
+ } else {
259
+ reject ( p )
260
+ }
261
+ } )
262
+ } )
263
+ }
264
+ }
265
+
266
+ // 发送所有请求
267
+ function fetchAny ( urls ) {
268
+ // 中断一个或多个请求
269
+ const controller = new AbortController ( )
270
+ const signal = controller . signal
271
+
272
+ // 遍历将所有的请求地址转换为promise
273
+ const PromiseAll = urls . map ( ( url ) => {
274
+ return new Promise ( ( resolve , reject ) => {
275
+ fetch ( url , { signal } )
276
+ . then ( progress )
277
+ . then ( ( res ) => {
278
+ const r = res . clone ( )
279
+ if ( r . status !== 200 ) reject ( null )
280
+ controller . abort ( ) // 中断
281
+ resolve ( r )
282
+ } )
283
+ . catch ( ( ) => reject ( null ) )
284
+ } )
285
+ } )
286
+
287
+ // 判断浏览器是否支持 Promise.any
288
+ if ( ! Promise . any ) createPromiseAny ( )
289
+
290
+ // 谁先返回"成功状态"则返回谁的内容,如果都返回"失败状态"则返回null
291
+ return Promise . any ( PromiseAll )
292
+ . then ( ( res ) => res )
293
+ . catch ( ( ) => null )
294
+ }
0 commit comments