Astro-Specific Considerations
Astro-specific considerations for PWAs
Section titled “Astro-specific considerations for PWAs”Astro’s flexibility — static, SSR, or hybrid rendering — introduces a handful of decisions that directly affect how your service worker behaves. Getting these right means your users enjoy a fast, reliable offline experience without stale or missing responses.
SSG vs SSR/hybrid: what gets precached
Section titled “SSG vs SSR/hybrid: what gets precached”Astro’s default output mode is static. Every page is rendered to an .html file at build time, so @vite-pwa/astro can walk the dist/ folder and include every HTML file in the precache manifest automatically.
Switch to output: 'server' or output: 'hybrid' and the picture changes: SSR routes are generated on the server at request time, so there is no .html file for Workbox to hash and precache. Those routes must be handled by runtime caching instead.
// astro.config.mjs — SSG (default), all pages precachedAstroPWA({ registerType: 'autoUpdate', workbox: { globPatterns: ['**/*.{css,js,html,svg,png,ico}'], // Every /blog/*, /about, / etc. is a static file — precached },})// astro.config.mjs — hybrid SSR// output: 'hybrid' or 'server'AstroPWA({ registerType: 'autoUpdate', workbox: { globPatterns: ['**/*.{css,js,svg,png,ico}'], // assets only — no .html for SSR routes runtimeCaching: [ { urlPattern: ({ url }) => url.pathname.startsWith('/api/'), handler: 'NetworkFirst', options: { cacheName: 'api-cache', networkTimeoutSeconds: 3 }, }, ], },})Quick reference
Section titled “Quick reference”| Scenario | Precache | Runtime cache |
|---|---|---|
SSG page (output: 'static') | Yes (auto) | Optional |
SSR page (output: 'server') | No | Required |
| Static asset (CSS/JS/images) | Yes | No |
| External API | No | Required |
Base path and scope alignment
Section titled “Base path and scope alignment”When you deploy Astro to a sub-path (for example, GitHub Pages at /my-app/), the service worker scope must match that base. If the scope is / but your app lives at /my-app/, the SW will fail to control your pages.
Set base, scope, manifest.start_url, and the Workbox globPatterns root together:
// astro.config.mjs — deployed at /my-app/export default defineConfig({ base: '/my-app/', integrations: [ AstroPWA({ scope: '/my-app/', base: '/my-app/', manifest: { start_url: '/my-app/' }, workbox: { globPatterns: ['**/*.{css,js,html,svg,png,ico}'] }, }), ],})Astro’s default trailingSlash is 'ignore', which means both /about and /about/ are valid. Make sure your scope ends with a slash (/my-app/) so the SW controls all paths under that prefix.
Islands hydration and offline behavior
Section titled “Islands hydration and offline behavior”Astro islands ship each component’s JavaScript as a separate chunk in dist/. Because @vite-pwa/astro precaches every file matching globPatterns, all island JS bundles are cached automatically. An island using client:visible or client:idle will hydrate correctly offline as long as its chunk is in the precache manifest — which it will be if your globPatterns includes **/*.js.
No extra configuration is needed for islands offline support. The key constraint is that the island’s data must also be available offline: if the component fetches from an uncached API at runtime, that data will be missing.
Testing with astro preview
Section titled “Testing with astro preview”The service worker is only generated during astro build. Running astro dev does not produce a SW, so DevTools will show no service worker registered. Always test your PWA against the production build:
# Build first, then preview — the SW only works in the built outputnpm run buildnpm run preview# Open http://localhost:4321 in DevTools > Application > Service WorkersAfter opening the preview URL, navigate to DevTools → Application → Service Workers to confirm the SW is registered and active. Use Cache Storage to verify that your precache manifest entries are present. To simulate offline behavior, check the Offline checkbox in the Network panel and reload.
Trade-offs
Section titled “Trade-offs”| Option | Benefit | Cost |
|---|---|---|
| Astro SSG (precache the entire build output) | Offline works immediately after build, since every page is already a static file | Frequently-changing content needs a full rebuild+redeploy every time before it gets cached |
| Astro + islands architecture (partial hydration) | Ships far less JS to the client, well suited to a speed-focused PWA | Have to be careful that the service worker caches each island’s JS with the right scope |
Common mistakes
Section titled “Common mistakes”- Forgetting that Astro is a multi-page app by default, so navigation between pages is a full page load the service worker must handle differently from an SPA.
- Not accounting for cache on SSR-rendered pages (in hybrid mode), so the offline fallback does not work for non-static pages.
- Precaching every page including ones almost nobody visits, growing storage more than necessary without extra benefit.
Documentation sites built with Astro or similar static-site generators commonly combine SSG with service-worker precaching so docs open instantly offline after the first visit, and many Astro-built blogs use a precache-the-whole-site approach because the total size is small enough to make it practical — the same trade-off table above applies either way.