通过Service Worker 缓存优化 Typecho 的首页访问加速
Service Worker 是一种运行在浏览器背景的脚本,它可以在页面关闭后继续运行,主要用于处理网络请求、缓存资源、推送消息等功能。
认识
Service Worker 也是一个后台运行的脚本,充当一个代理服务器,拦截用户发出的网络请求,比如加载脚本和图片。Service Worker 可以修改用户的请求,或者直接向用户发出回应,不用联系服务器,这使得用户可以在离线情况下使用网络应用。它还可以在本地缓存资源文件,直接从缓存加载文件,因此可以加快访问速度。
条件
要使用 Service Worker 确保网站支持 HTTPS 协议,这是必要条件。
注册
Typecho 使用的话,需要在主题的 header.php
或者 footer.php
里面添加如下代码,以完成 Service Worker 注册。
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/serviceworker.js')
.then(registration => {
console.log('Service Worker 注册成功:', registration);
})
.catch(error => {
console.log('Service Worker 注册失败:', error);
});
}
</script>
新建
在网站的根目录新建 serviceworker.js
和 offline.html
两个独立文件,其中js为引入的必需文件,offline为非必需离线文件。
const CACHE_NAME = 'typecho-cache-v2';
const OFFLINE_URL = '/offline.html';
const urlsToCache = [
'/',
'/index.php',
'/usr/themes/你的主题名字/css/style.min.css', /**css文件
'/usr/themes/你的主题名字/js/script.min.js', /**js文件
'/usr/uploads/ /**存储在服务器的图片或文件
'/favicon.ico',
OFFLINE_URL,
'https://artalk.bosir.cn/dist/Artalk.js' /**第三方缓存文件
];
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => cache.addAll(urlsToCache))
.then(() => self.skipWaiting())
);
});
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(name => {
if (name !== CACHE_NAME) {
return caches.delete(name);
}
})
);
}).then(() => self.clients.claim())
);
});
self.addEventListener('fetch', event => {
if (event.request.method !== 'GET') return;
event.respondWith(
caches.match(event.request).then(response => {
if (response) return response;
return fetch(event.request).then(response => {
if (!response || response.status !== 200 || response.type !== 'basic') {
return response;
}
const responseToCache = response.clone();
caches.open(CACHE_NAME).then(cache => cache.put(event.request, responseToCache));
return response;
}).catch(() => {
return caches.match(OFFLINE_URL);
});
})
);
});
offline模式,即离线模式,f12 打开开发者工具后找到 online选项,点击后会出现offine 字样,点击打开离线模式,刷新页面会发现首页依然可以访问,而没有缓存的页面就显示下面的离线页面。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>水清无鱼</title>
</head>
<body>
<h1>离线模式</h1>
</body>
</html>
缓存
为了防止在浏览器需要请求新版本的 serviceworker.js 文件时,而文件自身被缓存,所以需要给 serviceworker.js 文件单独指定缓存头 Cache-control: no-store
或 no-cache
。然后在 Nainx 的 server {
区域内添加:
# serviceworker.js 不设置缓存
location ~* /(.*)/serviceworker\.js {
add_header Cache-Control no-cache;
add_header Pragma no-cache;
add_header Expires 0;
}
添加完毕后,重启Nginx服务器。
更新
在更新 Service Worker 时,需要修改 CACHE_NAME 的版本号以触发缓存更新
const CACHE_NAME = 'typecho-cache-v1';
或
const CACHE_NAME = 'typecho-cache-v2';
总结
整体来说,只要不涉及复杂的主题和js,Typecho 已经足够快,且拥有良好的打开速度。可如果你像我一样比较追求极致性能,喜欢折腾,也可以尝试一下。我的目标是把博客优化到和静态博客一样丝滑,目前缓存过后进入首页只需要100ms以内,en...
题外话
目前 typecho 已经出现了 1.3.0测试版本,没错,就是目前我现在使用的这个版本。不过我并不建议大家进行升级,毕竟BUG有点多。我目前是全站 0 插件,测试版本的兼容性有待考量。且如果php像我一样为最新版,出现的问题可能更多...
参考资料
1.// cloud.tencent.com/developer/article/2005909
2.// www.luolt.cn/archives/1848.html
3.// www.bookstack.cn/read/webapi-tutorial/docs-service-worker.md