Using Flow types with Vite, the Hermes way

In my previous post, I outlined how I migrated a Create-React-App application with Flow types to Vite. I used bunchtogether’s lovely little vite-plugin-flow to get the job done.

After some discussion over on the Flowtype Discord I thought it might be worth figuring out whether I could use Hermes‘ parser capabilities instead (as recommended by the Flow team). On the surface it looked like it was going to be really difficult: I’ve always used Hermes as a Babel parser plugin, and Babel doesn’t usually fit into the whole Vite ecosystem particularly well. It turns out to work quite nicely for my use case.

Luckily others had done most of the work for me – I just had to put the pieces together. First up was vite-plugin-babel (from the wonderfully named Owls Department), which enables Babel in Vite’s development mode. Then came Flow’s @babel/preset-flow and babel-plugin-syntax-hermes-parser (which I was already using in the old Create-React-App project):

npm install --save-dev vite-plugin-babel @babel/preset-flow babel-plugin-syntax-hermes-parser

npm uninstall @bunchtogether/vite-plugin-flow

Finally I updated my project’s vite.config.js. I swapped out the imports:

import babel from "vite-plugin-babel";
import { flowPlugin, esbuildFlowPlugin } from "@bunchtogether/vite-plugin-flow";

Then added babel into the plugins section, and removed the vite-plugin-flow config:

{
  plugins: [
    babel({
      babelConfig: {
        babelrc: false,
        configFile: false,
        plugins: ["babel-plugin-syntax-hermes-parser"],
        parserOpts: { flow: "all" },
        presets: ["@babel/preset-flow"],
      },
    }),
    flowPlugin(),
  ],
  optimizeDeps: {
    esbuildOptions: {
      plugins: [esbuildFlowPlugin()],
    },
  },
}

So far everything in my project works nicely, and performance is largely unchanged from the previous setup (using vite-plugin-flow). Production builds on CircleCI come in around 3m30s faster than the previous Create-React-App builds.


The journey to get here took a couple of detours. The most notable was finding the official @vitejs/plugin-react can also do custom Babel plugins/presets. However, it appears support is limited (they do not enable code transformation), and are only applied during the production build. If that had worked, I wouldn’t have needed vite-plugin-babel.