Getting started with Bun on Windows

Jack Reeve
Version 1
Published in
4 min readDec 11, 2023

!!! As of 1.1, Bun now runs natively on Windows — see the official blog for more information !!!

What is Bun?

Bun is a new and exciting JavaScript toolkit that promises to revolutionize the way we develop, test, run, and bundle JavaScript and TypeScript projects. It is not just a runtime, but also a package manager, a test runner, a bundler, and more (basically a replacement for NodeJS while still being compatible with node modules).

Bun uses JavaScriptCore under the hood (like safari) instead of the V8 engine that Node uses (as does Chrome), giving it faster start up times and a smaller memory footprint than NodeJS/Deno. It also treats Typescript as a first class citizen, handling the transpiling automatically, so there’s no need to mess around with the likes of babel or tsc anymore!

Check it out at https://bun.sh/

Prerequisites

Unfortunately Bun does not run natively on Windows as of 1.0.7. We can use WSL to bridge this gap however.

Install WSL

Firstly, you’ll need to be on a recent version of Windows that supports WSL (Windows 10 build 19046 or higher. Or Windows 11)

Running wsl --install will either install WSL for you or launch an existing installation if one exists. Check the Microsoft Learn guide for more information

Install Bun

Once inside a WSL instance, installing bun is as simple as running one command. When finished, it will instruct you to source your env and then check bun installed correctly by running its help command.

curl -fsSL https://bun.sh/install | bash
source ~/.bashrc
bun --help

Create a new project

Create a new folder for the project

mkdir bun-project && cd bun-project

Install types for Bun built in APIs

bun add -d bun-types

Add a tsconfig.json

The following is the complete example tsconfig.json taken from Bun’s own documentation (https://bun.sh/guides/runtime/typescript)

{

"compilerOptions": {
// add Bun type definitions
"types": [
"bun-types"
],
// enable latest features
"lib": [
"esnext"
],
"module": "esnext",
"target": "esnext",
// if TS 5.x+
"moduleResolution": "bundler",
"noEmit": true,
"allowImportingTsExtensions": true,
"moduleDetection": "force",
// if TS 4.x or earlier
// "moduleResolution": "nodenext",
"jsx": "react-jsx", // support JSX
"allowJs": true, // allow importing `.js` from `.ts`
"esModuleInterop": true, // allow default imports for CommonJS modules
// best practices
"strict": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true
}
}

Debugging in VSCode

Install the “Bun for Visual Studio Code” extension by Oven

Reload after installing. Although not prompted, I got errors when trying to launch the debugger.

Create a vscode launch configuration

mkdir .vscode && touch .vscode/launch.json

The launch.json file should look like the following

{
"version": "0.2.0",
"configurations": [
{
"type": "bun",
"request": "launch",
"name": "Debug Bun",
// The path to a JavaScript or TypeScript file to run.
"program": "index.ts",
// The arguments to pass to the program, if any.
"args": [],
// The working directory of the program.
"cwd": "${workspaceFolder}",
// The environment variables to pass to the program.
"env": {},
// If the environment variables should not be inherited from the parent process.
"strictEnv": false,
// If the program should be run in watch mode.
// This is equivalent to passing `--watch` to the `bun` executable.
// You can also set this to "hot" to enable hot reloading using `--hot`.
"watchMode": false,
// If the debugger should stop on the first line of the program.
"stopOnEntry": false,
// If the debugger should be disabled. (for example, breakpoints will not be hit)
"noDebug": false,
// The path to the `bun` executable, defaults to your `PATH` environment variable.
"runtime": "bun",
// The arguments to pass to the `bun` executable, if any.
// Unlike `args`, these are passed to the executable itself, not the program.
"runtimeArgs": [
"--inspect=ws://localhost:6499/77me1nrm1g6"
],
},
{
"type": "bun",
"request": "attach",
"name": "Attach to Bun",
// The URL of the WebSocket inspector to attach to.
// This value can be retrieved by using `bun --inspect`.
"url": "ws://localhost:6499/",
}
]
}

Note: This is pretty much what’s instructed on the Bun for Visual Studio Code extension page with a couple of changes

Pressing F5 (or Debug) would cause the current file to be debugged (or fail if there is no file open). This is unlike how we’re used to debugging in traditional NodeJS projects where the entry point is usually static. I’ve hardcoded “index.ts” as the entry point here, but feel free to use whatever, or revert it back to ${file} if you prefer

// The path to a JavaScript or TypeScript file to run.
- "program": "${file}",
+ "program": "index.ts",

Each time a new debugger is started, the characters on the end of the URL will be different making it hard to VSCode to know where to attach to. Here we just give it a static URL to use, these characters can probably be arbitrary, but I’ve copied a random string it previously generated

// The arguments to pass to the `bun` executable, if any.
// Unlike `args`, these are passed to the executable itself, not the program.
"runtimeArgs": [
+ "--inspect=ws://localhost:6499/77me1nrm1g6"
],

Testing it works

Create an index.ts with some basic code with a breakpoint on the last line

const server = Bun.serve({
port: 3000,
fetch(request) {
return new Response("Welcome to Bun!");
},
});

console.log(`Listening on localhost:${server.port}`);

Press F5 (or debug) and see the breakpoint light up!

I’m really excited to see where Bun goes in the future. I love the built in tooling and it’s immediate start up never ceases to amaze me. It’s biggest weakness by far right now is the lack of native Windows support. WSL is a great tool for development that mostly just works (tm) but some gotchas surface from time to time that are just suck the fun out of living on the bleeding edge.

About the Author:
Jack Reeve is a Full Stack Software Developer at Version 1.

--

--