Converting to Vite (Part 2)
Tags: webpack, vite, javascript, webdev
Published: 2022-01-13 16:08:35

In this post, I'm going to describe some of the snags that we encountered as we transitioned to Vite - at their best, snags become lessons!

Open Sauced is a Progressive Web Application (PWA), and this includes the use of a Service Worker.  In my personal understanding, a Service Worker definition should be packaged as a standalone JavaScript file. When you look at how bundling is done in Vite, it will generate a `vendor.xyz.js` file, an `index.xyz.js` file, and otherwise pass through static assets in the `public` directory as-is. Our webpack configuration on the other hand was configured to handle our `src/service-worker.js` in a specific way. For that reason, we needed to move our `src/service-worker.js` file to `public/service-worker.js`, and move around the associations in our `src/index.js` file. Another thing we had to learn about was the way Vite handles [environment variables](https://vitejs.dev/guide/env-and-mode.html).  Our application would look at whether the application was in production or development mode (and also whether it was being served locally) in order to decide whether to register the service worker. For a project using Webpack, you usually refer to these as `process.env.VARIABLE` and the value is statically set in the bundling process. Vite does something a bit different, but instead you would need to refer to `import.meta.env.VARIABLE` and only a handful of things are pre-set for you and otherwise you need to use a variable naming convention to have something statically included in the bundle. Fortunately, most of the variables we needed to use were included by default, so it was easy to get working (or so we thought). We tweaked and tweaked some more, and in the end, we just ended up using the [`vite-plugin-pwa`](https://github.com/antfu/vite-plugin-pwa) extension to handle everything, while moving most of our PWA manifest to `vite.config.ts`. It's great to know how things work under the hood, but sometimes you just get better results with a plugin!

Another thing that we ran into dealt with the fact that some libraries end up just a little bit differently in development bundling than in production bundling.  When developing, Vite takes advantage of ESM to let the browser effectively cache your dependencies, separated out into module files.  In production, everything is bundled into one vendor file. Libraries can export different compiled versions between these two situations. We were having a lot of trouble that we isolated down to a specific component, that in turn used the `react-markdown` library. After reading through [issues](https://github.com/vitejs/vite/issues/3592) for this one and its dependencies, we found that there was a circular reference in one of `react-markdown`'s dependencies that only showed up in production bundles. 

The most straightforward fix for the circular reference was to update `react-markdown` through one major revision, but this introduced a new snag.  In this major revision, `react-markdown` changed to [ESM only](https://github.com/remarkjs/react-markdown/blob/main/changelog.md#700---2021-08-13), which would be fine for Vite, but not for our testing approach for `jest` (other than experimentally, [so I learned](https://jestjs.io/docs/ecmascript-modules). @0vortex and I got some help from @jasonericdavis on Discord to mock the `react-markdown` component in Jest (bypassing the need for ESM support) as part of a [preparatory PR](https://github.com/open-sauced/open-sauced/pull/1333), and we got back on track.

One takeaway that I had from this was the practice of stepping beyond running `vite dev`, and running `vite build` and `vite preview` as well, in order to verify what would run in production. We use Netlify deploy previews in Open Sauced, and running both `vite build` and `vite preview` helps with reproducing production issues locally. We updated our `package.json` to reflect these [CLI commands](https://vitejs.dev/guide/#command-line-interface).

I would love to hear from others what kind of experience they had switching from Webpack to Vite!

<small><em>Cover image Photo by <a href="https://unsplash.com/@william07?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">william william</a> on <a href="https://unsplash.com/s/photos/container-ship?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>. I chose this one because I felt like @0vortex and I were the tugboats!</em></small>