98 行
3.2 KiB
JavaScript
98 行
3.2 KiB
JavaScript
'use strict'
|
|
|
|
// Service Worker 配置 - 默认值
|
|
let config = {
|
|
cdnUrl: 'https://cdn.fillcode.com/',
|
|
serviceWorkerUrl: '/__static/sw-cdn.js',
|
|
staticRegex: /\.(js|css|png|jpg|jpeg|gif|svg|webp|woff|woff2|ttf|ico)$/,
|
|
debug: true,
|
|
}
|
|
|
|
// 监听配置更新消息
|
|
self.addEventListener('message', e => {
|
|
if (e.data.type !== 'CONFIG') return
|
|
|
|
config = e.data.config
|
|
|
|
if (config.debug) console.log('PWA-CDN: Config updated', config)
|
|
})
|
|
|
|
// 拦截网络请求
|
|
self.addEventListener('fetch', e => {
|
|
const url = new URL(e.request.url)
|
|
|
|
// 如果请求不是GET方法,直接返回
|
|
if (e.request.method !== 'GET') return
|
|
|
|
// 如果请求的域名不是当前页面的域名
|
|
if (url.origin !== self.location.origin) return
|
|
|
|
// 过滤__static路径下的请求
|
|
if (url.pathname.startsWith('/__static/')) return
|
|
|
|
// 如果请求的路径不匹配静态资源正则表达式,直接返回
|
|
if (!config.staticRegex.test(url.pathname)) return
|
|
|
|
// 判断是否是强制需要同源请求
|
|
const requiresSameOrigin = ['worker', 'sharedworker', 'serviceworker'].includes(e.request.destination)
|
|
|
|
// 如果是强制需要同源请求的资源类型,直接返回
|
|
if (requiresSameOrigin) return
|
|
|
|
// 开始处理静态资源请求
|
|
e.respondWith(handleStaticResource(e.request, url))
|
|
})
|
|
|
|
// 处理静态资源请求
|
|
async function handleStaticResource(request, url) {
|
|
// 生成CDN子路径
|
|
const hostname = self.location.hostname
|
|
const cdnPath = hostname.replace(/\./g, '-')
|
|
|
|
const targetUrl = config.cdnUrl + cdnPath + url.pathname + url.search
|
|
|
|
if (config.debug) console.log('PWA-CDN:', url.href, '->', targetUrl)
|
|
|
|
try {
|
|
// 创建新请求,保留原始缓存策略
|
|
const newRequest = new Request(targetUrl, {...request, mode: 'cors'})
|
|
|
|
// 请求目标域名,浏览器会自动处理缓存
|
|
const response = await fetch(newRequest)
|
|
|
|
if (!response.ok) throw new Error('Target domain response not ok: ' + response.status)
|
|
|
|
// 修复重定向问题
|
|
if([301, 302, 307, 308].includes(response.status)) {
|
|
const location = response.headers.get('location')
|
|
|
|
// 如果重定向的地址不是CDN地址,或者已经包含了CDN子路径,则返回原始响应
|
|
if(!location?.startsWith('/') || location.startsWith(`/${cdnPath}`)) return response
|
|
|
|
// 否则,重定向到新的CDN地址
|
|
const redirectUrl = new URL(location, config.cdnUrl + cdnPath)
|
|
|
|
if (config.debug) console.log('PWA-CDN: Redirecting to', redirectUrl.href)
|
|
return Response.redirect(redirectUrl.href, response.status)
|
|
}
|
|
|
|
return response
|
|
} catch (error) {
|
|
if (config.debug) console.warn('PWA-CDN: Fallback to original request for', url.href, error)
|
|
|
|
// 失败时回退到原始请求
|
|
return fetch(request)
|
|
}
|
|
}
|
|
|
|
// Service Worker 生命周期
|
|
self.addEventListener('install', () => {
|
|
if (config.debug) console.log('PWA-CDN: Service Worker installing')
|
|
self.skipWaiting().catch(console.error)
|
|
})
|
|
|
|
self.addEventListener('activate', () => {
|
|
if (config.debug) console.log('PWA-CDN: Service Worker activated')
|
|
self.clients.claim().catch(console.error)
|
|
})
|