Skip to content

Commit

Permalink
feat: service worker
Browse files Browse the repository at this point in the history
  • Loading branch information
D-Sketon committed Nov 23, 2024
1 parent 780dbdd commit 51d9e6e
Show file tree
Hide file tree
Showing 10 changed files with 264 additions and 10 deletions.
4 changes: 4 additions & 0 deletions assets/css/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@ a, .main-nav-icon, .popup-btn-close {
@import "partials/sidebar";
{{ end }}

{{ if $params.service_worker.enable }}
@import "partials/notification";
{{ end }}

[data-theme="dark"] {
::-webkit-scrollbar, ::-webkit-scrollbar-track {
background-color: #616161;
Expand Down
53 changes: 53 additions & 0 deletions assets/css/partials/notification.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
.notification-wrapper {
position: fixed;
z-index: 1000;
top: 20px;
right: 20px;
background: var(--color-header-background);
box-shadow: 0 0 10px var(--color-hover-shadow);
border-radius: 5px;
padding: 10px 20px;
margin-left: 20px;
opacity: 0;
visibility: hidden;
transition: .5s;
color: var(--grey-7);

&.show {
opacity: 1;
visibility: visible;
}

h1 {
padding: 10px 0;
}

p {
padding: 10px 0;
}

.notification-btn {
display: flex;
justify-content: flex-end;
gap: 15px;
padding: 10px 0;
}

button {
background: #ff7777;
border-radius: 5px;
color: #fff;
padding: 5px 10px;
font-family: 'Noto Serif SC', 'Noto Serif JP', -apple-system, 'PingFang SC', 'Microsoft YaHei', sans-serif;
border: none;
transition: .2s;

&:hover {
background: rgb(255, 77, 77);
}

&:active {
background: #ff2e2e;
}
}
}
52 changes: 52 additions & 0 deletions assets/js/service_worker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
if ("serviceWorker" in navigator && window.siteConfig.swPath) {
_$("#notification-update-btn").onclick = () => {
try {
navigator.serviceWorker.getRegistration().then((reg) => {
reg.waiting.postMessage("skipWaiting");
});
} catch (e) {
window.location.reload();
}
};

_$("#notification-close-btn").onclick = () => {
_$(".notification-wrapper").classList.remove("show");
}

function emitUpdate() {
_$(".notification-wrapper").classList.add("show");
}

navigator.serviceWorker
.register(siteConfig.swPath)
.then((registration) => {
console.log("Service Worker 注册成功: ", registration);
if (registration.waiting) {
emitUpdate();
return;
}
registration.onupdatefound = () => {
console.log("Service Worker 更新中...");
const installingWorker = registration.installing;
installingWorker.onstatechange = () => {
if (installingWorker.state === "installed") {
if (navigator.serviceWorker.controller) {
emitUpdate();
}
}
};
};
})
.catch((error) => {
console.log("Service Worker 注册失败: ", error);
});

let refreshing = false;
navigator.serviceWorker.addEventListener("controllerchange", () => {
if (refreshing) {
return;
}
refreshing = true;
window.location.reload();
});
}
95 changes: 95 additions & 0 deletions assets/js/sw.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
const VERSION = "{{ time.Now.Unix }}";

const preCache = [
'{{ "images/taichi.png" | relURL }}',
'{{ "images/taichi-fill.png" | relURL }}',
'{{ "css/loader.css" | relURL }}',
'{{ "css/main.css" | relURL }}',
'{{ "js/main.js" | relURL }}',
'{{ .Site.Params.banner | relURL }}',
];

const cacheDomain = [
"fonts.googleapis.com",
"npm.webcache.cn",
"unpkg.com",
"fastly.jsdelivr.net",
"cdn.jsdelivr.net",
];

// 安装时预加载必要内容
self.addEventListener("install", (event: ExtendableEvent) => {
console.log(`Service Worker ${VERSION} installing.`);
event.waitUntil(caches.open(VERSION).then((cache) => cache.addAll(preCache)));
});

async function cacheRequest(request, options?) {
try {
const responseToCache = await fetch(request);
const cache = await caches.open(VERSION);
if (!/^https?:$/i.test(new URL(request.url).protocol))
return responseToCache;
cache.put(request, responseToCache.clone());
return responseToCache;
} catch (e) {
const responseToCache = await fetch(request, options);
const cache = await caches.open(VERSION);
if (!/^https?:$/i.test(new URL(request.url).protocol))
return responseToCache;
cache.put(request, responseToCache.clone());
return responseToCache;
}
}

async function respondRequest(request, options?) {
const response = await caches.match(request);
if (response) {
return response;
}
return cacheRequest(request, options);
}

self.addEventListener("fetch", (event) => {
const url = new URL(event.request.url);
// 检查请求的域名是否在 CacheDomain 中
if (cacheDomain.includes(url.hostname)) {
event.respondWith(respondRequest(event.request));
} else {
// 检查请求是否为 POST 或带有查询参数的 GET 这样可避免错误缓存
if (
event.request.method === "POST" ||
(event.request.method === "GET" && url.search)
) {
try {
event.respondWith(fetch(event.request));
} catch (e) {
event.respondWith(fetch(event.request, { mode: "no-cors" }));
}
} else {
event.respondWith(respondRequest(event.request, { mode: "no-cors" }));
}
}
});

self.addEventListener("activate", (event) => {
event.waitUntil(
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames.map((cacheName) => {
if (VERSION !== cacheName) {
console.log(`Service Worker: deleting old cache ${cacheName}`);
return caches.delete(cacheName);
}
})
);
})
);
console.log(`Service Worker ${VERSION} activated.`);
});

self.addEventListener("message", (event) => {
console.log("Service Worker: message received");
if (event.data === "skipWaiting") {
(self as unknown as ServiceWorkerGlobalScope).skipWaiting();
}
});
2 changes: 1 addition & 1 deletion assets/js/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"target": "ES2018",
"declaration": true,
"esModuleInterop": true,
"lib": ["dom", "ESNext", "DOM.Iterable"]
"lib": ["dom", "ESNext", "DOM.Iterable", "WebWorker"]
},
"include": ["./**/*"],
"exclude": ["node_modules"]
Expand Down
4 changes: 4 additions & 0 deletions config/_default/params.yml
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,10 @@ quicklink:
# Only support string
ignores: []

# Experimental
service_worker:
enable: false

# Experimental
live2d:
enable: false
Expand Down
27 changes: 21 additions & 6 deletions layouts/partials/afterFooter.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
{{ partial "helpers/js.html" (dict "src" (index (partial "helpers/vendorCdn.html" (dict "item" $js.lazysizes "ctx" $site)) 0) "integrity" (index (partial "helpers/vendorCdnIntegrity.html" (dict "item" $js.lazysizes)) 0)) }}
{{ partial "helpers/js.html" (dict "src" (index (partial "helpers/vendorCdn.html" (dict "item" $js.clipboard "ctx" $site)) 0) "integrity" (index (partial "helpers/vendorCdnIntegrity.html" (dict "item" $js.clipboard)) 0)) }}

{{ partial "helpers/ts.html" (dict "source" "js/main.ts") }}
{{ partial "helpers/ts.html" (dict "source" "js/main.ts" "ctx" .) }}

{{ if $params.animation.enable }}
{{ partial "helpers/ts.html" (dict "source" "js/aos.ts") }}
{{ partial "helpers/ts.html" (dict "source" "js/aos.ts" "ctx" .) }}
<script>
var aosInit = () => {
AOS.init({
Expand All @@ -27,7 +27,7 @@
</script>
{{ end }}

{{ partial "helpers/ts.html" (dict "source" "js/pjax_main.ts" "pjax" true) }}
{{ partial "helpers/ts.html" (dict "source" "js/pjax_main.ts" "pjax" true "ctx" .) }}

{{ if $params.algolia_search.enable }}
<script>
Expand All @@ -50,7 +50,7 @@
</script>
{{ partial "helpers/js.html" (dict "src" (index (partial "helpers/vendorCdn.html" (dict "item" $js.algolia "ctx" $site)) 0) "defer" true "integrity" (index (partial "helpers/vendorCdnIntegrity.html" (dict "item" $js.algolia)) 0)) }}
{{ partial "helpers/js.html" (dict "src" (index (partial "helpers/vendorCdn.html" (dict "item" $js.instantsearch "ctx" $site)) 0) "defer" true "integrity" (index (partial "helpers/vendorCdnIntegrity.html" (dict "item" $js.instantsearch)) 0)) }}
{{ partial "helpers/ts.html" (dict "source" "js/algolia_search.ts") }}
{{ partial "helpers/ts.html" (dict "source" "js/algolia_search.ts" "ctx" .) }}
{{ end }}

{{ if $params.firework.enable }}
Expand Down Expand Up @@ -136,7 +136,7 @@
cacheBust: false,
});
</script>
{{ partial "helpers/ts.html" (dict "source" "js/pjax.ts") }}
{{ partial "helpers/ts.html" (dict "source" "js/pjax.ts" "ctx" .) }}
{{ end }}

{{ if $params.live2d.enable }}
Expand Down Expand Up @@ -240,7 +240,7 @@
</script>
{{ end }}
{{ if not .IsHome }}
{{ partial "helpers/ts.html" (dict "source" "js/insert_highlight.ts" "pjax" true) }}
{{ partial "helpers/ts.html" (dict "source" "js/insert_highlight.ts" "pjax" true "ctx" .) }}
{{ $photoswipe_lightbox := index (partial "helpers/vendorCdn.html" (dict "item" $js.photoswipe_lightbox "ctx" $site)) 0 }}
{{ $photoswipe_lightbox_integrity := index (partial "helpers/vendorCdnIntegrity.html" (dict "item" $js.photoswipe_lightbox)) 0 }}
{{ $photoswipe := index (partial "helpers/vendorCdn.html" (dict "item" $js.photoswipe "ctx" $site)) 0 }}
Expand Down Expand Up @@ -325,6 +325,21 @@
{{ partial "helpers/js.html" (dict "src" (index (partial "helpers/vendorCdn.html" (dict "item" $js.busuanzi "ctx" $site)) 0) "async" true "integrity" (index (partial "helpers/vendorCdnIntegrity.html" (dict "item" $js.busuanzi)) 0)) }}
{{ end }}

{{ if $params.service_worker.enable }}
{{ partial "helpers/ts.html" (dict "source" "js/sw.ts" "ctx" . "inline" false "target" "sw.js") }}
{{ partial "helpers/ts.html" (dict "source" "js/service_worker.ts" "ctx" .) }}
{{ else }}
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.getRegistrations().then((registrations) => {
for (let registration of registrations) {
registration.unregister();
}
});
}
</script>
{{ end }}

<script>
const reimuCopyright = String.raw`
______ ______ __ __ __ __ __
Expand Down
5 changes: 5 additions & 0 deletions layouts/partials/head/config.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,8 @@
<script>
window.siteConfig = JSON.parse({{ $siteConfig | jsonify }});
</script>
{{ if .Site.Params.service_worker.enable }}
<script>
window.siteConfig.swPath = '{{ "sw.js" | relURL }}';
</script>
{{ end }}
21 changes: 18 additions & 3 deletions layouts/partials/helpers/ts.html
Original file line number Diff line number Diff line change
@@ -1,15 +1,30 @@
{{ $source := .source }}
{{ $temp := .source }}
{{ $pjax := .pjax }}
{{ $target := .target }}
{{ $inline := .inline | default true }}
{{ $ctx := .ctx }}

{{- with resources.Get $source }}
{{- if eq hugo.Environment "development" }}
{{- with . | js.Build }}
{{ $ts := . | resources.ExecuteAsTemplate $temp $ctx }}
{{- $opts := dict "targetPath" $target }}
{{- with $ts | js.Build $opts }}
{{ if $inline }}
<script src="{{ .RelPermalink }}" {{ if $pjax }}data-pjax{{ end }}></script>
{{ else }}
<!-- {{ .RelPermalink }} -->
{{ end }}
{{- end }}
{{- else }}
{{- $opts := dict "minify" true }}
{{- with . | js.Build $opts | fingerprint }}
{{ $ts := . | resources.ExecuteAsTemplate $temp $ctx }}
{{- $opts := dict "minify" true "targetPath" $target }}
{{- with $ts | js.Build $opts }}
{{ if $inline }}
<script src="{{ .RelPermalink }}" integrity="{{- .Data.Integrity }}" crossorigin="anonymous" {{ if $pjax }}data-pjax{{ end }}></script>
{{ else }}
<!-- {{ .RelPermalink }} -->
{{ end }}
{{- end }}
{{- end }}
{{- end }}
11 changes: 11 additions & 0 deletions layouts/partials/loader.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,14 @@

<div id="copy-tooltip" style="pointer-events: none; opacity: 0; transition: all 0.2s ease; position: fixed;top: 50%;left: 50%;z-index: 999;transform: translate(-50%, -50%);color: white;background: rgba(0, 0, 0, 0.5);padding: 10px 15px;border-radius: 10px;">
</div>

{{ if .Site.Params.service_worker.enable }}
<div class="notification-wrapper">
<h1>{{ i18n "service_worker.title" }}</h1>
<p>{{ i18n "service_worker.content" }}</p>
<div class="notification-btn">
<button id="notification-update-btn">{{ i18n "service_worker.confirm" }}</button>
<button id="notification-close-btn">{{ i18n "service_worker.cancel" }}</button>
</div>
</div>
{{ end }}

0 comments on commit 51d9e6e

Please sign in to comment.