Skip to content

Instantly share code, notes, and snippets.

@Chaphasilor
Created October 17, 2019 08:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Chaphasilor/a7708f85341cdbfe8819e3431f27bb3f to your computer and use it in GitHub Desktop.
Save Chaphasilor/a7708f85341cdbfe8819e3431f27bb3f to your computer and use it in GitHub Desktop.
Some code for twelve70
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="theme-color" content="#121212">
<title>Example Page for twelve70</title>
<link rel="manifest" href="./manifest.webmanifest">
</head>
<body>
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
navigator.serviceWorker.register('./sw.js').then(function (registration) {
// Registration was successful
// console.log('ServiceWorker registration successful with scope: ', registration.scope);
}, function (err) {
// registration failed :(
console.error('ServiceWorker registration failed: ', err);
});
});
}
</script>
</body>
</html>
{
"short_name": "twelve70",
"name": "twelve70 - mens outfit calculator",
"description": "A tool to help you pick an outfit that matches in color and style!",
"icons": [
{
"src": "android-icon-36x36.png",
"sizes": "36x36",
"type": "image/png",
"density": "0.75"
},
{
"src": "android-icon-48x48.png",
"sizes": "48x48",
"type": "image/png",
"density": "1.0"
},
{
"src": "android-icon-72x72.png",
"sizes": "72x72",
"type": "image/png",
"density": "1.5"
},
{
"src": "android-icon-96x96.png",
"sizes": "96x96",
"type": "image/png",
"density": "2.0"
},
{
"src": "android-icon-144x144.png",
"sizes": "144x144",
"type": "image/png",
"density": "3.0"
},
{
"src": "android-icon-192x192.png",
"sizes": "192x192",
"type": "image/png",
"density": "4.0"
}
],
"background_color": "#f3f3f3",
"theme_color": "#121212",
"start_url": "/",
"scope": "/",
"display": "standalone",
"orientation": "portrait-primary"
}
var cacheName = 'siteCache';
var urlsToCache = [
'/',
'/js/app.js?id=26497c63fc3241f91fe6',
'/css/app.css?id=405c791f984aee167ca3',
'/css/shared.css?id=436b54b159887bac1dfc',
'/css/main.css?id=f4aed1a982eb3149c8b9',
'/js/myscript.js?id=e895ac1c23c2ad01e0bc',
];
// on installation of the service worker, create a new cache an load all configured urls into it
self.addEventListener('install', function (event) {
// Perform install steps
event.waitUntil(
caches.open(cacheName)
.then(function (cache) {
console.log('Opened cache');
return cache.addAll(urlsToCache);
})
);
});
// if content is loaded, the service worker will act as a proxy and respond with the cached resource if available
//! it is possible, that changes you make to the files in urlsToCache won't be reflected to the user until their cache is wiped. maybe look for a different caching strategy, or don't use caching at all?
self.addEventListener('fetch', function (event) {
event.respondWith(
caches.match(event.request)
.then(function (response) {
// Cache hit - return response
if (response) {
return response;
}
return fetch(event.request);
}
)
);
});
@rubanraj7
Copy link

Thanks for doing this.
Got a question though, do I manually need to change the .js files to cache everytime I recompile them?
How will the sw know when to pull an updated js file?

@Chaphasilor
Copy link
Author

You shouldn't have to compile JavaScript at all, it's a scripting language which normally is not complied, only executed.

The service worker, as configured currently, will always cache the listed files when the user visits the site for the first time. Because the files are cached and the service worker doesn't check for updates, these cached files might never get updated and cause problems down the line. The options you have here are either
a) not caching at all
b) trying to load the online files and only serving the cached ones, if the online version can't be loaded (user is offline). this way the cached files are always up-to-date, as they are replaced every time the site is loaded
c) serve the cached files, but have them expire after a certain amount of time, so they have to be re-cached

for your lightweight website you actually don't really need caching at all, but it's good practice to implement it. I'd recommend c) for your website. If you want me to, I could implement this for you

@rubanraj7
Copy link

Well, I'm using a compiler to minify it and add a unique string at the end for cache busting purposes.
Is there an alternate solution I should be looking at?
C) does seem to be best. Is the cache expiry setting applied in the script you provided?

@Chaphasilor
Copy link
Author

Ah okay, I see what you mean. You're building the code, not actually compiling it. Minifying is great, but I don't know how that unique string would help with cache busting. As long as the unique string is not part of the file name, the browser will still think the cached version is the most recent one and won't even try to look for an updated version.

The cache expiry is not set in my current skript, but I'll add over the course of the next few hours.

I'm thinking about maybe a 3 day caching time, that way any updates you push will be available to any active user after 3 days at the latest. They can always clear their cache or do a force-reload (using ctrl-F5) to get the latest files.

@Chaphasilor
Copy link
Author

It would be great if you could compile me a list of all the files in your app that are mostly static, like icon paths, scripts and static html pages.
I haven't looked into how exactly you are accessing your matching algorithm, but if it's through a script and not through a server, we could basically cache all pages and make the whole app work more or less offline :)

@rubanraj7
Copy link

3 days would be great. I need to somehow show my appreciation for this when I have some more time to spare. I've been looking for people to bounce ideas off of and get advice, would have never thought Reddit would be this awesome. Thank you.

Ok so currently it is server based. But if I am understanding you correctly, if I was to make it into an API, then it could live offline?

@Chaphasilor
Copy link
Author

Hey, no problem at all! I enjoy doing this stuff and it would make me happy to see you implementing this on your page :)

I think I also found a better solution to our caching problem, if you are building your scripts anyway an are appending a custom id, you could simply do the same with the service worker! I discovered that the browser always checks for a new service worker version and ignored the cache for that check, so if you change any of your files and rebuild the code, just increment the service worker's version and all files will be cached again! I'm currently not caching any other files or requests, so if you are loading new fashion data from the server, it will always be the latest version.

To answer your second question, no, not really. Because you would still need the actual fashion data from your server, so there would still be requests. You'd need to preconfigure all combinations and download them to the users device, with is neither practical nor possible in you case. BUT, if you would use an API and load your data in the background through JavaScript, then your site would feel much more like an app! You could cache all sites (excluding images or other, dynamic files) and simply load the needed data once the page is opened. The nice thing about this approach is that you could show loading animations or other eye-candy while you're retrieving the data.

For now, only the homepage and a few static pages would be cached (which btw I still need from you), but all pages showing results would be fetched from the server. That's not such a big deal because your page is rather light-weight. But in order to be able to install the site as an app we need a service worker that handles network requests one way or another, and if we need to handle this anyway why not just cache a few things ;)

I hope this wasn't too complicated to understand, but if it was just say it and I'll try to make it a bit less abstract :)

@rubanraj7
Copy link

Sorry for the delayed reply, things have ramped up in the sense that we are making decisions as to which way we take this thing.

That is all making sense the more I read into it and understand what is happening behind the scenes.
I wonder if a good start is to make the user's favourites available offline since these are tied to user accounts.

When you say that you need the homepage from me, do you need the actual file?

@Chaphasilor
Copy link
Author

Yes, depending on how you access/save the favorites, you really could save those offline. Although this would likely have nothing to do with service workers, instead you would use IndexedDB for this (again, this depends on how you access the favorites).

what I mean by needing the files is I'd need the links to all the static content on your page, images, home pages, faq site, anything that is static. Then I could include those files in the cached pages.
Alternatively you could also send me the source code of the site, just make sure to remove any api keys or other secrets...

@rubanraj7
Copy link

Hey, are you still around to assist with this?

@Chaphasilor
Copy link
Author

Chaphasilor commented Dec 28, 2019

Technically, yes. I don't have too much time at hand and honestly havent used the site in weeks, but I'm still interested :D
You have a Discord or Slack?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment