mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2026-01-01 04:10:06 -05:00
wip service worker
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
<html lang="{{ LANGUAGE_CODE }}">
|
||||
<head>
|
||||
<title>Tandoor</title>
|
||||
<meta name="description" content="{% trans 'Tandoor Recipe Manager' %}">
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5, minimal-ui, shrink-to-fit=no">
|
||||
<meta name="robots" content="noindex,nofollow"/>
|
||||
@@ -43,16 +44,16 @@
|
||||
<script type="application/javascript">
|
||||
localStorage.setItem('BASE_PATH', "{% base_path request 'base' %}")
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
if ("serviceWorker" in navigator) {
|
||||
navigator.serviceWorker.register("{% url 'service_worker' %}", {scope: "{% base_path request 'base' %}" + '/'}).then(function (reg) {
|
||||
}).catch(function (err) {
|
||||
console.warn('Error whilst registering service worker', err);
|
||||
});
|
||||
} else {
|
||||
console.warn('service worker not in navigator');
|
||||
}
|
||||
});
|
||||
{#window.addEventListener("load", () => {#}
|
||||
{# if ("serviceWorker" in navigator) {#}
|
||||
{# navigator.serviceWorker.register("{% url 'service_worker' %}", {scope: "{% base_path request 'base' %}" + '/'}).then(function (reg) {#}
|
||||
{# }).catch(function (err) {#}
|
||||
{# console.warn('Error whilst registering service worker', err);#}
|
||||
{# });#}
|
||||
{# } else {#}
|
||||
{# console.warn('service worker not in navigator');#}
|
||||
{# }#}
|
||||
{#});#}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -523,6 +523,9 @@ def report_share_abuse(request, token):
|
||||
return HttpResponseRedirect(reverse('index'))
|
||||
|
||||
|
||||
def service_worker(request):
|
||||
return
|
||||
|
||||
def web_manifest(request):
|
||||
theme_values = get_theming_values(request)
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
"jsdom": "^26.1.0",
|
||||
"typescript": "^5.8.3",
|
||||
"vite": "6.2.6",
|
||||
"vite-plugin-pwa": "^1.0.0",
|
||||
"vite-plugin-vuetify": "^2.1.1",
|
||||
"vue-tsc": "^2.2.8"
|
||||
}
|
||||
|
||||
137
vue3/src/sw.ts
Normal file
137
vue3/src/sw.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
// These JavaScript module imports need to be bundled:
|
||||
import {precacheAndRoute, cleanupOutdatedCaches} from 'workbox-precaching';
|
||||
import {registerRoute, setCatchHandler} from 'workbox-routing';
|
||||
import {CacheFirst, NetworkFirst, NetworkOnly, StaleWhileRevalidate} from 'workbox-strategies';
|
||||
import {ExpirationPlugin} from 'workbox-expiration';
|
||||
import {BackgroundSyncPlugin, Queue} from "workbox-background-sync";
|
||||
|
||||
cleanupOutdatedCaches()
|
||||
|
||||
declare let self: ServiceWorkerGlobalScope
|
||||
precacheAndRoute(self.__WB_MANIFEST)
|
||||
|
||||
const OFFLINE_CACHE_NAME = 'offline-html';
|
||||
let script_name = typeof window !== 'undefined' ? localStorage.getItem('SCRIPT_NAME') : '/'
|
||||
var OFFLINE_PAGE_URL = script_name + 'offline/';
|
||||
|
||||
self.addEventListener('install', async (event) => {
|
||||
event.waitUntil(
|
||||
caches.open(OFFLINE_CACHE_NAME).then((cache) => cache.add(new Request(OFFLINE_PAGE_URL, {cache: "reload"})))
|
||||
);
|
||||
});
|
||||
|
||||
// default handler if everything else fails
|
||||
setCatchHandler(({event}) => {
|
||||
switch (event.request.destination) {
|
||||
case 'document':
|
||||
console.log('Triggered fallback HTML')
|
||||
return caches.open(OFFLINE_CACHE_NAME).then((cache) => cache.match(OFFLINE_PAGE_URL))
|
||||
default:
|
||||
console.log('Triggered response ERROR')
|
||||
return Response.error();
|
||||
}
|
||||
});
|
||||
|
||||
registerRoute(
|
||||
({request}) => request.destination === 'image',
|
||||
new CacheFirst({
|
||||
cacheName: 'images',
|
||||
plugins: [
|
||||
new ExpirationPlugin({
|
||||
maxEntries: 20,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
);
|
||||
|
||||
registerRoute(
|
||||
({request}) => (request.destination === 'script' || request.destination === 'style'),
|
||||
new NetworkFirst({
|
||||
cacheName: 'assets'
|
||||
})
|
||||
)
|
||||
|
||||
registerRoute(
|
||||
new RegExp('jsreverse'),
|
||||
new StaleWhileRevalidate({
|
||||
cacheName: 'assets'
|
||||
})
|
||||
)
|
||||
|
||||
registerRoute(
|
||||
new RegExp('jsi18n'),
|
||||
new StaleWhileRevalidate({
|
||||
cacheName: 'assets'
|
||||
})
|
||||
)
|
||||
|
||||
registerRoute(
|
||||
new RegExp('api/recipe/([0-9]+)'),
|
||||
new NetworkFirst({
|
||||
cacheName: 'api-recipe',
|
||||
plugins: [
|
||||
new ExpirationPlugin({
|
||||
maxEntries: 50,
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
|
||||
const queue = new Queue('shopping-sync-queue', {
|
||||
maxRetentionTime: 7 * 24 * 60,
|
||||
});
|
||||
|
||||
registerRoute(
|
||||
new RegExp('api/shopping-list-entry/([0-9]+)'),
|
||||
new NetworkOnly({
|
||||
plugins: [
|
||||
{
|
||||
fetchDidFail: async ({request}) => {
|
||||
await queue.pushRequest({request});
|
||||
},
|
||||
}
|
||||
],
|
||||
}),
|
||||
'PATCH'
|
||||
)
|
||||
|
||||
addEventListener('message', (event) => {
|
||||
if (event.data.type === 'BGSYNC_REPLAY_REQUESTS') {
|
||||
queue.replayRequests().then((r) => {
|
||||
event.ports[0].postMessage('REPLAY_SUCCESS SW');
|
||||
}).catch((err) => {
|
||||
event.ports[0].postMessage('REPLAY_FAILURE');
|
||||
});
|
||||
}
|
||||
if (event.data.type === 'BGSYNC_COUNT_QUEUE') {
|
||||
queue.getAll().then((r) => {
|
||||
event.ports[0].postMessage(r.length);
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
registerRoute(
|
||||
new RegExp('api/*'),
|
||||
new NetworkFirst({
|
||||
cacheName: 'api',
|
||||
plugins: [
|
||||
new ExpirationPlugin({
|
||||
maxEntries: 50
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
|
||||
registerRoute(
|
||||
({request}) => request.destination === 'document',
|
||||
new NetworkFirst({
|
||||
cacheName: 'html',
|
||||
plugins: [
|
||||
new ExpirationPlugin({
|
||||
maxAgeSeconds: 60 * 60 * 24 * 30,
|
||||
maxEntries: 50,
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
|
||||
@@ -3,6 +3,7 @@ import {fileURLToPath, URL} from 'node:url'
|
||||
import {defineConfig} from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import vuetify, {transformAssetUrls} from 'vite-plugin-vuetify'
|
||||
import {VitePWA} from "vite-plugin-pwa";
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
@@ -14,6 +15,16 @@ export default defineConfig({
|
||||
vuetify({
|
||||
autoImport: true,
|
||||
}),
|
||||
VitePWA({
|
||||
registerType: 'autoUpdate',
|
||||
strategies: 'injectManifest',
|
||||
srcDir: 'src',
|
||||
filename: 'sw.ts',
|
||||
injectManifest: {
|
||||
swDest: "../cookbook/templates/sw.js",
|
||||
injectionPoint: undefined
|
||||
}
|
||||
})
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
|
||||
2601
vue3/yarn.lock
2601
vue3/yarn.lock
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user