Bundle source files for Cloudflare's Worker Loader binding (closed beta). Perfect for AI coding agents that need to dynamically generate and deploy javascript code with real npm dependencies.
Installation
npm install workers-builder
Quick Start
Just provide your source code and dependencies — no config files needed:
import { createWorker } from 'workers-builder'; const worker = env.LOADER.get('my-worker', async () => { const { mainModule, modules } = await createWorker({ files: { 'src/index.ts': ` import { Hono } from 'hono'; import { cors } from 'hono/cors'; const app = new Hono(); app.use('*', cors()); app.get('/', (c) => c.text('Hello from Hono!')); app.get('/json', (c) => c.json({ message: 'It works!' })); export default app; `, 'package.json': JSON.stringify({ dependencies: { hono: '^4.0.0' } }), }, }); return { mainModule, modules, compatibilityDate: '2026-01-01' }; }); await worker.getEntrypoint().fetch(request);
The library automatically:
- Detects your entry point (
src/index.tsby default) - Fetches and installs npm dependencies from the registry
- Bundles everything with esbuild
- Returns modules ready for the Worker Loader binding
API
createWorker(options)
| Option | Type | Default | Description |
|---|---|---|---|
files |
Record<string, string> |
required | Source files (path → content) |
entryPoint |
string |
auto | Override entry point detection |
bundle |
boolean |
true |
Bundle into single file |
externals |
string[] |
[] |
Additional modules to exclude (cloudflare:* always excluded) |
minify |
boolean |
false |
Minify output |
sourcemap |
boolean |
false |
Generate inline source maps |
registry |
string |
'https://registry.npmjs.org' |
npm registry URL |
Returns
{ mainModule: string; // Entry point path modules: Record<string, string>; // All output modules wranglerConfig?: { // Parsed from wrangler.toml/json/jsonc main?: string; compatibilityDate?: string; compatibilityFlags?: string[]; }; warnings?: string[]; // Any warnings during bundling }
Entry Point Detection
Priority order:
entryPointoptionmainfield in wrangler configexports,module, ormainfield in package.json- Default paths:
src/index.ts,src/index.js,index.ts,index.js
More Examples
Multiple Dependencies
const worker = env.LOADER.get('my-worker', async () => { const { mainModule, modules } = await createWorker({ files: { 'src/index.ts': ` import { Hono } from 'hono'; import { zValidator } from '@hono/zod-validator'; import { z } from 'zod'; const app = new Hono(); const schema = z.object({ name: z.string() }); app.post('/greet', zValidator('json', schema), (c) => { const { name } = c.req.valid('json'); return c.json({ message: \`Hello, \${name}!\` }); }); export default app; `, 'package.json': JSON.stringify({ dependencies: { hono: '^4.0.0', '@hono/zod-validator': '^0.4.0', zod: '^3.23.0' } }), }, }); return { mainModule, modules, compatibilityDate: '2026-01-01' }; });
With Wrangler Config
For projects that need specific compatibility settings or are migrating from existing Workers:
const worker = env.LOADER.get('my-worker', async () => { const { mainModule, modules, wranglerConfig } = await createWorker({ files: { 'src/index.ts': ` export default { fetch: () => new Response('Hello!') } `, 'wrangler.toml': ` main = "src/index.ts" compatibility_date = "2026-01-01" compatibility_flags = ["nodejs_compat"] `, }, }); return { mainModule, modules, compatibilityDate: wranglerConfig?.compatibilityDate ?? '2026-01-01', compatibilityFlags: wranglerConfig?.compatibilityFlags, }; });
Transform-only Mode
Skip bundling to preserve module structure:
const worker = env.LOADER.get('my-worker', async () => { const { mainModule, modules } = await createWorker({ files: { /* ... */ }, bundle: false, }); return { mainModule, modules, compatibilityDate: '2026-01-01' }; });
Worker Loader Setup
# wrangler.toml (host worker) [[worker_loaders]] binding = "LOADER"
interface Env { LOADER: WorkerLoader; }
Future Work
- Lockfile support: Read
package-lock.json/pnpm-lock.yamlfor deterministic installs
License
MIT