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!
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. 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 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 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, which would be fine for Vite, but not for our testing approach for
jest (other than experimentally, so I learned. @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, 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.
I would love to hear from others what kind of experience they had switching from Webpack to Vite!