service worker stuff work in progress

This commit is contained in:
vabene1111
2021-01-21 16:16:49 +01:00
parent ec14338159
commit 47c690526e
14 changed files with 211 additions and 97 deletions

View File

@ -12,7 +12,6 @@
"bootstrap-vue": "^2.21.2",
"core-js": "^3.6.5",
"moment": "^2.29.1",
"register-service-worker": "^1.7.1",
"vue": "^2.6.11",
"vue-multiselect": "^2.1.6",
"vue-template-compiler": "^2.6.12",
@ -31,7 +30,8 @@
"workbox-navigation-preload": "^6.0.2",
"workbox-precaching": "^6.0.2",
"workbox-routing": "^6.0.2",
"workbox-strategies": "^6.0.2"
"workbox-strategies": "^6.0.2",
"workbox-expiration": "^6.0.2"
},
"eslintConfig": {
"root": true,

View File

@ -0,0 +1,94 @@
<template>
<div id="app">
<label>
{{ _('Search') }}
<input type="text" v-model="filter" class="form-control">
</label>
<div class="row">
<div class="col-md-3" v-for="r in filtered_recipes" :key="r.id">
<b-card :title="r.name" tag="article">
<b-card-text>
<span class="text-muted">{{ formatDateTime(r.updated_at) }}</span>
{{ r.description }}
</b-card-text>
<b-button :href="resolveDjangoUrl('view_recipe', r.id)" variant="primary">{{ _('Open') }}</b-button>
</b-card>
</div>
</div>
</div>
</template>
<script>
import Vue from 'vue'
import {BootstrapVue} from 'bootstrap-vue'
import 'bootstrap-vue/dist/bootstrap-vue.css'
import {GettextMixin, ResolveUrlMixin} from "@/utils/utils";
import moment from "moment";
Vue.use(BootstrapVue)
Vue.prototype.moment = moment
export default {
name: 'OfflineView',
mixins: [
ResolveUrlMixin,
GettextMixin
],
computed: {
filtered_recipes: function () {
let filtered_list = {}
this.recipes.forEach((recipe) => {
if (recipe.name.toLowerCase().includes(this.filter.toLowerCase())) {
if (recipe.id in filtered_list) {
if (recipe.updated_at > filtered_list[recipe.id].updated_at) {
filtered_list[recipe.id] = recipe
}
} else {
filtered_list[recipe.id] = recipe
}
}
})
return filtered_list
}
},
data() {
return {
recipes: [],
filter: '',
}
},
mounted() {
this.loadRecipe()
},
methods: {
formatDateTime: function (datetime) {
moment.locale(window.navigator.language);
return moment(datetime).format('LLL')
},
loadRecipe: function () {
caches.open('api-recipe').then(productsRuntimeCache => {
productsRuntimeCache.keys().then(keys => {
keys.forEach((key) => {
caches.match(key).then((response) => {
response.json().then((json) => {
this.recipes.push(json)
})
})
})
});
});
},
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,8 @@
import Vue from 'vue'
import App from './OfflineView.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')

View File

@ -1,32 +0,0 @@
/* eslint-disable no-console */
import { register } from 'register-service-worker'
if (process.env.NODE_ENV === 'production') {
register(`${process.env.BASE_URL}service-worker.js`, {
ready () {
console.log(
'App is being served from cache by a service worker.\n' +
'For more details, visit https://goo.gl/AFskqB'
)
},
registered () {
console.log('Service worker has been registered.')
},
cached () {
console.log('Content has been cached for offline use.')
},
updatefound () {
console.log('New content is downloading.')
},
updated () {
console.log('New content is available; please refresh.')
},
offline () {
console.log('No internet connection found. App is running in offline mode.')
},
error (error) {
console.error('Error during service worker registration:', error)
}
})
}

View File

@ -2,50 +2,43 @@
import {precacheAndRoute} from 'workbox-precaching';
import {registerRoute, setCatchHandler} from 'workbox-routing';
import {CacheFirst, NetworkFirst, StaleWhileRevalidate} from 'workbox-strategies';
import {ExpirationPlugin} from 'workbox-expiration';
const CACHE_NAME = 'offline-html';
// This assumes /offline.html is a URL for your self-contained
// (no external images or styles) offline page.
const FALLBACK_HTML_URL = '/offline/';
// Populate the cache with the offline HTML page when the
// service worker is installed.
const OFFLINE_CACHE_NAME = 'offline-html';
const OFFLINE_PAGE_URL = '/offline/';
self.addEventListener('install', async (event) => {
event.waitUntil(
caches.open(CACHE_NAME)
.then((cache) => cache.add(new Request(FALLBACK_HTML_URL, {cache: "reload"})))
);
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}) => {
// The FALLBACK_URL entries must be added to the cache ahead of time, either
// via runtime or precaching. If they are precached, then call
// `matchPrecache(FALLBACK_URL)` (from the `workbox-precaching` package)
// to get the response from the correct cache.
//
// Use event, request, and url to figure out how to respond.
// One approach would be to use request.destination, see
// https://medium.com/dev-channel/service-worker-caching-strategies-based-on-request-types-57411dd7652c
switch (event.request.destination) {
case 'document':
// If using precached URLs:
// return matchPrecache(FALLBACK_HTML_URL);
console.log('Triggered fallback HTML')
return caches.match(FALLBACK_HTML_URL);
switch (event.request.destination) {
case 'document':
console.log('Triggered fallback HTML')
return caches.match(OFFLINE_PAGE_URL);
default:
// If we don't have a fallback, just return an error response.
console.log('Triggered response ERROR')
return Response.error();
}
default:
console.log('Triggered response ERROR')
return Response.error();
}
});
precacheAndRoute(self.__WB_MANIFEST);
registerRoute(
({request}) => request.destination === 'image',
new CacheFirst({cacheName: 'images'}),
new CacheFirst({
cacheName: 'images',
plugins: [
new ExpirationPlugin({
maxEntries: 20,
}),
],
}),
);
registerRoute(
@ -65,14 +58,51 @@ registerRoute(
registerRoute(
new RegExp('api/*'),
new NetworkFirst({
cacheName: 'api'
cacheName: 'api',
plugins: [
new ExpirationPlugin({
maxEntries: 50
}),
],
})
)
registerRoute(
({request}) => request.destination === 'document',
new RegExp('api/recipe/([0-9]+)'),
new NetworkFirst({
cacheName: 'html'
cacheName: 'api-recipe',
plugins: [
new ExpirationPlugin({
maxEntries: 50,
}),
],
})
)
const matchHtml = ({url, request, event}) => {
if (request.destination === 'document') {
if (RegExp('view/recipe/*').test(url)) {
return true
}
if (RegExp('search/*').test(url)) {
return true
}
if (RegExp('plan/*').test(url)) {
return true
}
}
return false;
};
registerRoute(
matchHtml,
new NetworkFirst({
cacheName: 'html',
plugins: [
new ExpirationPlugin({
maxAgeSeconds: 60 * 60 * 24 * 30,
}),
],
})
)

View File

@ -5,6 +5,10 @@ const pages = {
entry: './src/apps/RecipeView/main.js',
chunks: ['chunk-vendors']
},
'offline_view': {
entry: './src/apps/OfflineView/main.js',
chunks: ['chunk-vendors']
},
}
module.exports = {

View File

@ -1 +1 @@
{"status":"done","chunks":{"chunk-vendors":[{"name":"css/chunk-vendors.css","path":"F:\\Developement\\Django\\recipes\\cookbook\\static\\vue\\css\\chunk-vendors.css"},{"name":"js/chunk-vendors.js","path":"F:\\Developement\\Django\\recipes\\cookbook\\static\\vue\\js\\chunk-vendors.js"}],"recipe_view":[{"name":"js/recipe_view.js","path":"F:\\Developement\\Django\\recipes\\cookbook\\static\\vue\\js\\recipe_view.js"}]}}
{"status":"done","chunks":{"chunk-vendors":[{"name":"css/chunk-vendors.css","path":"F:\\Developement\\Django\\recipes\\cookbook\\static\\vue\\css\\chunk-vendors.css"},{"name":"js/chunk-vendors.js","path":"F:\\Developement\\Django\\recipes\\cookbook\\static\\vue\\js\\chunk-vendors.js"}],"offline_view":[{"name":"js/offline_view.js","path":"F:\\Developement\\Django\\recipes\\cookbook\\static\\vue\\js\\offline_view.js"}],"recipe_view":[{"name":"js/recipe_view.js","path":"F:\\Developement\\Django\\recipes\\cookbook\\static\\vue\\js\\recipe_view.js"}]}}

View File

@ -8865,6 +8865,13 @@ workbox-expiration@^5.1.4:
dependencies:
workbox-core "^5.1.4"
workbox-expiration@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/workbox-expiration/-/workbox-expiration-6.0.2.tgz#ac01e8d17f48daa31dc0872c09ee6f4d2cf28ccb"
integrity sha512-6+nbR18cklAdI3BPT675ytftXPwnVbXGR8mPWNWTJtl5y2urRYv56ZOJLD7FBFVkZ8EjWiRhNP/A0fkxgdKtWQ==
dependencies:
workbox-core "^6.0.2"
workbox-google-analytics@^5.1.4:
version "5.1.4"
resolved "https://registry.yarnpkg.com/workbox-google-analytics/-/workbox-google-analytics-5.1.4.tgz#b3376806b1ac7d7df8418304d379707195fa8517"