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
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.