Using Chokidar with Esbuild To Rebuild On Change
1 min read

Using Chokidar with Esbuild To Rebuild On Change

This month I was migrating from Webpacker to ESBuild using JSBundling in a client's Ruby on Rails project, since, they were using Stimulus & a couple of Javascript dependencies in the project, the migration went smoothly.

However, I realised that ESBuild doesn't watch for changes in the root project instead it only listens to the files mentioned in `entryPoints` config. This doesn't make it an ideal DX (developer experience), so I decided to dig deeper on how to get this experience right.

I found an issue on ESBuild repo a lot of folks have shared their approach to solve it. I picked the one that felt right for our use case, tweaked it a little bit to get what I want & kept is as simple as I could. Here is what I ended up with  

const path = require('path')
const chokidar = require('chokidar')
const esbuild = require("esbuild")

const watchDirectories = [
  "./app/javascript/**/*.js",
  "./app/views/**/*.html.erb",
]

const config = {
  entryPoints: ["application.js", "admin.js"],
  bundle: true,
  outdir: path.join(process.cwd(), "app/assets/builds"),
  absWorkingDir: path.join(process.cwd(), "app/javascript"),
  watch: process.argv.includes("--watch"),
  sourcemap: process.argv.includes("--watch"),
  incremental: process.argv.includes("--watch"),
  plugins: [],
}


if (process.argv.includes("--watch")) {

  (async () => {
    const result = await esbuild.build(config);
    chokidar.watch(watchDirectories).on('all', (event, path) => {
      console.log(`rebuilding ${path}`)
      result.rebuild()
    })
  })();

} else {
  esbuild.build(config).catch(() => process.exit(1))
}

Basically, this uses Chokidar which is a Nodejs package to watch changes on specified files. So I used a combination of Chokidar and ESBuild package to rebuild files whenever there are changes in the project, and because ESbuild is fast there isn't much waiting & overhead.