Gatsby plugin that adds drop-in offline functionality and resistance to bad network connections using Workbox Build.
npx @tessl/cli install tessl/npm-gatsby-plugin-offline@6.15.0A Gatsby plugin that adds drop-in support for making a Gatsby site work offline and more resistant to bad network connections. It uses Workbox Build to create a service worker for the site and loads the service worker into the client.
npm install gatsby-plugin-offlineThis is a Gatsby plugin, so it's configured in your gatsby-config.js file rather than imported directly:
// gatsby-config.js
module.exports = {
plugins: [
'gatsby-plugin-offline'
]
}The most basic setup requires no configuration:
// gatsby-config.js
module.exports = {
plugins: [
'gatsby-plugin-offline'
]
}// gatsby-config.js
module.exports = {
plugins: [
{
resolve: 'gatsby-plugin-offline',
options: {
precachePages: ['/about-us/', '/projects/*'],
appendScript: require.resolve('src/custom-sw-code.js'),
debug: false,
workboxConfig: {
importWorkboxFrom: 'cdn',
runtimeCaching: [
{
urlPattern: /^https?:.*\.(png|jpg|jpeg|webp|svg|gif|tiff|js|woff|woff2|json|css)$/,
handler: 'StaleWhileRevalidate',
}
]
}
}
}
]
}gatsby-plugin-offline integrates with Gatsby's build process to automatically generate and configure service workers for offline functionality:
interface PluginOptions {
precachePages?: string[];
appendScript?: string;
debug?: boolean;
workboxConfig?: WorkboxConfig;
}precachePages?: string[]An array of page globs whose resources should be precached by the service worker.
Example:
// gatsby-config.js
{
resolve: 'gatsby-plugin-offline',
options: {
precachePages: ['/about-us/', '/projects/*']
}
}appendScript?: stringA file path to be appended at the end of the generated service worker.
Example:
// gatsby-config.js
{
resolve: 'gatsby-plugin-offline',
options: {
appendScript: require.resolve('src/custom-sw-code.js')
}
}// src/custom-sw-code.js
// Show a notification after 15 seconds
setTimeout(() => {
self.registration.showNotification("Hello, world!")
}, 15000)
// Register a custom navigation route
const customRoute = new workbox.routing.NavigationRoute(({ event }) => {
// Custom route logic
})
workbox.routing.registerRoute(customRoute)debug?: booleanSpecifies whether Workbox should show debugging output in the browser console at runtime. When undefined, defaults to showing debug messages on localhost only.
workboxConfig?: WorkboxConfigAllows you to override the default Workbox configuration. See the Workbox Configuration section for details.
The workboxConfig option allows complete override of the default Workbox Build configuration:
interface WorkboxConfig {
importWorkboxFrom?: 'local' | 'cdn';
globDirectory?: string;
globPatterns?: string[];
modifyURLPrefix?: Record<string, string>;
cacheId?: string;
dontCacheBustURLsMatching?: RegExp;
maximumFileSizeToCacheInBytes?: number;
runtimeCaching?: RuntimeCachingRule[];
skipWaiting?: boolean;
clientsClaim?: boolean;
}interface RuntimeCachingRule {
urlPattern: RegExp;
handler: 'CacheFirst' | 'NetworkFirst' | 'StaleWhileRevalidate' | 'NetworkOnly' | 'CacheOnly';
options?: {
networkTimeoutSeconds?: number;
};
}The plugin uses the following default Workbox configuration:
const defaultWorkboxConfig = {
importWorkboxFrom: 'local',
globDirectory: 'public',
modifyURLPrefix: {
"/": `${pathPrefix}/`,
},
cacheId: 'gatsby-plugin-offline',
dontCacheBustURLsMatching: /(\.js$|\.css$|static\/)/,
runtimeCaching: [
{
urlPattern: /(\.js$|\.css$|static\/)/,
handler: 'CacheFirst',
},
{
urlPattern: /^https?:.*\/page-data\/.*\.json/,
handler: 'StaleWhileRevalidate',
},
{
urlPattern: /^https?:.*\.(png|jpg|jpeg|webp|avif|svg|gif|tiff|js|woff|woff2|json|css)$/,
handler: 'StaleWhileRevalidate',
},
{
urlPattern: /^https?:\/\/fonts\.googleapis\.com\/css/,
handler: 'StaleWhileRevalidate',
},
],
skipWaiting: true,
clientsClaim: true,
}This plugin implements several Gatsby plugin hooks that are called automatically during the build process. These are not directly callable by users but are part of the plugin's internal API:
function onPreBootstrap(args: GatsbyNodeArgs): voidCopies the app shell component to the cache directory during bootstrap.
function createPages(args: GatsbyNodeArgs): voidCreates the offline app shell fallback page at /offline-plugin-app-shell-fallback/ in production builds.
function onPostBuild(args: GatsbyNodeArgs, options: PluginOptions): Promise<void>Main plugin logic that:
function registerServiceWorker(): booleanDetermines whether to register the service worker (excludes preview mode).
function onServiceWorkerActive(args: ServiceWorkerActiveArgs): void
interface ServiceWorkerActiveArgs {
getResourceURLsForPathname: (pathname: string) => string[];
serviceWorker: ServiceWorkerContainer;
}Handles service worker activation by:
function onRouteUpdate(args: RouteUpdateArgs): void
interface RouteUpdateArgs {
location: Location;
getResourceURLsForPathname: (pathname: string) => string[];
}Updates cached resources on route changes and enables the offline shell.
function onPostPrefetchPathname(args: PrefetchArgs): void
interface PrefetchArgs {
pathname: string;
getResourceURLsForPathname: (pathname: string) => string[];
}Caches resources for prefetched pages to improve offline experience.
function onPreRenderHTML(args: PreRenderHTMLArgs): void
interface PreRenderHTMLArgs {
getHeadComponents: () => React.ReactNode[];
pathname: string;
replaceHeadComponents: (components: React.ReactNode[]) => void;
}Filters head components for the offline app shell page to prevent preloading of page-specific resources.
function onRenderBody(args: RenderBodyArgs): void
interface RenderBodyArgs {
pathname: string;
setHeadComponents: (components: React.ReactNode[]) => void;
}Adds a noscript fallback for the offline app shell page that redirects to disable the offline shell.
The plugin automatically generates a service worker that includes:
The service worker exposes a message API for communication with the main thread:
// Messages that can be sent to the service worker
interface ServiceWorkerMessage {
gatsbyApi: 'setPathResources' | 'clearPathResources' | 'enableOfflineShell' | 'disableOfflineShell';
path?: string;
resources?: string[];
}The service worker includes custom navigation route handling that:
The plugin generates several files during the build process:
public/sw.js)A complete service worker with:
A minimal React component at /offline-plugin-app-shell-fallback/ that serves as a fallback for offline navigation.
A versioned copy of the idb-keyval library for client-side resource caching in IndexedDB.
When using with gatsby-plugin-manifest, ensure gatsby-plugin-offline is listed after gatsby-plugin-manifest in your plugin configuration:
// gatsby-config.js
module.exports = {
plugins: [
{
resolve: 'gatsby-plugin-manifest',
options: {
icon: 'src/icon.svg',
cache_busting_mode: 'none'
}
},
{
resolve: 'gatsby-plugin-offline',
options: {
workboxConfig: {
globPatterns: ['**/icon-path*']
}
}
}
]
}If manifest icons aren't being cached, update your configuration:
{
resolve: 'gatsby-plugin-manifest',
options: {
icon: 'icon.svg',
cache_busting_mode: 'none' // Required for proper caching
}
},
{
resolve: 'gatsby-plugin-offline',
options: {
workboxConfig: {
globPatterns: ['**/icon-path*'] // Include icon patterns
}
}
}To safely remove the plugin from an existing site:
npm install gatsby-plugin-remove-serviceworker
npm uninstall gatsby-plugin-offline// gatsby-config.js
module.exports = {
plugins: [
'gatsby-plugin-remove-serviceworker' // Replaces gatsby-plugin-offline
]
}This ensures the service worker is properly unregistered from users' browsers.