bundlebun
bundlebun bundles Bun—the all-in-one JavaScript runtime, package manager, and build tool—directly into your Ruby gem bundle. No Docker, no curl | sh, no Homebrew required.
-
Zero setup.
bundle add bundlebun && rake bun:installand you're done. -
Team-friendly. Everyone runs the same Bun version, pinned in
Gemfile.lock. - Auto-updating. New Bun release? bundlebun ships it automatically. Or freeze your preferred version.
- Integrates automatically. Works out of the box with vite-ruby, cssbundling-rails, jsbundling-rails, and ExecJS.
bundle add bundlebun
rake bun:install
bin/bun --versionTable of Contents
- Rationale
- Install
- Usage
- Integrations
- Versioning
- Uninstall
- Acknowledgements
- Contributing
- License
Rationale
Modern frontend setup is needlessly complex and may involve a lot of maintenance. Developers need at the very least a JavaScript runtime (typically, Node.js), a package manager (could be npm, yarn, or pnpm), and a build tool (Vite, Webpack, esbuild, Parcel—dozens of them).
- One way forward is to dockerize development environments, creating unnecessary headaches for the development team—both frontend and backend engineers (especially if the team is not that large and the project is not that complex).
- Another approach is to declare front-ops bankruptcy and pursue the "no-build" route.
What if we could simplify this? Bun is a JavaScript runtime, optimized for speed and developer experience. Bun is also a fast JavaScript package manager. Bun is also a build tool. Bun is also distributed as a single executable file.
However, Bun still requires some installation, and we need to make sure everyone on the team is using the same version.
So, how about we just pack it into a Ruby gem as a binary and allow developers to stay updated? Then, we'll be ready every time a new Bun version is out—or the user can freeze their desired version within their Ruby project. There are no setups, large READMEs with instructions, and no enforcing the Docker workflow.
Enter bundlebun. With a fast JavaScript runtime and a package manager included, you can even skip the build tool and use Bun itself.
Install
bundlebun gem releases include a binary distribution of Bun for each supported Bun platform (macOS, Linux, Windows) and architecture. bundlebun is tested for Unix-like environments and Windows.
Add bundlebun to your Gemfile, placing it after your existing frontend-related gems:
# Frontend-related gems go here
# gem "vite_rails"
gem "bundlebun"Then run:
bundle add bundlebun
rake bun:installrake bun:install creates a bin/bun binstub and auto-detects which integrations to enable. It will also offer to migrate package.json scripts and Procfile entries to use bin/bun.
If you're seeing a message like Could not find gems matching 'bundlebun' valid for all resolution platforms (aarch64-linux, aarch64-linux-gnu <...> ), check this article.
Windows: bin\bun.cmd is created instead. If you joined a project with only the Unix binstub, run rake bun:install again.
Usage
Binstub
The easiest way to run Bun is via the bin/bun binstub:
bin/bun install
bin/bun add postcss
bin/bun run buildPATH
bundlebun prepends the bundled Bun directory to your application's PATH. Tools that detect a bun executable (like vite-ruby) find it automatically—no extra configuration needed.
Rake
Alternatively, you can use a Rake task. The syntax is far from perfect—that's a limitation of Rake—but it's an option if you cannot install the binstub. Note the quotes around the parameters:
rake bun[command] # Run bundled Bun with parameters> rake "bun[outdated]"
bun outdated v1.1.38 (bf2f153f)
...Ruby API
Bundlebun.('install') # exec: replaces the current Ruby process with Bun
Bundlebun.call(['add', 'postcss']) # same thing, array formNote: Bundlebun.call (and the () shortcut) replaces the current process—it never returns. Use Bundlebun.system to run Bun and continue executing Ruby:
if Bundlebun.system('install')
puts 'Dependencies installed!'
end
success = Bundlebun.system('test')
# => true if Bun exited successfully, false or nil otherwiseSee the API documentation for full details on Bundlebun::Runner.
Instrumentation
When ActiveSupport is available, bundlebun emits events you can subscribe to:
ActiveSupport::Notifications.subscribe('system.bundlebun') do |event|
Rails.logger.info "Bun: #{event.payload[:command]} (#{event.duration.round(1)}ms)"
endEvents: system.bundlebun (for Bundlebun.system) and exec.bundlebun (for Bundlebun.call). Payload: { command: args }.
Integrations
bundlebun auto-detects and loads integrations when you run rake bun:install—as long as gem "bundlebun" is placed after the relevant gems in your Gemfile.
vite-ruby / vite-rails
vite-ruby and vite-rails are gems that make Ruby and Rails integration with Vite, a great JavaScript build tool and platform, seamless and easy.
The bundlebun integration is installed automatically with rake bun:install, or you can run it explicitly:
rake bun:install:viteThat will make sure you have a bin/bun binstub. Next, it installs a custom bin/bun-vite binstub to use in build scripts, and creates or updates vite.json to use that binstub for building. See the Vite Ruby configuration manual for details on vite.json.
To enable the integration manually:
Bundlebun::Integrations::ViteRuby.bun!cssbundling-rails / jsbundling-rails
cssbundling-rails and jsbundling-rails are Rails gems that support the traditional CSS and JS building pipeline for Ruby on Rails.
Be sure to check both gems for documentation on bootstrapping your frontend build pipeline instead of duplicating approaches here. cssbundling-rails, for instance, includes an excellent sample build configuration for Bun.
# Bootstrap cssbundling-rails
bundle add cssbundling-rails
bin/rails css:install:[tailwind|bootstrap|bulma|postcss|sass]
# Bootstrap jsbundling-rails
bundle add jsbundling-rails
bin/rails javascript:install:bun
# Ensure bundlebun integration
rake bun:install:bundling-railsExecJS
ExecJS runs JavaScript code straight from Ruby. It supports a number of runtimes it can launch—and get a result from. Bun runtime support already exists in ExecJS; bundlebun just ensures it uses the bundled version.
Works automatically when bundlebun loads after ExecJS in your Gemfile. To enable manually:
Bundlebun::Integrations::ExecJS.bun!Versioning
bundlebun versions follow the #{gem.version}.#{bun.version} scheme. For example, 0.1.0.1.1.38 = gem version 0.1.0 + Bun 1.1.38.
New gem versions are published automatically on each Bun release. Lock to a specific Bun version in your Gemfile, or leave it unspecified to always get the latest.
Uninstall
bundle remove bundlebunThen clean up:
-
bin/bun(andbin\bun.cmdon Windows) -
bin/bun-viteif present -
tasks/bundlebun.rakeif present - Any
bin/bunreferences in scripts and configs - Any
Bundlebunreferences in your code
Acknowledgements
Bun binaries are sourced directly from oven-sh/bun releases. Bun was created by Jarred Sumner (@jarred-sumner) and distributed under MIT.
Big thanks to Jason Meller (@terracatta) for his work on Bun's Ruby on Rails ecosystem integration—jsbundling-rails, cssbundling-rails, turbo-rails, stimulus-rails, and ExecJS support—in this Pull Request.
Contributing
Make sure you have up-to-date Ruby. Run bin/setup to install gems, install lefthook, and run rake bundlebun:download to fetch a local Bun build for tests.
Run rake rspec to check tests. Open an issue or a PR.
License
The gem is available as open source under the terms of the MIT License. See LICENSE.txt.
