Skip to main content

@gasket/plugin-service-worker Examples

Basic Plugin Configuration

// gasket.js
import { makeGasket } from '@gasket/core';
import pluginServiceWorker from '@gasket/plugin-service-worker';

export default makeGasket({
plugins: [
pluginServiceWorker
],
serviceWorker: {
url: '/sw.js',
scope: '/',
content: '', // Optional initial content
cacheKeys: [(req) => req.headers['accept-language'] || 'en-US'],
cache: {
maxAge: 1000 * 60 * 60 * 24 * 5, // 5 days
updateAgeOnGet: true
},
minify: {
compress: true,
mangle: true
},
webpackRegister: true,
staticOutput: false
}
});

getSWRegisterScript Action

Next.js App Router

// app/layout.js
import gasket from '../gasket.js';

export default async function RootLayout({ children }) {
const swRegisterScript = await gasket.actions.getSWRegisterScript();

return (
<html lang="en">
<body>
<main>{children}</main>
<div dangerouslySetInnerHTML={{ __html: swRegisterScript }} />
</body>
</html>
);
}

Express Route

// server.js
import express from 'express';
import gasket from './gasket.js';

const app = express();

app.get('/', async (req, res) => {
const swRegisterScript = await gasket.actions.getSWRegisterScript();

res.send(`
<!DOCTYPE html>
<html>
<head><title>My App</title></head>
<body>
<h1>Hello World</h1>
${swRegisterScript}
</body>
</html>
`);
});

composeServiceWorker Lifecycle Hook

Adding Inline Service Worker Code

// plugin-push-notifications.js
export default {
name: 'plugin-push-notifications',
hooks: {
composeServiceWorker(gasket, content, { req, res }) {
return content + `
self.addEventListener('push', (event) => {
const title = 'My App Notification';
const options = {
body: event.data.text(),
icon: '/icon-192x192.png',
badge: '/badge-72x72.png'
};
event.waitUntil(
self.registration.showNotification(title, options)
);
});
`;
}
}
};

Loading External Service Worker Files

// plugin-market-specific-sw.js
import { readFile } from 'fs/promises';
import path from 'path';

export default {
name: 'plugin-market-specific-sw',
hooks: {
async composeServiceWorker(gasket, content, { req, res }) {
const market = req.cookies?.market || 'en-US';
const swFile = path.join('sw-partials', `${market.toLowerCase()}.js`);

try {
const marketSpecificContent = await readFile(swFile, 'utf8');
return content + marketSpecificContent;
} catch (error) {
gasket.logger.warn(`No SW partial found for market: ${market}`);
return content;
}
}
}
};

serviceWorkerCacheKey Lifecycle Hook

Basic Cache Key Based on Locale

// plugin-locale-cache.js
export default {
name: 'plugin-locale-cache',
hooks: {
serviceWorkerCacheKey(gasket) {
return function localeCacheKey(req, res) {
return req.headers['accept-language']?.split(',')[0] || 'en-US';
};
}
}
};