Quasar PWA Extension: Architecture Boundaries for Offline Caching and Updates
An architecture note on Quasar's PWA extension: where Workbox-generated service workers help, where trust boundaries sit, and which operational checks catch stale caches and API failures.
03 Mar 2026, 03:32 UTC

The offline gap and the extension's actual boundary
Adding offline support to a Quasar application is often framed as flipping a build flag, but the PWA extension introduces a service worker that sits between the browser and your network stack. The useful takeaway is that the extension reliably solves asset precaching and installability, while API resilience and update freshness remain explicit engineering decisions. This note covers the architecture boundaries, the minimal configuration that works, and the checks that catch the most common failures.
Requirements and version assumptions
The PWA extension is maintained alongside Quasar CLI v2.x and targets Vue 3 projects. If you are still on Quasar v1, the legacy @quasar/app-extension-pwa@v1 package is the supported path; mixing v2 extension code with a v1 CLI will not work.
At minimum, a project needs two structural pieces:
- A
pwasection insidequasar.conf.js. - A
src-pwadirectory containingregister-service-worker.js.
Service workers also require a secure context. localhost is treated as secure during development, but production deployments must serve the application over HTTPS.
The smallest suitable design
For most applications, the smallest suitable design uses Workbox in GenerateSW mode. In this mode, Workbox inspects the build output and generates a service worker with a precache manifest for static assets. The CLI injects manifest.json and registers the worker automatically during quasar dev -m pwa and quasar build -m pwa.
A minimal quasar.conf.js configuration looks like this:
// quasar.conf.js
pwa: {
workboxMode: 'GenerateSW',
manifest: {
name: 'My Application',
short_name: 'App',
display: 'standalone'
}
}
The src-pwa/register-service-worker.js file wires the browser to the generated worker. A minimal registration pattern uses the standard Service Worker API:
// src-pwa/register-service-worker.js
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js')
.then((registration) => {
// Handle ready, updated, and offline lifecycle events here
});
});
}
This design is sufficient when your offline requirement is limited to serving the application shell and static assets from cache. It does not, by itself, make API calls work offline.
Choosing between GenerateSW and InjectManifest
The pwa.workboxMode setting controls how much of the service worker you own.
| Mode | What it does | Choose it when |
|---|---|---|
GenerateSW | Workbox generates service-worker.js from your build output. | You need static asset precaching and standard installability without custom cache logic. |
InjectManifest | You provide a service worker template; Workbox injects only the precache manifest. | You need custom runtime caching strategies, route-specific rules, or non-default cache expiration. |
Trust and data boundaries
A service worker controls every page under its scope. That creates a trust boundary at the origin level: once installed, the worker intercepts requests for that origin and decides whether to serve cache or network.
Precached assets are trusted build artifacts. They are emitted by your build pipeline and fingerprinted by the precache manifest, so serving them offline is safe as long as the manifest is regenerated on every deployment.
Runtime cached API responses are different. The PWA extension does not proxy requests, and it does not automatically validate or scope API responses. If you add runtime caching for API data, you are taking responsibility for cache expiration, response freshness, and any security implications of serving stale or sensitive data offline.
Cross-origin API calls introduce an additional boundary. The extension does not proxy requests, so cross-origin calls must include appropriate CORS headers. Without custom runtime caching rules, offline fallback for APIs simply does not happen.
Operational checks
These checks confirm the extension is present and functioning. Run all CLI commands from the project root with standard development permissions; no elevated privileges are required.
- Configuration check. Verify
quasar.conf.jscontains apwakey and thatsrc-pwa/register-service-worker.jsexists. - Development check. Run
quasar dev -m pwa. In the browser console, look for a message such asService worker registered. In the generatedindex.html, confirm amanifest.jsonlink is present. - Build check. Run
quasar build -m pwa. Inspect thedist/pwafolder forservice-worker.jsandmanifest.json. - Browser check. Open Chrome DevTools, navigate to Application > Service Workers, and verify the worker is active and controls the page.
- Installability check. Run Lighthouse against the built output to confirm PWA criteria for installability and offline fallback.
Failure modes
Stale precache and update latency
Service worker updates rely on cache-busting. If the precache manifest is not regenerated after asset changes, users may serve stale content until the next update check. Even when the manifest is correct, the service worker lifecycle means a new worker waits until all controlled tabs close before taking over, unless you explicitly call skipWaiting() and clientsClaim() in your registration logic.
Silent API failures
Because the extension does not proxy requests, a cross-origin API call that works online will fail offline if no runtime caching rule matches it. The application shell may appear to load correctly while dynamic data is missing, which is easy to miss in a quick manual test.
Unbounded cache growth
Runtime caches created by custom Workbox strategies can grow without limit if expiration policies are not configured. Over time this can exceed browser storage quotas and cause eviction of precached assets.
Conditions that would change the design
- Custom runtime caching requirements. If your application needs route-specific cache strategies, stale-while-revalidate policies for API data, or background sync, switch from
GenerateSWtoInjectManifestand own the service worker template. - Legacy Quasar v1 projects. These require the legacy
@quasar/app-extension-pwa@v1package and a different configuration surface. - Complex update UX. If users must be prompted to refresh when new content is available, the minimal registration pattern is insufficient; you need explicit
updatedlifecycle handling and a user-facing notification. - Multi-origin data architectures. When APIs live on different origins, review CORS headers and cache partitioning before relying on runtime caching.
A practical way to check the result
After deploying a build, open the application in an incognito window, load it once online, then switch the browser to offline mode and reload. The application shell should render from cache. If dynamic data disappears, the gap is in your runtime caching rules, not in the Quasar extension itself. This single test separates asset precaching—which the extension handles—from API resilience, which it does not.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.