Merge branch 'service-worker-cache-api' into 'develop'

Cache API/media files with service workers

See merge request funkwhale/funkwhale!991
merge-requests/1042/head
Eliot Berriot 2020-01-09 10:54:55 +01:00
commit 1bdbce037e
3 zmienionych plików z 89 dodań i 11 usunięć

Wyświetl plik

@ -263,7 +263,7 @@ export default {
updateApp () {
this.$store.commit('ui/serviceWorker', {updateAvailable: false})
if (!this.serviceWorker.registration || !this.serviceWorker.registration.waiting) { return; }
this.serviceWorker.registration.waiting.postMessage('skipWaiting');
this.serviceWorker.registration.waiting.postMessage({command: 'skipWaiting'})
}
},
computed: {
@ -317,9 +317,16 @@ export default {
},
},
watch: {
'$store.state.instance.instanceUrl' () {
'$store.state.instance.instanceUrl' (v) {
this.$store.dispatch('instance/fetchSettings')
this.fetchNodeInfo()
if (this.serviceWorker.registration) {
let sw = this.serviceWorker.registration.active
if (sw) {
sw.postMessage({command: 'serverChosen', serverUrl: v})
}
}
},
'$store.state.ui.theme': {
immediate: true,

Wyświetl plik

@ -6,13 +6,10 @@ import store from './store'
if (process.env.NODE_ENV === 'production') {
register(`${process.env.BASE_URL}service-worker.js`, {
ready () {
ready (registration) {
console.log(
'App is being served from cache by a service worker.'
'App is being served from cache by a service worker.', registration
)
},
registered (registration) {
console.log('Service worker has been registered.')
// check for updates every 2 hours
var checkInterval = 1000 * 60 * 60 * 2
// var checkInterval = 1000 * 5
@ -20,6 +17,13 @@ if (process.env.NODE_ENV === 'production') {
console.log('Checking for service worker update…')
registration.update();
}, checkInterval);
store.commit('ui/serviceWorker', {registration: registration})
if (registration.active) {
registration.active.postMessage({command: 'serverChosen', serverUrl: store.state.instance.instanceUrl})
}
},
registered () {
console.log('Service worker has been registered.')
},
cached () {
console.log('Content has been cached for offline use.')

Wyświetl plik

@ -1,14 +1,20 @@
// This is the code piece that GenerateSW mode can't provide for us.
// This code listens for the user's confirmation to update the app.
workbox.loadModule('workbox-routing');
workbox.loadModule('workbox-strategies');
workbox.loadModule('workbox-expiration');
self.addEventListener('message', (e) => {
if (!e.data) {
return;
}
switch (e.data) {
console.log('[sw] received message', e.data)
switch (e.data.command) {
case 'skipWaiting':
self.skipWaiting();
break;
case 'serverChosen':
self.registerServerRoutes(e.data.serverUrl)
default:
// NOOP
break;
@ -18,7 +24,7 @@ workbox.core.clientsClaim();
// The precaching code provided by Workbox.
self.__precacheManifest = [].concat(self.__precacheManifest || []);
console.log('Files to be cached by service worker [before filtering]', self.__precacheManifest.length);
console.log('[sw] Files to be cached [before filtering]', self.__precacheManifest.length);
var excludedUrlsPrefix = [
'/js/locale-',
'/js/moment-locale-',
@ -28,6 +34,67 @@ var excludedUrlsPrefix = [
self.__precacheManifest = self.__precacheManifest.filter((e) => {
return !excludedUrlsPrefix.some(prefix => e.url.startsWith(prefix))
});
console.log('Files to be cached by service worker [after filtering]', self.__precacheManifest.length);
console.log('[sw] Files to be cached [after filtering]', self.__precacheManifest.length);
// workbox.precaching.suppressWarnings(); // Only used with Vue CLI 3 and Workbox v3.
workbox.precaching.precacheAndRoute(self.__precacheManifest, {});
const router = new workbox.routing.Router();
router.addCacheListener()
router.addFetchListener()
var registeredServerRoutes = []
self.registerServerRoutes = (serverUrl) => {
console.log('[sw] Setting up API caching for', serverUrl)
registeredServerRoutes.forEach((r) => {
console.log('[sw] Unregistering previous API route...', r)
router.unregisterRoute(r)
})
if (!serverUrl) {
return
}
var regexReadyServerUrl = serverUrl.replace('.', '\\.')
registeredServerRoutes = []
var networkFirstPaths = [
'api/v1/',
'media/',
]
var networkFirstExcludedPaths = [
'api/v1/listen'
]
var strategy = new workbox.strategies.NetworkFirst({
cacheName: "api-cache:" + serverUrl,
plugins: [
new workbox.expiration.Plugin({
maxAgeSeconds: 24 * 60 * 60 * 7,
}),
]
})
var networkFirstRoutes = networkFirstPaths.map((path) => {
var regex = new RegExp(regexReadyServerUrl + path)
return new workbox.routing.RegExpRoute(regex, () => {})
})
var matcher = ({url, event}) => {
for (let index = 0; index < networkFirstExcludedPaths.length; index++) {
const blacklistedPath = networkFirstExcludedPaths[index];
if (url.pathname.startsWith('/' + blacklistedPath)) {
// the path is blacklisted, we don't cache it at all
console.log('[sw] Path is blacklisted, not caching', url.pathname)
return false
}
}
// we call other regex matchers
for (let index = 0; index < networkFirstRoutes.length; index++) {
const route = networkFirstRoutes[index];
let result = route.match({url, event})
if (result) {
return result
}
}
return false
}
var route = new workbox.routing.Route(matcher, strategy)
console.log('[sw] registering new API route...', route)
router.registerRoute(route)
registeredServerRoutes.push(route)
}