Next.js starter your AI actually understands. Ship internal tools in days not weeks. Pre-order $199 $499 → [Get it now]

How to use Vue with Service Workers

Service workers enable Vue applications to work offline, cache assets, and provide PWA features like push notifications. As the creator of CoreUI with 12 years of Vue development experience, I’ve built Vue PWAs that serve millions of users with reliable offline functionality.

The most maintainable approach is to use Vite PWA plugin with Workbox for automatic service worker generation and Vue integration.

Install Dependencies

Install Vite PWA plugin:

npm install vite-plugin-pwa -D

Configure Vite

Update vite.config.js:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { VitePWA } from 'vite-plugin-pwa'

export default defineConfig({
  plugins: [
    vue(),
    VitePWA({
      registerType: 'autoUpdate',
      includeAssets: ['favicon.ico', 'robots.txt', 'apple-touch-icon.png'],
      manifest: {
        name: 'My Vue App',
        short_name: 'VueApp',
        description: 'My awesome Vue application',
        theme_color: '#ffffff',
        icons: [
          {
            src: 'pwa-192x192.png',
            sizes: '192x192',
            type: 'image/png'
          },
          {
            src: 'pwa-512x512.png',
            sizes: '512x512',
            type: 'image/png'
          }
        ]
      },
      workbox: {
        runtimeCaching: [
          {
            urlPattern: /^https:\/\/api\.example\.com\/.*/i,
            handler: 'NetworkFirst',
            options: {
              cacheName: 'api-cache',
              expiration: {
                maxEntries: 50,
                maxAgeSeconds: 60 * 60 * 24
              },
              cacheableResponse: {
                statuses: [0, 200]
              }
            }
          }
        ]
      }
    })
  ]
})

Register Service Worker

Update src/main.js:

import { createApp } from 'vue'
import App from './App.vue'
import { registerSW } from 'virtual:pwa-register'

const app = createApp(App)

const updateSW = registerSW({
  onNeedRefresh() {
    console.log('New content available, please refresh')
  },
  onOfflineReady() {
    console.log('App ready to work offline')
  },
  onRegistered(registration) {
    console.log('Service worker registered:', registration)
  },
  onRegisterError(error) {
    console.error('Service worker registration error:', error)
  }
})

app.mount('#app')

Create Service Worker Status Component

Create src/components/ServiceWorkerStatus.vue:

<script setup>
import { ref, onMounted } from 'vue'
import { useRegisterSW } from 'virtual:pwa-register/vue'

const {
  needRefresh,
  updateServiceWorker
} = useRegisterSW()

const close = () => {
  needRefresh.value = false
}

const update = async () => {
  await updateServiceWorker()
}
</script>

<template>
  <div v-if="needRefresh" class="pwa-toast">
    <div class="message">
      New content available. Click reload to update.
    </div>
    <button @click="update">Reload</button>
    <button @click="close">Close</button>
  </div>
</template>

<style scoped>
.pwa-toast {
  position: fixed;
  bottom: 20px;
  right: 20px;
  padding: 16px;
  background: #333;
  color: white;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
  z-index: 1000;
}

.message {
  margin-bottom: 12px;
}

button {
  margin-right: 8px;
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
</style>

Create Offline Detection Composable

Create src/composables/useOnline.js:

import { ref, onMounted, onUnmounted } from 'vue'

export const useOnline = () => {
  const isOnline = ref(navigator.onLine)

  const updateOnlineStatus = () => {
    isOnline.value = navigator.onLine
  }

  onMounted(() => {
    window.addEventListener('online', updateOnlineStatus)
    window.addEventListener('offline', updateOnlineStatus)
  })

  onUnmounted(() => {
    window.removeEventListener('online', updateOnlineStatus)
    window.removeEventListener('offline', updateOnlineStatus)
  })

  return { isOnline }
}

Use in App

<script setup>
import { useOnline } from './composables/useOnline'
import ServiceWorkerStatus from './components/ServiceWorkerStatus.vue'

const { isOnline } = useOnline()
</script>

<template>
  <div id="app">
    <div v-if="!isOnline" class="offline-banner">
      You are offline. Some features may be unavailable.
    </div>

    <ServiceWorkerStatus />

    <router-view />
  </div>
</template>

<style>
.offline-banner {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  background: #f44336;
  color: white;
  padding: 12px;
  text-align: center;
  z-index: 999;
}
</style>

Custom Caching Strategy

For advanced caching, create public/sw.js:

import { precacheAndRoute } from 'workbox-precaching'
import { registerRoute } from 'workbox-routing'
import { StaleWhileRevalidate, CacheFirst, NetworkFirst } from 'workbox-strategies'
import { ExpirationPlugin } from 'workbox-expiration'

precacheAndRoute(self.__WB_MANIFEST)

// Cache images
registerRoute(
  ({ request }) => request.destination === 'image',
  new CacheFirst({
    cacheName: 'images',
    plugins: [
      new ExpirationPlugin({
        maxEntries: 60,
        maxAgeSeconds: 30 * 24 * 60 * 60
      })
    ]
  })
)

// Cache API calls
registerRoute(
  ({ url }) => url.pathname.startsWith('/api/'),
  new NetworkFirst({
    cacheName: 'api',
    plugins: [
      new ExpirationPlugin({
        maxEntries: 50,
        maxAgeSeconds: 5 * 60
      })
    ]
  })
)

Best Practice Note

This is the same service worker integration we use in CoreUI’s Vue admin templates. Vite PWA plugin automatically generates optimized service workers with Workbox, providing offline support and asset caching without manual configuration.

For production applications, consider using CoreUI’s Vue Admin Template which includes pre-configured PWA support with service workers, offline caching, and push notifications.

If you’re building offline features, you might also want to learn how to use Vue with IndexedDB for local data storage.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author

Subscribe to our newsletter
Get early information about new products, product updates and blog posts.
How to capitalize the first letter in JavaScript?
How to capitalize the first letter in JavaScript?

How to Clone an Object in JavaScript
How to Clone an Object in JavaScript

How to force a React component to re-render
How to force a React component to re-render

How to validate an email address in JavaScript
How to validate an email address in JavaScript

Answers by CoreUI Core Team