Elegant Hybrid TS project’s build
Matti Bar-Zeev

Matti Bar-Zeev @mbarzeev

About: Craftsman on an endless quest for mastery ▪ Musician first ▪ Web architect & Sr. FE developer ▪ Always learning...

Joined:
Aug 12, 2019

Elegant Hybrid TS project’s build

Publish Date: Mar 25
2 0

Oh BTW, This post was 100% human written with no AI assistance whatsoever. All typos and bad grammar are my own. Enjoy :)


I doubt you remember, but back at the time I wrote a piece about Hybrid NPM package through TypeScript Compiler (TSC), which explained how you can leverage TSC to produce 2 artifact types (ESM and CJS) from a single source code.
I thought it was pretty clever. Hell, I still do 😉

Recently though, I came across one of Matt Pocock’s TS course lessons (which I highly recommend on btw) that suggested a more elegant way to achieve that. In this post I will migrate to that way and explain what I do so your AI agent won’t get left behind ;)

Note: It would be best if you go over the Hybrid NPM package through TypeScript Compiler (TSC) article, so you will get the context of what I’m about to write on.


I have this package in my Pedalboard monorepo, called @pedalboard/media-loader (that you should totally check out if you’re a React dev struggling with media loading performance), which has a build process that generates 2 types of artifacts - ESM and CJS. In order to support that I’ve created 2 different tsconfig.json files and in the build script I’m running them both.
It looks something like this:

"build": "tsc --project tsconfig.esm.json & tsc --project tsconfig.cjs.json",
Enter fullscreen mode Exit fullscreen mode

Although there is nothing wrong with it, it kinda requires this plumbing in the package.json file and all-in-all feels a bit of a brute-force-primitive. Fortunately there is a more elegant way to achieve that using the references config.
Here is how:

Both the tsconfig.esm.json and tsconfig.cjs.json are in the root dir of the package, and to them I will add the “main” config file - tsconfig.json, and its content looks like this:

{
   "references": [
       {
           "path": "./tsconfig.esm.json"
       },
       {
           "path": "./tsconfig.cjs.json"
       }
   ],
   "files": []
}
Enter fullscreen mode Exit fullscreen mode

Let’s go over it real quick - it has a references array which has 2 paths defined in it, one for each config file, and it has an empty array for the files config, to ensure that the tsconfig.json does not enforce any type checking, but rather leaves that to the referenced projects.

Now we need to change the build script. Instead of what we have, we now write this:

"build": "tsc -b",
Enter fullscreen mode Exit fullscreen mode

Notice the -b param, which tells TSC to run it in build mode, thus taking into consideration the different references in the main tsconfig.json file. In other words, without the -b param, it won’t work as we expect it to.

And that is it!

When we run our build script now, TSC will run both configurations and create both ESM and CJS artifacts.
There is a lot more you can do with the project references like cache type check results (for faster builds) or define dependencies between projects, but in this case what we have is enough.

The code is available on Github @pedalboard/media-loader

Be seeing you

Photo by Trnava University on Unsplash

Comments 0 total

    Add comment