Last active
January 31, 2025 00:01
-
-
Save mattfysh/897c3c83e06353bbf542122cec38eaa6 to your computer and use it in GitHub Desktop.
bun build --target cloudflare
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import path from 'node:path' | |
import Bun from 'bun' | |
import { z } from 'zod' | |
function soft(to: string, from: string) { | |
return new URL(import.meta.resolve(to, from)).pathname | |
} | |
function hard(to: string, from: string) { | |
return Bun.resolveSync(to, path.dirname(from)) | |
} | |
const BrowserPkgSchema = z.object({ | |
browser: z.string().or(z.record(z.string())), | |
}) | |
const result = await Bun.build({ | |
// using target=bun strips `node:` prefixes from specifiers | |
// but cloudflare requires them, and we cannot use target=browser | |
// or bun will include node polyfil's and does not respect --external | |
// @see https://github.com/oven-sh/bun/issues/2701 | |
target: 'node', | |
entrypoints: ['src/index.ts'], | |
outdir: 'dist', | |
external: ['cloudflare:*'], | |
conditions: ['workerd', 'worker', 'browser'], | |
minify: true, | |
define: { | |
// prevent `createRequire(import.meta.url)` from failing | |
// on cloudflare where this value does not exist | |
'import.meta.url': JSON.stringify('file:///no'), | |
}, | |
plugins: [ | |
{ | |
name: 'sink', | |
setup(build) { | |
const remap: Record<string, string> = {} | |
build.onResolve({ filter: /.*/ }, async args => { | |
try { | |
if (args.path[0] === '.') { | |
const resolved = hard(args.path, args.importer) | |
const browser = remap[resolved] | |
return browser ? { path: browser } : undefined | |
} | |
const pkgPath = soft(`${args.path}/package.json`, args.importer) | |
const file = Bun.file(pkgPath) | |
const contents = await file.json() | |
const { browser } = BrowserPkgSchema.parse(contents) | |
if (typeof browser !== 'string') { | |
for (const [k, v] of Object.entries(browser)) { | |
remap[soft(k, pkgPath)] = soft(v, pkgPath) | |
} | |
return undefined | |
} | |
const entry = path.resolve(path.dirname(pkgPath), browser) | |
return { path: entry } | |
} catch (_) { | |
return undefined | |
} | |
}) | |
}, | |
}, | |
], | |
}) | |
if (!result.success) { | |
throw new Error(String(result.logs.join('\n'))) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment