Vibe Coding Bundler
Vibe Coding Bundler is a browser-based JavaScript and TypeScript bundler that leverages esbuild-wasm to perform compilation entirely within the browser environment, eliminating the need for a server. Currently at version 1.0.0, its release cadence is feature-driven as an initial offering. Key differentiators include first-class support for standard import maps, a virtual file system for in-memory bundling, and a robust plugin system with `onResolve` and `onLoad` hooks. It supports various output formats (ESM, IIFE, CJS), generates sourcemaps, and performs tree shaking. While it transpiles TypeScript and JSX, it does not perform type checking. An optional Node.js CLI is also provided for local development workflows.
Common errors
-
Error: The 'esbuild-wasm' package was not initialized. Call `await initialize()` first.
cause Attempting to create a bundler or bundle files before the esbuild-wasm module has been loaded and initialized.fixAdd `await initialize();` at the very beginning of your application logic, ensuring it completes before any `createBundler` or `bundle` calls. -
Error: Could not resolve "react" (or similar bare specifier)
cause The bundler could not find a resolution for a bare module specifier (e.g., `import 'react'`) either in the provided virtual file system or via the configured import maps.fixVerify that your `importMap` object correctly defines the bare specifier, including any necessary trailing slashes for subpath imports. Ensure the URL provided in the import map is accessible and returns valid JavaScript. -
TypeError: Failed to fetch (or similar network error)
cause The custom `fetcher` provided to `createBundler` (or the default fetch mechanism) failed to retrieve an external module, likely due to a network issue, CORS policy, or an incorrect URL.fixCheck the URL for correctness and ensure the CDN is accessible. If using a custom `fetcher`, add more robust error handling and logging. For browser usage, inspect the network tab for specific HTTP errors and check browser console for CORS warnings.
Warnings
- gotcha The `initialize()` function, which loads the esbuild-wasm module, must be called exactly once before any `createBundler` or `bundle` operations. Failing to call it will result in errors, and calling it multiple times is redundant and can cause unexpected behavior or performance issues.
- gotcha When using `esbuild-wasm` in a browser, the initial download and compilation of the WebAssembly module can be substantial (several megabytes). This might impact the initial load time of your application. Subsequent uses are cached.
- gotcha The bundler uses esbuild for transpilation of TypeScript and JSX, but it does not perform type checking. This means syntax errors related to types will be ignored, and you will need a separate type-checking step (e.g., `tsc --noEmit`) in your development workflow if type safety is required.
- gotcha Import maps require careful configuration, especially for bare specifiers and subpaths. A common mistake is forgetting the trailing slash for prefix matches (e.g., `lodash/` -> `https://esm.sh/lodash-es/`) or incorrect versioning that leads to module resolution failures.
Install
-
npm install vibe-coding-bundler -
yarn add vibe-coding-bundler -
pnpm add vibe-coding-bundler
Imports
- createBundler
const { createBundler } = require('vibe-coding-bundler');import { createBundler } from 'vibe-coding-bundler'; - initialize
require('vibe-coding-bundler').initialize();import { initialize } from 'vibe-coding-bundler'; - BundlerOptions
import { BundlerOptions } from 'vibe-coding-bundler';import type { BundlerOptions } from 'vibe-coding-bundler';
Quickstart
import { createBundler, initialize } from 'vibe-coding-bundler';
async function runBundler() {
// Initialize esbuild-wasm (only needed once per application lifetime)
await initialize();
// Create a bundler instance with a custom fetcher for external modules
const bundler = createBundler({
fetcher: async (url) => {
// Example: add custom headers or caching logic
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Failed to fetch ${url}: ${response.statusText}`);
}
return { contents: await response.text() };
},
});
// Define virtual files and an import map for resolving bare specifiers
const files = {
'/src/index.ts': `
import { useState } from 'react';
export function App() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}
console.log('App loaded');
`,
};
const importMap = {
imports: {
react: 'https://esm.sh/react@18',
'react/': 'https://esm.sh/react@18/' // Important for subpaths
},
};
// Bundle the code
const result = await bundler.bundle(
'/src/index.ts', // Entry point
files, // Virtual file system
importMap, // Import map configuration
{
format: 'esm',
minify: true,
sourcemap: 'inline',
target: 'es2020'
}
);
// Log the bundled output (typically a single output file 'index.js')
console.log(result.outputFiles['index.js']);
// Example: Run the bundled code in a browser context
const script = document.createElement('script');
script.type = 'module';
script.textContent = result.outputFiles['index.js'];
document.body.appendChild(script);
}
runBundler().catch(console.error);