New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a Service Worker for offline support #2917
Comments
The offline-plugin run into some issue with CDN_HOST usage on glitch.social, and I had no idea how to debug this in production, so I gave up until it's in a separate PR by someone who knows more than me. |
I have some experience with SWs and would like to look into this. (Not trying to prevent anyone else from working on it; just declaring my intent to tackle this next. 😄) |
@beatrix-bitrot Do you remember what the issue was that you ran into with Service Worker + CDN? I have a local production environment I can test in. |
I've been looking into this a bit (see this branch). I have a solution that mostly works – it's able to register a ServiceWorker to statically cache all the Webpack assets, including fixing the CDN_HOST problem. Unfortunately there's not much point yet, because as of right now this solution isn't buying us much unless it can cache the actual |
OK, in order to solve this problem AFAICT we will need the following:
I'm not sure I see any other way around this, but then again I'm also extremely ignorant of Rails and HAML. |
I want to address some issues that we might face building a SW
All this blathering is about describing all the things (some ideas) that we need to do while using a ServiceWorker. I sincerely think that we should be writing our own SW anyway (even if we wanted to implement push notifications in the future). It's not totally perfect or complete. Any other suggestions or corrections are highly accepted. 😊 Sample SW code// sw.js
'use strict';
// May store these in indexedDB
const NAME = require('../package.json').name;
const VERSION = require('../package.json').version;
importScripts('files-to-cache.js'); // To be generated by webpack
self.oninstall = evt => {
evt.waitUntil(
caches
.open(`${NAME}-v${VERSION}`)
.then(cache => {
// Add all static assests from the list generated by webpack
// which includes 404 error page
})
);
self.skipWaiting();
};
// When new SW is installed
self.onactivate = _ => {
const currentCacheName = `${NAME}-v${VERSION}`;
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if (cacheName.indexOf(NAME) === -1) {
return null;
}
if (cacheName !== currentCacheName) {
return caches.delete(cacheName);
}
return null;
})
);
});
self.clients.claim();
};
self.onfetch = evt => {
const FETCH_TIMEOUT = 10000;
const request = evt.request;
evt.respondWith(
caches.match(request)
.then(response => {
// Check if the request is to the API or to assests
// and act accordingly
// API requests return json data from cache that are not too old
// And any other requests to the assests are mostly cached
// or else thay are fetched and served (but not cached)
// If the request is for an emoji, the code from above
// is suitable for managing the requests
if (response) {
return response;
}
return Promise.race([
fetch(evt.request),
new Promise(resolve => {
setTimeout(resolve, FETCH_TIMEOUT);
})
]).then(response => {
if (response) {
return response;
}
return caches.match('/404/');
});
);
};
self.onmessage = event => {
// If user logs out, purge cache
}; if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js', {
scope: './'
}).then(registration => {
// SW updates
registration.onupdatefound = _ => {
let newWorker = registration.installing;
newWorker.addEventListener('statechange', _ => {
if (newWorker.state === 'activated' && navigator.serviceWorker.controller) {
// View a toast saying "Update available"
}
});
};
});
} |
@ramlmn Thanks for the feedback! I still think we should go with offline-plugin vs a fully custom service worker, because Right now I am trying to work solely on solving the HTML problem, which is tricky because of the CSRF token. I could also submit what I already have, but it will only do offline caching of JS/CSS/etc resources and wouldn't fully work offline. |
OK, I've made more progress this morning. I've solved the HTML issue (by configuring To respond to @ramlmn:
So basically the "offline mode" as I envision it is merely the fact that static assets and HTML are cached offline, so the user can read stale toots while offline, but nothing else works without a network connection. This is roughly how the Twitter native app seems to work, so it seems reasonable for a first pass. Hopefully I'll be able to submit a PR by the end of this weekend. 😃 Next steps:
|
I've filed an issue on |
You may just straight add Let me know if you need any help with SW/ |
Implementing |
@rixx See nolanlawson/blob-util#29, there are only a few tasks remaining. :) |
We do have a service worker now... |
(Opening an issue to allow for some discussion, rather than just submitting a big ambitious PR.)
A Service Worker would give Mastodon offline support for static assets, improve overall performance, and also provide an "install to home screen" prompt in supported browsers (notably Chrome and Opera, soon Firefox and Edge). It could also fall back to Application Cache to support non-SW browsers like Safari and Edge.
It seems to me that the offline-plugin would be the best candidate here, since it uses Webpack's innate understanding of the asset graph (perhaps at the expense of removing more control over the Service Worker itself though).
I noticed there was already some preliminary work on this in #2617 but it got abandoned. I started picking this up again myself (see this commit) but so far I don't have the SW actually working yet (probably due to a misconfiguration in offline-plugin).
Goals:
Questions:
sw.js
file? I believe the spec tells browsers to ignore Cache-Control and update it every ~24 hours, but this is worth verifying.master
(If you're a user, don't worry about this).The text was updated successfully, but these errors were encountered: