Zum Inhalt springen

Monorepo with Bun

Hello

Had this idea recently. I built this project management tool kinda like Jira, called kiffari, and now I’m working on turning it into something that runs locally, using markdown files as a database. It’s called kiffarino. The whole point is to keep tickets right next to the code that handles them

But this post isn’t really about that.

It’s about how much I’ve gotten used to bun as my go-to JavaScript runtime. I almost forgot it can also transpile TypeScript for Node, work as a package manager, and handle monorepos too. It does all of it.

Over the past few months I’ve moved most of my stuff to bun. It just makes sense. I love JavaScript. It’s the language I use the most and the one I feel fastest with. TypeScript grew on me too. Not because of the safety everyone talks about, but because the type hints are nice. It’s basically inline docs that actually work

What used to really piss me off with TypeScript was the setup. Every time I started a new side project it was the same annoying routine

  1. Init the project with npm or pnpm
  2. Copy a massive tsconfig from some other repo
  3. Try to run it with ts-node or tsx or figure out how to build it properly

It’s not awful if you have a good starter or template, but still, too much time wasted before you even write a line of code.

If also you want to have monorepo, with shared libs, the headache gets increasingly bigger, as you need to multiply the effort of all of those boilerplate nonsense.

I have used pnpm and nx for work, it works really well but the boilerplate you need to just get going is just too much.

Bundle that, build this, transpile that other one and by the time you get going that initial idea is getting boring and your side project is dead.

I have used bun so far as a runtime, monorepo manager and a package manager, so I decided to give it a go as a transpiler too.

Long story short, it worked.

In kiffarino, I have the following setup:

  • a hono backend
  • a svelte5 spa
  • a shared lib to share types and functions between the 2 repos. (Endpoint results for example)

I had done that before in other repos (alicarti a game framework for websocket games), but using bun as a runtime, so it was all good easy and smooth.

Here I wanted to create a single executable, to be compatible with node and be able to publish it on npm as a package I can use everywhere.

And it all just works.

How did I do that?

Easy:

Backend

"build": "bun build ./src/index.ts --outdir ./dist/ --target node"

This just transpiles and makes it runnable by node with only one command.

Frontend

"build": "bunx --bun vite build"

vite handles it really well but run via bunx

Shared libs

{
  "name": "@kiffarino/shared",
  "module": "index.ts",
  "type": "module",
  "devDependencies": {
    "@types/bun": "latest"
  },
  "peerDependencies": {
    "typescript": "^5"
  }
}

Only adding that index.ts and it looking like this

export * from "./config";
export * from "./models";

it allows me to use those libs everywhere in the monorepo.

It just works wonders and to setup the workspaces, as suggested from their docs, you only need to do two things:

This in the root packages.json

  "workspaces": [
    "be",
    "web",
    "shared"
  ],

and as long as those packages have a name in them, this what you can put so the subrepo can see stuff exported by other ones.

  "dependencies": {
    "@kiffarino/shared": "workspace:*",

and to use them you can just

import { Ticket } from "@kiffarino/shared"; // <-- isnt this great?
import type { Context } from "hono";

[...]

export async function create(c: Context) {
  const body = (await c.req.json()) as { title: string };
  [...]
  const ticket = Ticket.create(body.title);
  return c.json(
    {
      result: ticket,
    },
    201
  );
}

Setup finished.

How to run scripts concurrently you ask?

"dev": "bun --filter '*' dev",
"check": "bun --filter '*' check",

this will look in * all of the workspaces and check if a dev script is in the package.json and run it.
The second one is to do a typecheck instead.

In the case of a hono repo is a bit more complex as bun does not do typechecking.

But adding this is enough:

"check": "bunx tsc --noEmit -p tsconfig.json",

In short, bun has completely changed how I handle JavaScript and TypeScript projects. It cuts through the usual setup headaches, speeds up development, and keeps everything simple—even in monorepos. If you’re tired of wrestling with configs and build pipelines, give bun a shot. It just works.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert