Going Offline with Preact CLI
Preact CLI automatically pre-caches your application code and prerendered data for offline use.
Preact CLI version 3 comes bundled with workbox. It uses the InjectManifest plugin to generate a flexible service worker that covers many use cases right out of the box.
Note: Preact CLI fetches navigation requests using a network-first approach, so users will always see fresh content unless they are offline.
Adding a custom service worker
Without writing any code, Preact CLI will generate a service worker when building your application for production. To customize the service worker, Preact CLI provides a high-level API for that can be imported and used in an sw.js
file in your project:
1. Create a sw.js
file within your src/
directory
package.json
src/
index.js
sw.js
2. Import Preact CLI's service worker library, preact-cli/sw
import { getFiles, setupPrecaching, setupRouting } from 'preact-cli/sw';
3. Enable offline routing
This sets up the network-first fallback behaviour for offline users.
Skip this if you want a custom setup for offline fallback behavior.
import { getFiles, setupPrecaching, setupRouting } from 'preact-cli/sw';
setupRouting();
Run in REPL4. Enable pre-caching of resources
The getFiles()
function returns an Array of URLs generated at build time that should be cached for offline use.
These URLs can be passed to setupPrecaching()
to download and store them in the cache used by setupRouting()
.
import { getFiles, setupPrecaching, setupRouting } from 'preact-cli/sw';
setupRouting();
const urlsToCache = getFiles();
setupPrecaching(urlsToCache);
Run in REPL4.1 Adding other assets to precache manifest
In order to add anything else to the pre-cache manifest, you can use urlsToCache
object in the above example and push another entry({url, revision}) to it. e.g.
import { getFiles, setupPrecaching, setupRouting } from 'preact-cli/sw';
setupRouting();
const urlsToCache = getFiles();
urlsToCache.push({url: '/favicon.ico', revision: null});
setupPrecaching(urlsToCache);
Run in REPLThe revision in the above example is used to invalidate the resource if it changes. If the URL has this info(e.g. a hash) then feel free to leave it
null
.
5. Add your custom service worker logic
Now that the default Preact CLI functionality has been added to your custom service worker, you can now change or extend it to suit your needs - whether that's customizing the list of URLs to precache or setting up push notifications.
Adding other routes to runtime caching
To add runtime caching of other routes or API calls, first create a custom sw.js
by following the steps above. Then, use the Workbox API to customize your service worker:
import { registerRoute } from 'workbox-routing';
import { NetworkOnly } from 'workbox-strategies';
registerRoute(
({url, event}) => {
return (url.pathname === '/special/url');
},
new NetworkOnly() // or: CacheFirst/CacheOnly/StaleWhileRevalidate
);
Run in REPLIn the example above, using the networkOnly
strategy means /special/url
will never be cached by the service worker.
Note: Any custom routing code should be placed before
setupRouting()
.
Using other workbox modules in your service worker
Preact CLI uses InjectManifestPlugin to compile the service worker. This means that in order to use any other workbox module you'll need to install them via NPM and use them in you src/sw.js
by importing them.
Example: Adding Background sync
The following code can be added to your custom sw.js
. It uses Workbox Background Sync to retry API requests that failed when the user was offline.
import { getFiles, setupPrecaching, setupRouting } from 'preact-cli/sw';
import { BackgroundSyncPlugin } from 'workbox-background-sync';
import { registerRoute } from 'workbox-routing';
import { NetworkOnly } from 'workbox-strategies';
const bgSyncPlugin = new BackgroundSyncPlugin('apiRequests', {
maxRetentionTime: 60 // retry for up to one hour (in minutes)
});
// retry failed POST requests to /api/**.json
registerRoute(
/\/api\/.*\/.*\.json/,
new NetworkOnly({
plugins: [bgSyncPlugin]
}),
'POST'
);
/** Preact CLI setup */
setupRouting();
const urlsToCache = getFiles();
setupPrecaching(urlsToCache);
Run in REPL