window . addEventListener ( 'online' , ( ) => this . online ( true ) ) ;
window . addEventListener ( 'offline' , ( ) => this . online ( false ) ) ;
online ( online ) {
const showToast = online !== this . state . online ;
if ( showToast ) {
setTimeout ( ( ) => this . setState ( { showToast : null } ) , 2000 ) ;
}
const message = online
? "Yay, the application is online!"
: "Oh no, the app seems to be offline... " ;
this . setState ( { online, toastMessage : message , showToast : "show" } ) ;
}
< Toast message = { this . state . toastMessage } show = { this . state . showToast } / >
const precacheManifest = [ ] ;
workbox . precaching . precacheAndRoute ( precacheManifest ) ;
const dataCacheConfig = {
cacheName : 'meme-data'
} ;
workbox . routing . registerRoute (
/ .*categories/ ,
workbox . strategies . cacheFirst ( dataCacheConfig ) ,
'GET'
) ;
workbox . routing . registerRoute (
/ .*templates/ ,
workbox . strategies . cacheFirst ( dataCacheConfig ) ,
'GET'
) ;
workbox . routing . registerRoute (
/ .*memes\/.\w+/ ,
workbox . strategies . staleWhileRevalidate ( dataCacheConfig ) ,
'GET'
) ;
workbox . routing . registerRoute (
/ .*.(?:png|jpg|jpeg|svg)$/ ,
workbox . strategies . cacheFirst ( { cacheName : 'meme-images' } ) ,
'GET'
) ;
const apiStrategy = async ( { event } ) => {
try {
} catch ( error ) { }
} ;
return await workbox . strategies
. staleWhileRevalidate ( dataCacheConfig )
. handle ( { event } ) ;
const fake = {
id : 0 ,
top : 'memes' ,
bottom : 'not found' ,
template : 'notfound.jpg'
} ;
return new Response ( JSON . stringify ( [ fake ] ) ) ;
workbox . routing . setCatchHandler ( ( { event } ) => {
switch ( event . request . destination ) {
case 'image' :
return caches . match ( '/images/facepalm.jpg' ) ;
default :
return Response . error ( ) ;
}
} ) ;
const queue = new workbox . backgroundSync . Queue ( 'memes-to-be-saved' ) ;
self . addEventListener ( 'fetch' , event => {
if ( event . request . url . match ( / .*memes/ ) && event . request . method === 'POST' ) {
let response = fetch ( event . request . clone ( ) ) . catch ( ( ) =>
queueChange ( event . request . clone ( ) )
) ;
event . respondWith ( response ) ;
}
} ) ;
async function queueChange ( request ) {
await queue . addRequest ( request . clone ( ) ) ;
return new Response ( '' , { status : 200 } ) ;
}
const meme = await request . clone ( ) . json ( ) ;
meme . offline = true ;
let memes = ( await idbKeyval . get ( 'memes' ) ) || [ ] ;
idbKeyval . set ( 'memes' , [ ...memes , meme ] ) ;
const streamStrategy = workbox . streams . strategy ( [
( ) => '[' ,
async ( ) => {
/* Return the copied memes */
} ,
async e => {
/* Return the cached memes */
} ,
( ) => ']'
] ) ;
const data = await idbKeyval . get ( 'memes' ) ;
return stringify ( data , ',' ) ;
const response = await apiStrategy ( e ) ;
const data = await response . json ( ) ;
return stringify ( data ) ;
function stringify ( data , suffix ) {
if ( ! data || ! data . length ) {
return '' ;
}
let result = data . map ( item => JSON . stringify ( item ) ) . join ( ',' ) ;
if ( suffix ) {
result += suffix ;
}
return result ;
}
NB: Use the streamStrategy
{
callbacks: {
queueDidReplay: ( ) => clear ( ) ;
}
}
async function clear ( ) {
// Clear store
await idbKeyval . del ( 'memes' ) ;
// Clear cache
let cache = await caches . open ( 'meme-data' ) ;
let keys = await cache . keys ( ) ;
for ( let key of keys ) {
if ( / .*memes\/.\w+/ . test ( key . url ) ) {
cache . delete ( key ) ;
}
}
}