diff --git a/_config.yml b/_config.yml index ecc979f..d758be2 100644 --- a/_config.yml +++ b/_config.yml @@ -227,7 +227,8 @@ firework: # Experimental, may have a lot of bugs, open with caution! pjax: enable: false - +serviceworker: + enable: true # Dependent cdn links vendor: js: diff --git a/layout/_partial/head.ejs b/layout/_partial/head.ejs index 75f789c..30dbcc9 100644 --- a/layout/_partial/head.ejs +++ b/layout/_partial/head.ejs @@ -64,4 +64,7 @@ }).init(); <% } %> + <% if (theme.serviceworker.enable){ %> + + <% } %> diff --git a/scripts/generator/servicework.js b/scripts/generator/servicework.js new file mode 100644 index 0000000..1293d91 --- /dev/null +++ b/scripts/generator/servicework.js @@ -0,0 +1,12 @@ +const fs = require('hexo-fs') +let timeVersion = Date.now() + +hexo.extend.generator.register('ServiceWoker', function(locals){ + let filePath = 'themes/reimu/source/js/sw.js' + let content = fs.readFileSync(filePath) + content = 'const VERSION = "'+ timeVersion +'";\n' + content + return { + path: "sw.js", + data: content, + } +}) diff --git a/source/js/sw.js b/source/js/sw.js new file mode 100644 index 0000000..64a85ad --- /dev/null +++ b/source/js/sw.js @@ -0,0 +1,69 @@ +const PreCache = [ + '/images/taichi.png', + '/images/banner.jpg', + '/images/taichi-fill.png', + '/css/loader.css', + '/css/style.css', + '/js/script.js' +]; + +// 安装时预加载必要内容 +self.addEventListener('install', (event) => { + console.log(`Service Worker ${VERSION} installing.`); + event.waitUntil( + caches.open(VERSION).then((cache) => { + return cache.addAll(PreCache); + }) + ); +}); + +self.addEventListener('fetch', function(event) { + // 检查请求是否为 POST 或带有查询参数的 GET 这样可用避免错误缓存 + if (event.request.method === 'POST' || (event.request.method === 'GET' && event.request.url.indexOf('?') !== -1)) { + event.respondWith(fetch(event.request)); + } else { + event.respondWith( + caches.match(event.request) + .then(function(response) { + if (response) { + return response; + } + return fetch(event.request).then(function(responseToCache) { + var responseToCacheClone = responseToCache.clone(); + caches.open(VERSION).then(function(cache) { + cache.put(event.request, responseToCacheClone); + }); + return responseToCache; + }); + } + ) + ); + } +}); + + +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.`); +}); + +if ('serviceWorker' in navigator) { + navigator.serviceWorker.register('/sw.js') + .then((registration) => { + console.log('Service Worker 注册成功: ', registration); + }) + .catch((error) => { + console.log('Service Worker 注册失败: ', error); + }); +}