The presentation which I was using during my talk at EPAM Lviv JS community about offline-first applications. Contains high-level review of tools and web platform to submerge folks in a world of offline-first thinking.
2. 2
Agenda
● Why Do We Need Offline-First Design?
● Browser APIs Essential For Reliable Web
Apps.
● The Most Common UI/UX Patterns.
● Offline Storage With Replication to a Server.
● Challenges when you build Offline-First Apps.
11. 11
Web has evolved and ready to compete with native apps
Pros (compare to native apps):
● No installation.
● It may take less space.
● Web apps are way more secure
12. 12
Web has evolved and ready to compete with native apps
Pros (compare to native apps):
● No installation.
● It may take less space.
● Web apps are way more secure
Cons:
● Lower performance
● Less APIs available.
14. 14
HTML5 Application Cache
Pros:
Extremely easy to use.
Older browsers support it, only option in IE 10 & IE 11.
Cons:
Can be served over insecure HTTP.
Lacks flexibility.
Will be removed soon in new browsers.
<html manifest="cache.mf">
...
CACHE MANIFEST
style.css
image.png
# Use from network if available
NETWORK:
list.json
FALLBACK:
example/bar/ example.html
20. 20
Service Worker Install Event
const cacheCriticals = () => {
return caches.open(CACHE_NAME).then(cache => {
// important, but not critical
cache.addAll(resourcesToCache);
// critical resources
return cache.addAll(criticalResources);
});
};
self.addEventListener('install', function (installEvent) {
installEvent.waitUntil(cacheCriticals());
});
21. 21
Service Worker Activate Event
function cleanup(cacheNames) {
return Promise.all(
cacheNames.filter(function (cacheName) {
return cacheName !== CACHE_NAME;
}).map(function (cacheName) {
return caches.delete(cacheName);
})
);
}
self.addEventListener('activate', function(event) {
event.waitUntil(caches.keys().then(cleanup));
});
*Old service worker is paused at that moment. Fetch requests will be added to queue..
22. 22
Service Worker Fetch Event
self.addEventListener('fetch', function(event) {
// magic goes here
});
*The request is attended by the most specific SW only.
23. 23
Service Worker Fetch Event
self.addEventListener('fetch', function(event) {
event.respondWith(fetch(event.request));
});
*The request is attended by the most specific SW only.
26. 26
Workbox
Offline Caching:
● Cache only
● Cache first, falling back to network
● Cache, with network update
● Network only
● Network first, falling back to cache
Offline Analytics:
Workbox can collect user analytics while offline.
28. 28
Workbox
You can integrate it with:
Or use it directly in the service worker:
//synchronously imports scripts into the worker's scope
importScripts('/node_modules/workbox-sw/build/workbox-sw.vX.X.X.prod.js');
const workboxSW = new WorkboxSW();
const networkFirst = workboxSW.strategies.networkFirst();
workboxSW.router.registerRoute('/schedule', networkFirst);
29. 29
BackgroundSync DEMO
Service Worker Background Sync
// sync will fire when the user agent believes the user has connectivity
self.addEventListener('sync', function(event) {
if (event.tag === ‘anyTag’) event.waitUntil(doWhatYouWant());
});
Finally, we have a better option than WindowEventHandlers.onbeforeunload
31. 31
Browser Storage APIs
Cache API (part of Service Worker). - use it for URL addressable resources.
IndexedDB - use it for all other data. (Also, exist polyfills with fallback to Web
SQL).
32. 32
Browser Storage APIs
Cache API (part of Service Worker). - use it for URL addressable resources.
IndexedDB - use it for all other data. (Also, exist polyfills with fallback to Web
SQL).
LocalStorage - Has no Web Worker. But it is persistent storage by default!
33. 33
Browser Storage APIs
Cache API (part of Service Worker). - use it for URL addressable resources.
IndexedDB - use it for all other data. (Also, exist polyfills with fallback to Web
SQL).
LocalStorage - Has no Web Worker. But it is persistent storage by default!
Space available to origin is shared between all forms of storage above.
There is no standard way to check quota. We have two
experimental APIs: Quota Management API and Storage
Manager API.
35. 35
Be Aware of Cache Eviction in Browsers
*If app is not installed by user (Chrome, FF) or don’t have
high engagement.
Chrome LRU once Chrome runs out of
space
Firefox LRU if the whole disk gets full
Safari & Edge No cache eviction
!! It includes Indexed DB and Cache API.
36. 36
Be Aware of Cache Eviction in Browsers
*If app is not installed by user (Chrome, FF) or don’t have
high engagement.
Chrome LRU once Chrome runs out of
space
Firefox LRU if the whole disk gets full
Safari & Edge No cache eviction
!! It includes Indexed DB, Cache API.
navigator.storage.persist().then(function(isPersistent) {
// isPersistent will be true if user allowed
})
38. 38
● Try to provide offline by default if your app doesn't
require much data.
● Treat a connection to the internet as an enhancement
instead of a dependency
● Use optimistic UI approach if possible.
● User must be properly notified about app state.
● Use save for offline button
● Precache things that needed with high probability
offline especially if they are small
Core ideas
39. 39
Connection is enhancement not a dependency
You can create new google doc while you offline.
Once we connect to internet it will be synced.
40. 40
Use optimistic ui approach if possible
avoid that approach
if possible
If we offline, sync that action later.
42. 42
Use save for offline button
Especially important
approach for content
oriented applications
like:
● Spotify
● Google maps
● Web readers
● e.t.c
43. 43
Cache things automatically
● Do you users often use that
feature?
● Can it be useful offline?
● Is it lightweight?
● Is it not sensitive data?
If answer yes for all
Pre-cache it without asking.
49. 49
PouchDB + CouchDB
CouchDB is was designed from the bottom-up to
enable easy synchronization between databases.
{
"_id": "any_string",
"_rev": "1-bea5fa18e06522d12026f4aee6b15ee4"
"name": "John",
...
}
50. 50
PouchDB + CouchDB
Pros:
● Production ready. Well tested
● Nice documentation.
● Wide browser support.
Cons
● You are tight to a specific DB which supports its sync
protocol on backend.
● Poor automatic conflict resolution*
● Not good for real time apps.
*The winner is the version with the longest revision history
And in case of a tie, the winner is the revision with the lexicographically highest
revision ID; e.g. "12-F4B2..." beats "12-42AA..."
58. 58
More about CRDT
Well known CRDTs
● G-Counter (Grow-only Counter)
● PN-Counter (Positive-Negative Counter)
● G-Set (Grow-only Set, which only allows adding)
● 2P-Set (Two-Phase Set, remove-wins" set)
● LWW-Element-Set (Last-Write-Wins-Element-Set)
● e.t.c
CRDT provides strong eventual consistency (SEC)
It means that if all nodes get all updates in whatever order they will come to
the same state. If you use inappropriate type you may get messy state, although it will be
consistent across app.
59. 59
CRDT is not a silver bullet
Cannot model every data type..
60. 60
Swarm.js
Pros
● Real time replication
● Automatic conflict resolution
● Need little data to transfer (CmRDT)
Cons
● It is kind of research project
● Almost no documentation
● Vague future
61. 61
Logux
Pros
● In active development
● Very flexible
● Redux API
● Foundation for CRDT
Cons
● Very young project
Library inspired by Redux and Swarm.js
62. 62
Gun.js
Pros
● In active development
● With real time in mind
● Looks like best open source solution
● Integrates with different Backend DBs
Cons
● Not mature enough
64. 64
- Some useful API still not standardized
- Find security/convenience ballance.
- Handling multiple users on one machine.
- Educate through UI users about what is working offline
- Wise Caching. (Do not force user to download whole
site on first visit.)
- Mobile traffic costs a lot in some places.
- Data synchronization tools is quite immature.
- New auto testing challenges (Panic Server)
Challenges when you build Offline-First Apps
66. 66
More to read
- Repository with with information related to offline-first apps
- Problems of AppCache
- About Service Workers
- Is Service Worker Ready
- Read more about Workbox
- Good Article About Optimistic UI
- Complete Gun.js tutorial
- Read blog of Swarm.js developer
- More About Logux: YouTube Video
- CRDT original paperwork
- Security thoughts about offline apps
- Unit-testing-service-worker
- Background Sync
- My Offline-First App (Slightly Unfinished)