Ksable' 小屋

ホーム留言板
友達ブログについて

# 碎碎念: 2025-07-05

发表于 2025-07-05 15:45
更新于 2025-07-05 17:16
1082 字
6 min read

kissablecho

kissablecho 的个人博客 / 记录生活，分享技术 / 喜欢二次元和白丝。

128 記事

4 カテゴリー

7 タグ
ホーム
留言板
カテゴリー
タグ
アーカイブ
友達
ブログについて
一些实用的网站
astro-koharu 使用指南
音楽
碎碎念: 26-02-25 碎碎念: 26-02-22 碎碎念: 26-02-20 碎碎念: 26-02-18-2 碎碎念: 26-02-18 碎碎念: 26-02-17 碎碎念: 26-02-15 碎碎念: 26-02-14 碎碎念: 26-01-16 朋友、人际交往碎碎念: 26-01-01 2025年，年度回顾碎碎念: 2025-10-19 碎碎念: 2025-10-17 (补)碎碎念: 2025-10-13 (补、密码保护)碎碎念: 请原谅内向的我碎碎念: 2025-09-23 碎碎念: 完美移植 PureSuck 主题碎碎念: 2025-07-16 碎碎念: 2025-07-05 碎碎念: 2025-06-13 碎碎念: 2025-06-09 碎碎念: 2025-05-18 一张傍晚的照片碎碎念: 2025-05-05 碎碎念: 2025-04-30 碎碎念: 2025-04-20 碎碎念: 2025-04-19 碎碎念: 2025-04-13 碎碎念: 2025-03-09-2 碎碎念: 2025-03-09 碎碎念: 我太懒了，连个年终总结都没写碎碎念: 2024-11-17 碎碎念: 2024-10-8 至 2024-10-18 碎碎念: 2024-09-29 碎碎念: 2024-09-24 碎碎念: 2024-09-23 碎碎念: 2024-10-05 碎碎念: 2024-10-03 喝上了芋泥啵啵奶绿碎碎念: 2024-10-03 愿世界永无战事碎碎念: 2024-09-15 碎碎念: 2024-09-01 碎碎念: 2024-08-29 谁动我歌单？碎碎念: 2024-08-29 我抑郁症？碎碎念: 2024-08-29 碎碎念: 2024-08-26 碎碎念: 2024-08-22 碎碎念: 2024-08-18 碎碎念: 2024-08-11 碎碎念: 2024-08-08 碎碎念: 2024-08-06 梦碎碎念: 2024-08-06 碎碎念: 2024-08-04 碎碎念: 2024-07-21 碎碎念: 2024-07-13 碎碎念: 2024-07-08 碎碎念: 2024-07-03 碎碎念: 2024-07-02 碎碎念: 2024-07-01 碎碎念: 2024-06-30 碎碎念: 2024-06-28 碎碎念: 2024-06-27 碎碎念: 2024-06-26 碎碎念: 2024-06-22 碎碎念: 2024-06-20 碎碎念: 2024-06-18 碎碎念: 2024-06-17 碎碎念: 2024-06-15 碎碎念: 2024-06-14 碎碎念: 2024 年的高三喊楼碎碎念: 2024-06-06 碎碎念: 2024-05-30 二碎碎念: 2024-05-30 一碎碎念: 2024-05-27 碎碎念: 2024-05-26 碎碎念: 2024-05-23 碎碎念: 2024-05-22 碎碎念: 2024-05-19 碎碎念: 2024-05-17 碎碎念: 2024-05-14 碎碎念: 2024-05-13 碎碎念: 2024-05-12 碎碎念: 2024-05-10 碎碎念: 2024-05-08 碎碎念: 2024-05-06 碎碎念: 2024-05-05 M:8 三碎碎念: 2024-05-05 碎碎念: 2024-05-05 M:7 二碎碎念: 2024-05-05 M:7 一碎碎念: 2024-05-02 星期四 M:3 小雨碎碎念: 生日碎碎念: 2024-04-29 M:7 碎碎念: 2024-04-27 M:8
この投稿は「日本語」では表示できません。元の投稿を表示しています。
忙活了半天终于把网站的 Service Worker 缓存配置给弄好了。 之前(一直)觉得网站的速度不够快，总要等好几秒才加载完，背景图总是卡下才加载好。我已经尽自己能力把网络加载速度弄到最大了，首次加载已经做到最快加载了。也把我能控制地资源全加上了 cache-control 响应头，但第二次打开总有些图片啊、js啊没缓存，比如图片的白一下才显示出来。 今天就去折腾 Service Wor...

忙活了半天终于把网站的 Service Worker 缓存配置给弄好了。（暑假放假的第一天就折腾这些，下个月我就是高三学生了）

之前(一直)觉得网站的速度不够快，总要等好几秒才加载完，背景图总是卡下才加载好。我已经尽自己能力把网络加载速度弄到最大了（在不换主题不删功能的条件下），首次加载已经做到最快加载了。也把我能控制地资源全加上了 cache-control 响应头，但第二次打开总有些图片啊、js 啊没缓存，比如图片的白一下才显示出来。

今天就去折腾 Service Worker 了，使得博客的访问速度德到大大的提升，虽然不知为何有时图片等突然变得加载很慢，但总的来说比之前快了不少。

Service Worker 的代码我贴在这了，可以用作参考。

    const swconfig = {
        CACHE_VERSION: "v2.0",
        runtimeCaching: [
            // {
            //     urlPattern: /^https:\/\/cdn\.example\.com\/.*/,
            //     handler: "CacheFirst",
            //     maxAgeSeconds: 60 * 60 * 24 * 365
            // },
            // {
            //     urlPattern: /https:\/\/blog.ksable.top\//gi,
            //     handler: "NetworkFirst",
            //     maxAgeSeconds: 60 * 60 * 24 * 7
            // },
            {
                urlPattern: RegExp('^https://www.favicon.vip/get.php'),
                handler: "CacheFirst",
                maxAgeSeconds: 60 * 60 * 24 * 365
            },
            {
                urlPattern: RegExp('^https://image.thum.io/'),
                handler: "CacheFirst",
                maxAgeSeconds: 60 * 60 * 24 * 30
            },
            {
                urlPattern: /https?:\/\/[^\/]+\/.*\.(png|jpg|jpeg|gif|svg|ico|woff2|ttf|js|css?)(\?.*)?/,
                handler: "CacheFirst",
                maxAgeSeconds: 60 * 60 * 24 * 365
            },
            {
                urlPattern: /^https:\/\/ik.imagekit.io\//,
                handler: "CacheFirst",
                maxAgeSeconds: 0
            },
            {
                urlPattern: /^https:\/\/weavatar.com\/avatar\//,
                handler: "CacheFirst",
                maxAgeSeconds: 60 * 60 * 24 * 30
            },
            {
                urlPattern: /^https:\/\/assets.ksable.top\/js\/my-js.js/,
                handler: "CacheFirst",
                maxAgeSeconds: 60 * 60 * 24 * 1
            }
        ],
        exclude: [
            /^https:\/\/blog.ksable.top\/sw.js/gi
        ],
        precacheUrls: [
            '/content.json',   // 预缓存的内容JSON文件
            '/offline.html'    // 离线页面
        ]
    };

    const CACHE_NAME = `${swconfig.CACHE_VERSION}-cache`;
    const CACHE_META_KEY = 'cache-meta';
    const OFFLINE_URL = '/offline.html';

    // 匹配请求对应的规则
    function matchRule(request) {
        const url = request.url;

        // 检查排除规则
        for (const pattern of swconfig.exclude) {
            if (pattern.test(url)) return null;
        }

        // 反向遍历确保后面的规则优先级更高
        for (let i = swconfig.runtimeCaching.length - 1; i >= 0; i--) {
            const rule = swconfig.runtimeCaching[i];
            if (rule.urlPattern.test(url)) {
                return rule;
            }
        }

        return null;
    }

    // 获取缓存元数据
    async function getCacheMeta() {
        const cache = await caches.open(CACHE_NAME);
        const response = await cache.match(CACHE_META_KEY);
        return response ? await response.json() : {};
    }

    // 更新缓存元数据
    async function updateCacheMeta(url, timestamp) {
        const cache = await caches.open(CACHE_NAME);
        const meta = await getCacheMeta();

        meta[url] = {
            timestamp,
            cachedAt: Date.now()
        };

        await cache.put(
            CACHE_META_KEY,
            new Response(JSON.stringify(meta), {
                headers: { 'Content-Type': 'application/json' }
            })
        );
    }

    // 后台更新缓存
    async function backgroundUpdate(request, rule) {
        try {
            const cache = await caches.open(CACHE_NAME);
            const cachedResponse = await cache.match(request);

            if (!cachedResponse) return;

            // 准备验证头
            const headers = new Headers();
            const etag = cachedResponse.headers.get('ETag');
            const lastModified = cachedResponse.headers.get('Last-Modified');

            if (etag) headers.set('If-None-Match', etag);
            if (lastModified) headers.set('If-Modified-Since', lastModified);

            // 发送验证请求
            const networkResponse = await fetch(request, {
                headers,
                cache: 'no-cache'
            });

            if (networkResponse.status === 304) {  // 未修改
                await updateCacheMeta(request.url, Date.now());
            } else if (networkResponse.ok) {  // 资源已更新
                const responseClone = networkResponse.clone();
                await cache.put(request, responseClone);
                await updateCacheMeta(request.url, Date.now());
            }
        } catch (error) {
            console.error('Background update failed:', error);
        }
    }

    // 安装阶段 - 初始化缓存
    self.addEventListener('install', event => {
        event.waitUntil(
            caches.open(CACHE_NAME).then(cache => {
                // 初始化缓存元数据
                return cache.put(
                    CACHE_META_KEY,
                    new Response('{}', {
                        headers: { 'Content-Type': 'application/json' }
                    })
                ).then(() => {
                    // 预缓存关键资源
                    return cache.addAll(swconfig.precacheUrls);
                });
            }).then(() => self.skipWaiting())
        );
    });

    // 激活阶段 - 清理旧缓存
    self.addEventListener('activate', event => {
        event.waitUntil(
            caches.keys().then(cacheNames => {
                return Promise.all(
                    cacheNames.map(name => {
                        if (name !== CACHE_NAME && name.startsWith('v')) {
                            return caches.delete(name);
                        }
                    })
                );
            }).then(() => self.clients.claim())
        );
    });

    // 请求处理
    self.addEventListener('fetch', event => {
        const request = event.request;

        // 只处理GET请求
        if (request.method !== 'GET') return;

        // 特殊处理导航请求的离线回退
        if (request.mode === 'navigate') {
            event.respondWith(
                (async () => {
                    try {
                        // 首先尝试网络请求
                        const networkResponse = await fetch(request);
                        return networkResponse;
                    } catch (error) {
                        // 网络失败时返回离线页面
                        const offlineResponse = await caches.match(OFFLINE_URL);
                        if (offlineResponse) {
                            return offlineResponse;
                        }
                        // 如果离线页面也未缓存，返回简单错误响应
                        return new Response('Offline', {
                            status: 503,
                            statusText: 'Service Unavailable'
                        });
                    }
                })()
            );
            return;
        }
        // 匹配缓存规则
        const rule = matchRule(request);
        if (!rule) return;

        // 处理不同缓存策略
        switch (rule.handler) {
            case 'NetworkOnly':
                event.respondWith(fetch(request));
                break;

            case 'CacheOnly':
                event.respondWith(
                    caches.match(request).then(response => response || Response.error())
                );
                break;

            case 'NetworkFirst':
                event.respondWith(
                    fetch(request).catch(() => caches.match(request))
                );
                break;

            case 'CacheFirst':
            default:
                event.respondWith((async () => {
                    const cache = await caches.open(CACHE_NAME);
                    const cachedResponse = await cache.match(request);
                    const meta = await getCacheMeta();
                    const url = request.url;
                    const metaEntry = meta[url];

                    // 如果找到缓存
                    if (cachedResponse) {
                        // 检查是否需要后台更新
                        if (rule.maxAgeSeconds > 0 && metaEntry) {
                            const age = (Date.now() - metaEntry.cachedAt) / 1000;
                            if (age > rule.maxAgeSeconds) {
                                // 后台更新不影响当前响应
                                event.waitUntil(backgroundUpdate(request, rule));
                            }
                        }
                        return cachedResponse;
                    }

                    // 没有缓存则请求网络
                    try {
                        const networkResponse = await fetch(request);
                        if (networkResponse.ok) {
                            const responseClone = networkResponse.clone();
                            await cache.put(request, responseClone);
                            await updateCacheMeta(url, Date.now());
                        }
                        return networkResponse;
                    } catch (error) {
                        return Response.error();
                    }
                })());
                break;
        }
    });

気に入ったら、コメントを残してね～

日本語
中文 English 日本語

kissablecho

kissablecho 的个人博客 / 记录生活，分享技术 / 喜欢二次元和白丝。

128 記事

4 カテゴリー

7 タグ
ホーム
留言板
カテゴリー
タグ
アーカイブ
友達
ブログについて
一些实用的网站
astro-koharu 使用指南
音楽
碎碎念: 26-02-25 碎碎念: 26-02-22 碎碎念: 26-02-20 碎碎念: 26-02-18-2 碎碎念: 26-02-18 碎碎念: 26-02-17 碎碎念: 26-02-15 碎碎念: 26-02-14 碎碎念: 26-01-16 朋友、人际交往碎碎念: 26-01-01 2025年，年度回顾碎碎念: 2025-10-19 碎碎念: 2025-10-17 (补)碎碎念: 2025-10-13 (补、密码保护)碎碎念: 请原谅内向的我碎碎念: 2025-09-23 碎碎念: 完美移植 PureSuck 主题碎碎念: 2025-07-16 碎碎念: 2025-07-05 碎碎念: 2025-06-13 碎碎念: 2025-06-09 碎碎念: 2025-05-18 一张傍晚的照片碎碎念: 2025-05-05 碎碎念: 2025-04-30 碎碎念: 2025-04-20 碎碎念: 2025-04-19 碎碎念: 2025-04-13 碎碎念: 2025-03-09-2 碎碎念: 2025-03-09 碎碎念: 我太懒了，连个年终总结都没写碎碎念: 2024-11-17 碎碎念: 2024-10-8 至 2024-10-18 碎碎念: 2024-09-29 碎碎念: 2024-09-24 碎碎念: 2024-09-23 碎碎念: 2024-10-05 碎碎念: 2024-10-03 喝上了芋泥啵啵奶绿碎碎念: 2024-10-03 愿世界永无战事碎碎念: 2024-09-15 碎碎念: 2024-09-01 碎碎念: 2024-08-29 谁动我歌单？碎碎念: 2024-08-29 我抑郁症？碎碎念: 2024-08-29 碎碎念: 2024-08-26 碎碎念: 2024-08-22 碎碎念: 2024-08-18 碎碎念: 2024-08-11 碎碎念: 2024-08-08 碎碎念: 2024-08-06 梦碎碎念: 2024-08-06 碎碎念: 2024-08-04 碎碎念: 2024-07-21 碎碎念: 2024-07-13 碎碎念: 2024-07-08 碎碎念: 2024-07-03 碎碎念: 2024-07-02 碎碎念: 2024-07-01 碎碎念: 2024-06-30 碎碎念: 2024-06-28 碎碎念: 2024-06-27 碎碎念: 2024-06-26 碎碎念: 2024-06-22 碎碎念: 2024-06-20 碎碎念: 2024-06-18 碎碎念: 2024-06-17 碎碎念: 2024-06-15 碎碎念: 2024-06-14 碎碎念: 2024 年的高三喊楼碎碎念: 2024-06-06 碎碎念: 2024-05-30 二碎碎念: 2024-05-30 一碎碎念: 2024-05-27 碎碎念: 2024-05-26 碎碎念: 2024-05-23 碎碎念: 2024-05-22 碎碎念: 2024-05-19 碎碎念: 2024-05-17 碎碎念: 2024-05-14 碎碎念: 2024-05-13 碎碎念: 2024-05-12 碎碎念: 2024-05-10 碎碎念: 2024-05-08 碎碎念: 2024-05-06 碎碎念: 2024-05-05 M:8 三碎碎念: 2024-05-05 碎碎念: 2024-05-05 M:7 二碎碎念: 2024-05-05 M:7 一碎碎念: 2024-05-02 星期四 M:3 小雨碎碎念: 生日碎碎念: 2024-04-29 M:7 碎碎念: 2024-04-27 M:8