There are a few situations where the internet connection isn't optimal, but you still want to check your phone for news, social media, or other websites. If you want to have a good offline experience, there's usually no way around native mobile apps.
Periodic background syncs are a feature of service workers that brings native features to the web. Like the name already tells us, it allows websites to periodically fetch data in the background without any user interaction, so when users open the site again, they'll be able to read the latest news, even without having an internet connection.
In this article, I'll explain how this works and how you can easily add periodic background syncs to your web application as well.
If you already want to see some code, you can check out the example project I created for this tutorial.*
This feature is part of Project Fugu, a cross-company effort, brought to life by Google, to make the web more powerful. Click here to read more about it.
Watch my PWA online course 📹
You can now watch my course on how to turn your React app into a PWA on Skillshare. Learn what you need to know to get started, and turn your React app into a PWA in just 10 minutes.
Watch it for free with my referral link, which will give you a 14 day trial.
How it works
As you already might know, service workers enable offline capabilities by caching the application code of the website. This means that when the user opens the app, he won't have to wait for the necessary HTML, JavaScript, and CSS to load.
While this greatly improves the page load on subsequent visits, usually, the data that users actually want to see is dynamic. With the current web APIs, there's no way of providing fresh data without an internet connection because we're limited to fetch data while the user is on our website.
The periodic background sync API is here to solve this problem — something that previously only native applications were able to do. Using this API, we're able to provide users with new data even when they don't have an internet connection.
Let's say you want to read the latest news articles on the subway ride to work, but the internet connection is less than optimal. The latest news articles can be fetched periodically in the background, so the user will see relevant data, even without an internet connection.
Periodic background sync !== background sync
Even though these two APIs have similar names, their intention is quite different. Background syncs are usually used for sending data after the user left the page, while the periodic background sync synchronizes data in the background without any user interaction.
Don't always use this
While this API is a nice way to improve the loading times of frequent users, you shouldn't always use it. Consider checking network conditions and the available storage before making a request.
You shouldn't unnecessarily waste precious mobile bandwidth for data the user probably isn't going to need.
Prerequisites
To prevent websites from abusing this, there are a few things your site needs before periodic background syncs are enabled.
In addition to these prerequisites, make sure that your browser is supported.
Progressive Web App
Your site needs to be a Progressive Web App and it needs to be installed to register a periodic background sync.
Internet connection
The sync only happens on internet connections that the device has been connected to before. This is a security measure to prevent doing network requests on untrusted networks.
Site engagement score
Of course, there are concerns about security and extensive data usage when adding an API that allows JavaScript to be executed without any user interaction. That's where Chromium's site engagement score comes into play, which aims to prevent the misuse of this API.
The site engagement score a number between 0 and 100 that is calculated based on how much a user interacts with a website. It also takes into consideration whether the application is installed. You can read more about this on the Chromium website.
For the periodic background sync, this means that the frequency of the possible syncs depends on this score. In the following table, you can see the frequency in hours for a given level of engagement.
Engagement Score | Periodic Sync |
---|---|
NONE | Never |
MINIMAL | 36 |
LOW | 24 |
MEDIUM | 24 |
HIGH | 12 |
MAX | 12 |
The MINIMAL bucket represents ~25% of sites, whereas the LOW bucket represents a further ~65% of sites. This means that for most of the sites, they’ll only get the opportunity to sync in the background every 24 or 36 hours, for the service worker execution timeout period, which is 3 minutes in the current implementation. Source
You can check your own engagement scores under chrome://site-engagement/
.
Implementation
Enough theory, let's have a look at how you can use this feature in your PWA. For this article, I created a GitHub repository where I tried everything out.
How to register a periodic background sync?
Before we can register a new sync we need to check whether we have the permission to do so. The permission is only granted if the app is installed and we're using a Chromium browser.
const status = await navigator.permissions.query({
name: 'periodic-background-sync',
});
if (status.state === 'granted') {
// Continue registering the periodic sync
}
If the permission is granted, we can proceed to register a periodic sync:
if (status.state === 'granted') {
await registration.periodicSync.register('news', {
minInterval: 24 * 60 * 60 * 1000, // 1 day in ms
});
}
Putting all of this together, we'll end up with something like this in our code:
// Check if service workers are supported
if ('serviceWorker' in navigator) {
const registration = await navigator.serviceWorker.ready;
// Check if periodicSync is supported
if ('periodicSync' in registration) {
// Request permission
const status = await navigator.permissions.query({ name: 'periodic-background-sync', }); if (status.state === 'granted') {
try {
// Register new sync every 24 hours
await registration.periodicSync.register('news', { minInterval: 24 * 60 * 60 * 1000, // 1 day }); console.log('Periodic background sync registered!');
} catch(e) {
console.error(`Periodic background sync failed:\n${e}`);
}
}
}
}
In the service worker, we then need to listen to the periodicsync
event and update the cache.
In this example, fetchAndCacheNews
fetches the latest news and adds them to the cache (see the source
code here).
self.addEventListener('periodicsync', (event) => {
if (event.tag === 'news') {
console.log('Fetching news in the background!');
event.waitUntil(fetchAndCacheNews());
}
});
And that's already everything we need to do. In the next section, I'll show you how you can check if your code is working.
Debugging
The features mentioned in this section are available in Chrome v81 or later.
Since periodic background syncs only work when the web application is installed, you need to do so for debugging as well.
In Google Chrome you'll find a small +
sign on the right side of the URL bar. This only appears if you're not browsing
in incognito mode and your PWA is installable (go to DevTools > Lighthouse for debugging issues with this).
Trigger periodic syncs
Once installed, you hit F12
to open the DevTools. Under Application
> Service Worker
, you can trigger a periodic sync.
Specify the tag name of your sync (in our case news
) and press the Periodic Sync
button to simulate a sync.
Record activity
In the left menu of the Application
tab, you'll find Periodic Background Sync
. If you hit the record button, Chrome will
record all local periodic sync events for up to 3 days.
Browser Support
The periodic sync API is currently only supported by Chromium-based browsers. As of writing this article, this is Chrome v80, Edge v80, Android Browser v81, and Chrome for Android v81. You can check out the latest update on caniuse.com.
According to the Chrome Platform Status, Firefox and Safari haven't shown any public signals about this API. This, however, might change if it proves useful to Chromium-based browsers.
Conclusion
While fetching data at a maximal frequency of 12 hours, and only on Chromium browsers, might not seem like a big benefit, it's a step in the right direction, adding more native features to the web. If it proves valuable, other browsers will catch up as well.
Given that there are very few changes necessary to implement this, it might be worth adding it to existing projects anyway and by this, improve the user experience of Chromium users. Just make sure to check for compatibility before using the API.
I'm excited about the future of this technology and other features that hopefully will come to the web as well.
If you've come so far and you're still curious about Progressive Web Apps, you can check out my other articles on PWAs and subscribe to my newsletter to get my latest content by email.