DEV Community

Cover image for Using Bun Compile/Build to embed an Express / Vite / Vue Application into a Binary
Calum Knott
Calum Knott

Posted on • Edited on

Using Bun Compile/Build to embed an Express / Vite / Vue Application into a Binary

WHY?

OK, So your developing an internal tool using JS... or project for a customer. You want to ship them a 100% self contained binary, that they just run, to launch the tool... No installation steps for the customer, no debugging versions of bun / libraries... You also want some basic ability to avoid having to distribute the source code.

Bun Bundler/Compiler

Bun handles this build step quite well, https://bun.sh/docs/bundler/executables but does have a few small issues, related to packing the files, which can then be locally served.

The issue is the embed dir ability for bun is.... in beta, at best, and seems to have a few quirks. It is also quite hard to get the files back to serve them with express.

So the solution?

1) Build your vite project

vite build
Enter fullscreen mode Exit fullscreen mode

2) Take your /dist directory, and build a virtual file system!

We can use https://github.com/seveibar/make-vfs/ to take our entire dist directory, and repack it as a single .js file. This can produce a fairly heavy file, but as we are distributing the whole thing as a binary anyway, it doesnt matter!

bunx make-vfs --dir ./dist --content-format string --outfile ./bundle/client-bundle-vfs.js
Enter fullscreen mode Exit fullscreen mode

UPDATE

make-vfs seems to be fundementally broken with its implementation of base64 encoding or decoding.

I wrote a new alternative, the repo is updated.

https://gist.github.com/calumk/65d2b9352c92e7e83cbb59fbb205f123


3) Use Express to load and then serve your vfs : (See Repo)

import staticRoutes from "../../dist/client-bundle-vfs.js";
import { lookup } from "es-mime-types"
import express from "express";
import routes from "./routes.js";

const app = express();
// serve express routes
app.use(routes);
// serve the static bundled files
app.use((req, res, next) => {
  const url = new URL(req.url, `http://${req.headers.host}`);
  const path = url.pathname;
  const normalizedPath = path.replace(/^\//, "").replace(/\/$/, "");
  if (staticRoutes[normalizedPath]) {
    let mimeType = lookup(normalizedPath);
    return res.status(200).type(mimeType).send(staticRoutes[normalizedPath]);
  }
  next();
});

// Fallback to assist vue-router
app.use((req, res) => {
  return res.status(200).type("text/html").send(staticRoutes["index.html"]);
});


app.listen(3002, () => {
  console.log("Server is running on http://localhost:3002");
});
Enter fullscreen mode Exit fullscreen mode

4) Build your final applicaion, as the application consumes the vfs, everything is bundled.

bun build ./src/server/main-compile.js --compile --outfile myServer
Enter fullscreen mode Exit fullscreen mode

GitHub logo calumk / vite-express-bun-compiled

vite-express-bun-compiled shows how to compile a vite-vue application using vfs

Vue 3 + Vite + Bun + VFS!

This repository is a template for Vite + Vue 3 + Bun + VFS (Virtual File System)

It is a simple template to get you started with Vue 3 and Vite, using Bun as the package manager and VFS for file system operations.

It is designed to allow you to bundle your Vue 3 application with Vite and run it using Bun, while also providing a simple way to manage your files using VFS.

This allows a standalone application to be run without the need for a server, making it easy to deploy and share your application.






Developer-first embedded dashboards

Developer-first embedded dashboards

Ship pixel-perfect dashboards that feel native to your app with Embeddable. It's fast, flexible, and built for devs.

Get early access

Top comments (0)

Gen AI apps are built with MongoDB Atlas

Gen AI apps are built with MongoDB Atlas

MongoDB Atlas is the developer-friendly database for building, scaling, and running gen AI & LLM apps—no separate vector DB needed. Enjoy native vector search, 115+ regions, and flexible document modeling. Build AI faster, all in one place.

Start Free

👋 Kindness is contagious

Discover this thought-provoking article in the thriving DEV Community. Developers of every background are encouraged to jump in, share expertise, and uplift our collective knowledge.

A simple "thank you" can make someone's day—drop your kudos in the comments!

On DEV, spreading insights lights the path forward and bonds us. If you appreciated this write-up, a brief note of appreciation to the author speaks volumes.

Get Started