Skip to content

Instantly share code, notes, and snippets.

@prof3ssorSt3v3
Last active January 10, 2024 00:08
Show Gist options
  • Select an option

  • Save prof3ssorSt3v3/5c3368c26f7051963e7a46a25348c901 to your computer and use it in GitHub Desktop.

Select an option

Save prof3ssorSt3v3/5c3368c26f7051963e7a46a25348c901 to your computer and use it in GitHub Desktop.
Code from Service Workers 6 - Using fetch and the cache
const APP = {
SW: null,
init() {
//called after DOMContentLoaded
//register our service worker
APP.registerSW();
document.querySelector('h2').addEventListener('click', APP.addImage);
},
registerSW() {
if ('serviceWorker' in navigator) {
// Register a service worker hosted at the root of the site
navigator.serviceWorker.register('/sw.js').then(
(registration) => {
APP.SW =
registration.installing ||
registration.waiting ||
registration.active;
},
(error) => {
console.log('Service worker registration failed:', error);
}
);
} else {
console.log('Service workers are not supported.');
}
},
addImage(ev) {
let img = document.createElement('img');
img.src = '/img/1016-800x600.jpg';
img.alt = 'dynamically added image';
let p = document.createElement('p');
p.append(img);
document.querySelector('main').append(p);
},
};
document.addEventListener('DOMContentLoaded', APP.init);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Intro to Service Workers</title>
<!-- import google fonts -->
<link rel="preconnect" href="https://fonts.gstatic.com" />
<link
href="https://fonts.googleapis.com/css2?family=Lato&family=Montserrat:wght@400;700&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="css/main.css" />
</head>
<body>
<header>
<h1>Intro to Service Workers</h1>
<h2>Controlling Fetch &amp; Cache with Service Workers</h2>
</header>
<!--
IMAGES
https://picsum.photos/id/1011/5472/3648
https://picsum.photos/id/1016/3844/2563
-->
<main>
<p>
<img src="/img/1011-800x600.jpg" alt="sample image 1" />
Some water and a woman in a canoe.
</p>
<p>
<img src="/img/1016-800x600.jpg" alt="sample image 2" />
A beautiful desert landscape.
</p>
</main>
<script defer src="./js/app.js"></script>
</body>
</html>
html {
font-size: 20px;
font-family: 'Montserrat', sans-serif;
line-height: 1.5;
background-color: #222;
color: #eee;
}
body {
min-height: 100vh;
background-color: inherit;
color: inherit;
}
header,
main {
margin: 1rem 2rem;
}
main {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 1rem;
justify-content: space-around;
}
h1 {
color: orangered;
font-weight: 700;
}
h2 {
color: orange;
font-weight: 700;
}
p {
font-family: 'Lato', sans-serif;
font-weight: 400;
}
main img {
/* max-width: 100%;
min-width: 200px; */
width: clamp(200px, 400px, 600px);
}
const version = 2;
let staticName = `staticCache-${version}`;
let dynamicName = `dynamicCache`;
let fontName = `fontCache-${version}`;
let imageName = `imageCache-${version}`;
let options = {
ignoreSearch: false,
ignoreMethod: false,
ignoreVary: false,
};
//starter html and css and js files
let assets = ['/', '/index.html', '/css/main.css', '/js/app.js'];
//starter images
let imageAssets = [
'/img/1011-800x600.jpg',
'/img/1011-800x600.jpg?id=one',
'/img/1011-800x600.jpg?id=two',
'/img/1011-800x600.jpg?id=three',
];
self.addEventListener('install', (ev) => {
// service worker has been installed.
//Extendable Event
console.log(`Version ${version} installed`);
// build a cache
ev.waitUntil(
caches
.open(staticName)
.then((cache) => {
cache.addAll(assets).then(
() => {
//addAll == fetch() + put()
console.log(`${staticName} has been updated.`);
},
(err) => {
console.warn(`failed to update ${staticName}.`);
}
);
})
.then(() => {
caches.open(imageName).then((cache) => {
cache.addAll(imageAssets).then(
() => {
console.log(`${imageName} has been updated.`);
},
(err) => {
console.warn(`failed to update ${staticName}.`);
}
);
});
})
);
});
self.addEventListener('activate', (ev) => {
// when the service worker has been activated to replace an old one.
//Extendable Event
console.log('activated');
// delete old versions of caches.
ev.waitUntil(
caches.keys().then((keys) => {
return Promise.all(
keys
.filter((key) => {
if (key != staticName && key != imageName) {
return true;
}
})
.map((key) => caches.delete(key))
).then((empties) => {
//empties is an Array of boolean values.
//one for each cache deleted
});
})
);
});
self.addEventListener('fetch', (ev) => {
// ev.request each time the webpage asks for any resource.
//Extendable Event
console.log(`fetch request for: ${ev.request.url}`);
/* */
// version 1 - pass thru
// ev.respondWith(fetch(ev.request));
/* */
// version 2 - check the caches first for the file. If missing do a fetch
// ev.respondWith(
// caches.match(ev.request).then((cacheRes) => {
// if (cacheRes == undefined) {
// console.log(`MISSING ${ev.request.url}`);
// }
// return cacheRes || fetch(ev.request);
// })
// );
/* */
//version 3 - check cache. fetch if missing. then add response to cache
ev.respondWith(
caches.match(ev.request).then((cacheRes) => {
return (
cacheRes ||
fetch(ev.request).then((fetchResponse) => {
let type = fetchResponse.headers.get('content-type');
if (
(type && type.match(/^text\/css/i)) ||
ev.request.url.match(/fonts.googleapis.com/i)
) {
//css to save in dynamic cache
console.log(`save a CSS file ${ev.request.url}`);
return caches.open(dynamicName).then((cache) => {
cache.put(ev.request, fetchResponse.clone());
return fetchResponse;
});
} else if (
(type && type.match(/^font\//i)) ||
ev.request.url.match(/fonts.gstatic.com/i)
) {
console.log(`save a FONT file ${ev.request.url}`);
return caches.open(fontName).then((cache) => {
cache.put(ev.request, fetchResponse.clone());
return fetchResponse;
});
} else if (type && type.match(/^image\//i)) {
//save in image cache
console.log(`save an IMAGE file ${ev.request.url}`);
return caches.open(imageName).then((cache) => {
cache.put(ev.request, fetchResponse.clone());
return fetchResponse;
});
} else {
//save in dynamic cache
console.log(`OTHER save ${ev.request.url}`);
return caches.open(dynamicName).then((cache) => {
cache.put(ev.request, fetchResponse.clone());
return fetchResponse;
});
}
})
);
})
);
});
self.addEventListener('message', (ev) => {
//message from web page ev.data.
//Extendable Event
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment