DEV Community

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

Posted on

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






Top comments (0)