Configuring StencilJS Service Worker Precaching for a Robust PWA
Learn how to enable and configure StencilJS’s built‑in service worker for precaching and PWA routing. Follow this step‑by‑step guide to build, test, and recover from common issues.
19 Apr 2026, 02:51 UTC

Desired Outcome
After following this guide you will have a StencilJS project that:
- Generates a service worker with a precache manifest that covers all static assets and routes.
- Registers the service worker on the client, enabling offline functionality and automatic updates.
- Uses Stencil’s lightweight router to perform client‑side navigation without full page reloads.
Prerequisites
- Node.js 20+ and npm (or yarn) installed on your machine.
- A working StencilJS project created with
npm init stenciloryarn create stencil. - Basic familiarity with TypeScript, JSX, and the Stencil configuration file
stencil.config.ts. - Optional: A local HTTP server (e.g.,
npm install -g serve) for testing the production build.
Focused Procedure
- Enable Service Worker Output Target
Add an
outputTargetsentry for the web build that includes aserviceWorkerconfiguration. This tells Stencil to generate asw.jsfile during the build.// stencil.config.ts export const config: Config = { namespace: 'myapp', outputTargets: [ { type: 'dist', dir: 'dist', serviceWorker: { globPatterns: ['**/*.{js,css,html,svg,png,jpg,webp}'], globIgnores: ['**/index.html'], swDest: 'dist/sw.js', swSrc: 'src/sw/custom-sw.js', // optional custom service worker }, }, ], };Place
custom-sw.jsinsrc/swif you need custom logic; otherwise Stencil’s default will suffice. - Configure Routing for the Client
Stencil’s router is used by default in the
corepackage. Ensure yourindex.htmlincludes theapp-rootcomponent and the router is set up insrc/components/app-root/app-root.tsx:import { Component, h } from '@stencil/core'; import { Router, Route } from '@stencil/router'; @Component({ tag: 'app-root', styleUrl: 'app-root.css', shadow: false, }) export class AppRoot { render() { return ( <div> <Router url={window.location.pathname}> <Route url='/' component='home-page' /> <Route url='/about' component='about-page' /> </Router> </div> ); } } - Build the Project
Run:
npm run buildThis compiles the components, generates the
dist/folder, and createsdist/sw.jswith a precache manifest. - Serve the Production Build
To test offline behavior, serve the
distfolder:serve -s distOpen the URL in a browser, then disable network (Chrome DevTools > Network > Offline). You should still see the app’s static pages and components.
- Register the Service Worker in the Browser
Stencil automatically injects a registration script into
index.htmlwhenserviceWorkeris enabled. Confirm the script exists:<script type="module"> import { registerSW } from 'virtual:service-worker'; registerSW(); </script>When the page loads, the service worker registers, caches assets, and listens for
updatefoundevents to notify users of new content.
Expected Checks
- Run
ls distand verifysw.jsis present. - Open
dist/sw.jsand confirm aself.__WB_MANIFESTarray exists (the precache list). - In the browser console, search for “Service worker registered” or “Installing service worker” messages.
- Navigate to a route that isn’t the root (e.g.,
/about) and refresh. The page should load instantly and remain functional offline.
Recovery Options
- If the service worker fails to register, check the console for
ServiceWorkerRegistrationErrormessages. Common causes include:- HTTPS requirement – serve over HTTPS or use
serve -s dist --devfor local testing. - Wrong
swDestpath – ensure the path matches the build output.
- HTTPS requirement – serve over HTTPS or use
- To clear a stale cache, open Chrome DevTools > Application > Service Workers > Unregister, then reload the page.
- When you need to force the browser to use the latest assets, delete the
sw.jsfile fromdistand rebuild.
Limitations & Practical Checks
- Stencil’s default service worker uses a
Cache Firststrategy for all assets. For dynamic data, you must add runtime caching rules incustom-sw.js. - Routing works only for paths that match the configured routes. Deep linking to unknown paths will fall back to the fallback page defined in
stencil.config.ts. - Testing offline behavior requires a stable network connection initially to allow the service worker to cache assets. If the first load fails, the app will not cache.
- Use
npm run build -- --devto generate a dev build that skips service worker generation for quick iteration.
Concrete Example: Adding Runtime Caching for API Calls
Suppose your app fetches data from https://api.example.com/users. Add the following to src/sw/custom-sw.js:
import { registerRoute } from 'workbox-routing';
import { StaleWhileRevalidate } from 'workbox-strategies';
registerRoute(
({ url }) => url.origin === 'https://api.example.com' && url.pathname.startsWith('/users'),
new StaleWhileRevalidate({ name: 'api-users' })
);
Rebuild and redeploy; the service worker now caches API responses while still serving fresh data when online.
Conclusion
By enabling the serviceWorker output target, configuring routes, and verifying the build, you can transform a StencilJS application into a fully offline‑capable PWA. The lightweight router and built‑in service worker generation keep bundle sizes small while delivering a robust user experience.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.