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

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 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 ./dist/client-bundle-vfs.js 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"); }); 4) Build your final applicaion, as the application consumes the vfs, everything is bundled. bun build ./src/server/main-compile.js --compile --outfile myServer 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. View on GitHub

May 12, 2025 - 14:49
 0
Using Bun Compile/Build to embed an Express/ Vite / Vue Application

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

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 ./dist/client-bundle-vfs.js


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");
});

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

bun build ./src/server/main-compile.js --compile --outfile myServer

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.