Bun is an ambitious project that is quickly emerging as a drop-in replacement and faster alternative to Node.js. Here's a look at how Bun works and how to use it for your server-side JavaScript applications. Bun.js is an all-in-one JavaScript toolkit whose lighthearted moniker belies its transformative potential. Bun draws together several important themes in server-side JavaScript, resulting in a single, high-performance tool. It is a runtime like Node or Deno, a package manager like NPM or pnpm, and a build tool like webpack or Vite. It has rapidly evolved from a one-person side project to a compelling alternative to standard approaches. Bun vs. Node.js Bun.js is fundamentally a server-side JavaScript runtime like Node. Atop this is incorporated a package manager and a bundler/transpiler. The runtime itself is the current focus of development and is the most fully realized part of the project. The package manager is the next most developed, and the bundler is the most alpha-stage at the moment. Bun creator Jarred Sumner told me, “We want to make JavaScript faster to run and simpler to write. An important part of that is ecosystem compatibility. Bun is designed as a drop-in Node.js replacement. People shouldn’t have to rewrite their code to use Bun.” Bun is built from the ground up with the WebKit/Safari JavaScriptCore engine (instead of V8 like Node). It is not a fork of Node. The libraries are built in C and Zig, and it explicitly avoids any Node or NPM dependencies, thereby minimizing JavaScript in its stack. These decisions are all in service of maximizing performance. Rewriting the universe of JavaScript-implemented APIs like network and disk IO in a lower level language nets huge performance gains. It’s also a monumental undertaking. Bun aims to cover the entire Node/NPM API, and it is rapidly moving towards that aim. Here’s the Bun project roadmap, where you can get a sense of the scope of the project and how quickly it is moving. Additionally, there’s a list of planned features yet to be implemented. You’ll notice that Bun includes edge-oriented features and much more. It is really an entire JavaScript ecosystem built on top of a runtime engine. Bun is in active development, and its developers acknowledge that “it is experimental software.” Currently, the focus is on expanding and stabilizing the JavaScript runtime. The project is currently in 0.5.5 release. Now that we know what Bus is intended for and have a sense of where it is in its growth trajectory, let’s get our hands on Bun! Install and run a Bun React application You can install Bun as a native package on any operating system. You can also install it as a global NPM package. It might feel a little odd to install an NPM replacement with NPM, but it sure does make the installation easy. Listing 1. Install Bun with NPM $ npm install -g bun $ bun -v 0.5.5 The bun command is now available on your command line. Let’s use Bun to create a new React app. This is the same as entering: npx create-react-app my-app. If you are familiar with using npx (which runs on NPM/Node) then you will immediately notice how fast using Bun works. Run the command in Listing 2 to start a new project using the create-react-app libraries. Listing 2. Run create-react-app $ bun create react ./bun-react [package.json] Detected React - added "react-refresh" $ bun install // This happens automatically [12.00ms] bun install $ bun bun ./src/index.jsx // this happens automatically [720.00ms] bun create react Note that you don’t enter the second two commands; they happen automatically as part of the initial command. You may be surprised to observe that the entire command took less than a second including installing the Node modules. You can now cd into the bun-react/ directory and start the development server with bun dev. You can then visit the application at localhost:3000, where you’ll see a welcome screen like the one shown in Figure 1. IDG Figure 1. The Bun React application welcome screen If you glance at the package.json file, you’ll see it is the same as it would otherwise be, with nothing specific to Bun added. Bun is doing just what NPM would do, but faster. For an unscientific quick check, I rm -rf’d the /mode_modules directory and reinstalled the dependencies with bun install (four milliseconds) versus npm install (two seconds). Bun for edge and serverless deployments What you have just seen is Bun doing the work of a package manager as well as a script runner. When you did bun dev, you were doing the equivalent of npm run dev. The nicety with Bun is again the speed, but that speed also has implications for other areas. Bun is fast at running the task because it is fast at starting up. Most of the time required to run a task with Node/NPM is spent in starting the Node process itself. The fact that Bun is quick to start is an important characteristic in edge and serverless deployments, where the ideal is “scale to zero.” That means you want a system that can spawn nodes to meet demand. Then, when that demand tapers off, it should cheaply drop nodes. A big hurdle to such scalability is the speed at which nodes are able to spin up. So, the ability to rapidly start and execute scripts means Bun is well-suited for edge and serverless computing environments. Bun for Next, Svelte, and Vue Bun can do something similar with a Next application, starting with the command: bun create next ./app. To get a list of all the currently available create commands, type bun create. You’ll notice there’s about a dozen supported templates in Bun .0.5.5. To handle use cases where a built-in loader is not available, Bun.js includes pluggable loaders. This allows for handling files for Svelte or Vue, like .svelte or .vue. You can learn more about Bun’s custom loaders here. There is an experimental SvelteKit adapter to run SvelteKit in Bun. This is very much in development, since the Bun API itself is rapidly evolving and SvelteKit depends on those APIs. (The SvelteKit template obtained with bun create doesn’t seem to be working at the moment.) Bun transpiling and modules One of Bun’s ambitions is to replace the transpilation phase of building. This is complex because it deals with so many different technologies, from CSS to JSX. These are technologies that are subject to change, and thus to complications like tree shaking and minification. Bun also has to deal with JavaScript module resolution, which the Bun documentation acknowledges is complex. The complexity is overwhelming to even think about, which is what prevents most people from attempting something like Bun. Rewriting what is already pretty good (Node/NPM) with something even better is a lofty goal. I’ll refer you again to the Bun roadmap, which includes items related to transpiling, bundling, and module resolution. Bun as a server Bun can run WASM binaries on the server. It can also can handle HTTP requests with a built-in API that is similar to a serverless environment. Let’s take a quick look. If we create a file called server.ts and add the code in Listing 3, we can then run it with Bun. Listing 3. Use Bun as a simple server export default { port: 3000, fetch(request: Request) { return new Response("Hello InfoWorld"); } }; To run the echo server, type bun server.ts. If you browse to localhost:3000, you’ll see the greeting. This works because if Bun finds a default export object with a fetch method, it assumes it’s a server. It wraps this in the Bun.serve API. You can see a simple use of this API in Listing 4. Where appropriate, the APIs found in Bun follow web standards, so the request and response objects are the familiar standards (i.e., Request). Listing 4 uses the Request object to grab the fetched URL and output it. Listing 4. Using the Bun.serve API Bun.serve({ fetch(req) { return new Response("You visited: " + JSON.stringify(req.url)); }, }); Note that Bun’s Node APIs (NAPI) are not complete enough to yet run Express; however, there are a number of similar projects for Bun itself. One example is BunRest. A new approach to server-side JavaScript The Bun roadmap includes many open to-do’s, which provides a sense of the scope and ambition of this project. Bun really looks to become a one-stop shop to perform most server-side JavaScript tasks, including everything from spawning processes to hosting an embedded SQLite instance to running native function with Bun FFI (foreign function interface). Instead of the workflow being: I need to do some JavaScript work, so let me go get the runtime and the package manager and download the specific tools to stand up a working environment, followed by the tools for the task at hand, it becomes: let’s install bunks and get the tools required for the actual work. It is also interesting that Bun uses Zig under the hood. Zig is not only a programming language but a package manager and build tool all in one. This is a sensible trend, because in the past we had the goal of creating a working general-purpose language. That was a big enough goal in itself, and then all the required support for development and production was bolted on afterward. Today, most of us understand that a language will need those things, especially a package manager and a build tool. It makes sense that designers are building them into the language from the ground up. From the 10,000-foot view, it looks like we are seeing a new generation of programming tools that are bootstrapping tools and utilities at a higher level based on past learnings. Now is a very interesting time to be building software. Want to keep learning about Bun? Start with this list of interesting projects in the Bun.js ecosystem. Related content feature 14 great preprocessors for developers who love to code Sometimes it seems like the rules of programming are designed to make coding a chore. Here are 14 ways preprocessors can help make software development fun again. By Peter Wayner Nov 18, 2024 10 mins Development Tools Software Development feature Designing the APIs that accidentally power businesses Well-designed APIs, even those often-neglected internal APIs, make developers more productive and businesses more agile. By Jean Yang Nov 18, 2024 6 mins APIs Software Development news Spin 3.0 supports polyglot development using Wasm components Fermyon’s open source framework for building server-side WebAssembly apps allows developers to compose apps from components created with different languages. By Paul Krill Nov 18, 2024 2 mins Microservices Serverless Computing Development Libraries and Frameworks news Go language evolving for future hardware, AI workloads The Go team is working to adapt Go to large multicore systems, the latest hardware instructions, and the needs of developers of large-scale AI systems. By Paul Krill Nov 15, 2024 3 mins Google Go Generative AI Programming Languages Resources Videos