Develop, test and build with tsx, vitest and tsc

Two years ago, I hoped I made a reliable example and template for a decent backend node server. It used SWC, TypeScript and Express. You know the latter two, but SWC is the odd one out today. I made that choice based these aspects:

  • SWC was built in Rust, and I like Rust
  • SWC was realigned for use in Next by Vercel

In July 2022, I had to face the facts though. SWC might somehow work out for Next. But it does not work outside of that ecosystem. Maybe Next gets away with it because they never leave CJS modes? Maybe Next gets way with it because they never use Jest and actually never test anything? I’ll never know.

I know about the bun in the oven. Bun gets plenty of love. It’s great and all but it’s not boring yet so I am wary. I am happy to be in the early majority when it comes to technology, and especially so when it’s cross-compatible with an existing ecosystem.

In 2024, I trialing this:

  • tsx

    For dev mode. Consider this just like ts-node or a combination of tsc and nodemon rolled together. Internally it uses esbuild.

    Nodemon is fine, so if you forgoe this dependency (and it’s only a dev-dependency at worst), that’s fine too and you can go back to looping nodemon and tsc just fine.

    To note: the naming of tsx is absolutely awful.

  • vitest

    For testing. Consider this the alternative to Jest. Vitest does not need to fight nearly so much with esm. That’s already enough to enjoy it. There are supposed to be speed benefits too, but it’s hard to say on smaller test suites. It also uses esbuild internally.

  • tsc

    For building. In the end, I realize I do not specifically care about how long it takes to build the JavaScript files from TypeScript files. I rarely build locally, and I can wait if I do. Otherwise, the build is running in continuous integration.

Here are my concerns though:

  • tooling consistency

    There’s no way to know for sure that tsx and vitest and tsc are producing the same runnables. I am trusting that my code is boring enough to be roughly equivlent in each. It’s placing a lot of congitive trust in the tooling. Picking a single tool (see Bun) would be ideal. Alas, the node ecosystem is still working on it.

  • broad usage

    tsx has about 1 million/weekly download rate.

    vitest has about 3 million/weekly download rate.

    typescript and therefore tsc (although; I suspect many people download the package without using it for tsc) has about a 47 million/weekly download rate.

    That’s probably enough. But likely nobody is combining these three tools together.

Many of my codebases are still running with the last trial I ran two years ago, with SWC. They work fine. It’s still a mess though. With this combination, I am using a boring tool (tsc), a necessary (vitest) and an optional nicety (tsx).

I’ll make an example repository for this eventually and link it here.

Follow me on Mastodon

Follow me on Twitter @ryanmr.