Service Worker
The Service Worker controller provides useful methods to facilitate interaction with the service worker lifecycle. It enables you to manually update the service worker and notify users when updates are available, particularly useful when the skipWaiting option is set to false.
This component is essential for:
Notifying users about available application updates
Providing manual update controls
Ensuring users get the latest features without forced reloads
Creating a smooth update experience without interrupting user workflow
Usage
Basic Update Button
<div {{ stimulus_controller('@pwa/service-worker') }}>
<button
id="update-btn"
{{ stimulus_action('@pwa/service-worker', 'update', 'click') }}
style="display:none;"
>
Update Available - Click to Refresh
</button>
</div>
<script>
document.addEventListener('pwa--service-worker:update-available', () => {
document.getElementById('update-btn').style.display = 'block';
});
</script>Update Notification Banner
<div {{ stimulus_controller('@pwa/service-worker') }}>
<div id="update-banner" class="update-notification" style="display:none;">
<p>A new version of this app is available!</p>
<button {{ stimulus_action('@pwa/service-worker', 'update', 'click') }}>
Update Now
</button>
<button onclick="document.getElementById('update-banner').style.display='none'">
Later
</button>
</div>
</div>
<script>
document.addEventListener('pwa--service-worker:update-available', () => {
document.getElementById('update-banner').style.display = 'block';
});
</script>
<style>
.update-notification {
position: fixed;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background: #007bff;
color: white;
padding: 15px 20px;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
z-index: 1000;
}
.update-notification button {
margin: 5px;
padding: 8px 15px;
border: none;
border-radius: 4px;
cursor: pointer;
}
</style>Toast Notification with Countdown
<div {{ stimulus_controller('@pwa/service-worker') }}>
<div id="update-toast" class="toast" style="display:none;">
<span id="toast-message">New version available!</span>
<button {{ stimulus_action('@pwa/service-worker', 'update', 'click') }}>
Update
</button>
</div>
</div>
<script>
document.addEventListener('pwa--service-worker:update-available', () => {
const toast = document.getElementById('update-toast');
const message = document.getElementById('toast-message');
toast.style.display = 'flex';
// Optional: Auto-hide after 10 seconds
let countdown = 10;
const interval = setInterval(() => {
countdown--;
message.textContent = `New version available! Auto-dismissing in ${countdown}s`;
if (countdown <= 0) {
clearInterval(interval);
toast.style.display = 'none';
}
}, 1000);
});
</script>Integration with User Settings
<div {{ stimulus_controller('@pwa/service-worker') }}>
<!-- Settings page -->
<div class="settings">
<h2>Application Settings</h2>
<label>
<input type="checkbox" id="auto-update" checked>
Automatically install updates
</label>
<button id="manual-update-btn" style="display:none;">
Update Available
</button>
</div>
</div>
<script>
document.addEventListener('pwa--service-worker:update-available', () => {
const autoUpdate = document.getElementById('auto-update').checked;
const updateBtn = document.getElementById('manual-update-btn');
if (autoUpdate) {
// Auto-update: show brief notification and update
console.log('Auto-updating to new version...');
// Trigger update automatically
document.querySelector('[data-action*="update"]').click();
} else {
// Manual update: show button
updateBtn.style.display = 'block';
updateBtn.textContent = 'Update Available - Click to Install';
}
});
</script>Parameters
None
Actions
update
updateTriggers the service worker update process. When called:
The new service worker becomes active
The page automatically refreshes to load the updated version
Users immediately see the latest features and fixes
{{ stimulus_action('@pwa/service-worker', 'update', 'click') }}Calling this action will refresh the current page. Ensure users are aware of this behavior and have saved any unsaved work before triggering the update.
Targets
None
Events
pwa--service-worker:update-available
pwa--service-worker:update-availableDispatched when a new version of the service worker is detected and ready to be installed.
No payload
This event is fired only when:
A new service worker has finished installing
The new service worker is waiting to activate
The
skipWaitingoption is set tofalsein the service worker configuration
Example usage:
document.addEventListener('pwa--service-worker:update-available', () => {
// Show update notification
showUpdateBanner();
// Log for debugging
console.log('Service worker update available');
// Optional: Ask user preference
if (confirm('New version available. Update now?')) {
// Trigger update
document.querySelector('[data-action*="update"]').click();
}
});Best Practices
Clear communication: Always inform users that updating will refresh the page
Save user work: If your app has forms or unsaved data, warn users before updating
Provide options: Let users choose to update now or later
Visual feedback: Use prominent but non-intrusive UI elements like banners or toasts
Graceful timing: Consider detecting idle time before prompting for updates
Persistent notification: Keep the update notification visible until user acts on it
Configuration Reference
This component works in conjunction with the service worker configuration. To enable manual updates, ensure skipWaiting is set to false:
pwa:
serviceworker:
enabled: true
src: "sw.js"
skip_waiting: false # Allows manual control over updatesFor more information on service worker configuration, see the Service Worker Configuration page.
Advanced Example: Update Manager
Here's a complete example of an update manager with user preferences and smart update timing:
<div {{ stimulus_controller('@pwa/service-worker') }}>
<div id="update-manager" style="display:none;">
<div class="update-card">
<h3>📦 Update Available</h3>
<p>A new version of the app is ready to install.</p>
<div class="update-options">
<button
class="btn-primary"
{{ stimulus_action('@pwa/service-worker', 'update', 'click') }}
>
Update Now
</button>
<button class="btn-secondary" onclick="snoozeUpdate()">
Remind Me in 1 Hour
</button>
</div>
</div>
</div>
</div>
<script>
let updateSnoozed = false;
document.addEventListener('pwa--service-worker:update-available', () => {
if (updateSnoozed) return;
// Check if user is idle (no interaction for 30 seconds)
let idleTime = 0;
const checkIdle = setInterval(() => {
idleTime++;
if (idleTime >= 30) {
clearInterval(checkIdle);
showUpdateManager();
}
}, 1000);
// Reset idle time on user interaction
['mousedown', 'keypress', 'scroll', 'touchstart'].forEach(event => {
document.addEventListener(event, () => {
idleTime = 0;
}, { once: true });
});
});
function showUpdateManager() {
document.getElementById('update-manager').style.display = 'block';
}
function snoozeUpdate() {
document.getElementById('update-manager').style.display = 'none';
updateSnoozed = true;
// Re-enable after 1 hour
setTimeout(() => {
updateSnoozed = false;
showUpdateManager();
}, 3600000);
}
</script>Last updated
Was this helpful?