DEV Community

Cover image for How to Register a Service Worker With Vite and Rollup Without Plugins
Federico Moretti
Federico Moretti

Posted on • Edited on

How to Register a Service Worker With Vite and Rollup Without Plugins

I’m on vacation, trying to renew my personal website (that’s just a one-page showcase right now) before coming back to work. I’ve already replaced Webpack with Vite, since I think that it’s a better tool to date — but I still needed to turn it into a full Progressive Web Application.


PWA Vite Plugin

I know, PWA Vite Plugin is a great choice to do the same without headache, but I just wanted to have a simple Service Worker to cache the website assets and I didn’t want to add further development dependencies. If you got here, I think you’re trying to achieve something similar.


Then, I found an existing solution that was proposed about two years ago by @reeshee, but it lacks a TypeScript support that I need and it requires yet another dependency… so I tried to build my own. I succeeded in registering a Service Worker, but it needs lots of improvements.

I took inspiration by an old Workbox tutorial, although you don’t need it at all to follow my instructions below: remember, the main goal here is getting things done without plugins or development dependencies, so I won’t ask you to install any except Vite itself.

One of the flaws in my approach is that you need to add an inline script in your index.html (that’s why @reeshee relied on register-service-worker, I guess): I don’t see this as a security issue, but you could. Maybe using a nonce global attribute can be useful here.

<script>
  window.addEventListener('load', () => {
    if ('serviceWorker' in navigator) {
      navigator.serviceWorker.register('/sw.js').then(() => {
        console.info('Service worker registered!');
      }).catch((error) => {
        console.warn(`Error registering service worker:\n${error}.`);
      });
    }
  });
</script>
Enter fullscreen mode Exit fullscreen mode

Above, a simplified version of the script proposed by the Google tutorial I already mentioned. Now it’s time to create an actual Service Worker: I chose to call it sw.js, but you can choose whatever you want — just remember to keep the .js extension here and to be consistent.

Yes, because I said that I want to use TypeScript, so the Service Worker sources will be saved somewhere in a .ts file instead. I followed the conventions, creating a /src/ts/sw.ts file in the same folder of the main app.ts file which handles all PWA features.

Of course, following the Google guidelines, I chose to transpile and move it to the /dist root along with index.html to share the same scope. This was a bit challenging at first, and that’s where Rollup comes in handy: being a Vite implicit dependency, you don’t need to install it.


Rollup and TypeScript

I didn’t change anything in tsconfig.json, even though mine is more “futuristic” than usual, but I found a solution to fix an error I’ve got on the Service Worker. This has nothing to do with the integration itself and I won’t share the sources here, because I think that adding logics to the sw.ts file is up to you.

Anyway, the main changes belong to vite.config.ts, where you should include the Rollup configuration and adapt the following example to your folder structure. I said that you should, because there’s the chance that you don’t want to strictly follow my instructions and you can do it without issues.

import type { UserConfig } from 'vite';

export default {
  base: '/',
  build: {
    outDir: 'dist',
    assetsDir: './',
    emptyOutDir: true,
    rollupOptions: {
      input: {
        index: 'index.html',
        sw: 'src/ts/sw.ts',
      },
    },
  },
} satisfies UserConfig;
Enter fullscreen mode Exit fullscreen mode

Above, the rollupOptions object is required, because otherwise Vite will skip the Service Worker transpiling: you must not import sw.ts in your main TypeScript file, since this would break the whole logic. That’s why I needed to list index.html here. It’s not mandatory.

If you noticed, I changed the assetsDir too. I wanted to keep both the sw.js and the index.html output files in the root, then I opted for this solution, but it will move the main module and the styles there as well: in my actual integration I’ve also added further directives to avoid it.

Basically, I listed all the input files and set a custom output object to rule their destination path. I chose to remove hashes, because my Service Worker doesn’t need them, but yours could: I can’t know how you handle your caches in advance, so I prefer to skip this part.

I plan to share my solution for it, as well as the whole Service Worker sources, once I’m 100% done. If you’re curious, you can always have a look at the GitHub repository of my personal website to get inspired: it’s a work in progress, so don’t expect everything to work.


Building this solution, I saw that Vite is going to replace Rollup with Rolldown and I gave it a try. Unfortunately, it still needs improvements in the way it handles CSS files, so I was forced to rollback to Rollup, but I think that I will come back to it when ready to be released into production.

Top comments (0)