Astro adapter for Bun with optimized static file serving and ISR support
npm install @wyattjoh/astro-bun-adapterAn Astro adapter that runs your SSR site on Bun using Bun.serve.
``bash`
bun add @wyattjoh/astro-bun-adapter
`js
// astro.config.mjs
import { defineConfig } from "astro/config";
import bun from "@wyattjoh/astro-bun-adapter";
export default defineConfig({
output: "server",
adapter: bun(),
});
`
Build and run:
`bash`
bun run build
bun run ./dist/server/entry.mjs
- All output modes — static, server, and hybrid are all supported./_astro/*
- Optimized static serving — Pre-rendered pages and static assets are served directly from a build-time manifest with ETag/304 support. Vite-hashed assets () get immutable 1-year cache headers; other static assets default to 24-hour must-revalidate (configurable via staticCacheControl). Pre-rendered HTML pages are accessible via clean URLs (e.g. /about serves /about/index.html). Static responses include an x-astro-cache: STATIC header.experimentalStaticHeaders
- Route-level headers — When Astro's is enabled, per-route headers (e.g. Content-Security-Policy) are included in static responses.
- ISR (Incremental Static Regeneration) — Optional two-tier cache for SSR responses. See ISR below.
By default, non-hashed static assets are served with Cache-Control: public, max-age=86400, must-revalidate. You can override this with the staticCacheControl option:
`js`
adapter: bun({
staticCacheControl: "public, max-age=3600, must-revalidate",
}),
Hashed assets under /_astro/ always use public, max-age=31536000, immutable regardless of this setting. Route-level headers from experimentalStaticHeaders still take precedence over staticCacheControl.
Enable ISR to cache SSR responses using an in-memory LRU backed by persistent disk storage. Cached responses are served according to Cache-Control semantics (s-maxage and stale-while-revalidate).
`js
// astro.config.mjs
import { defineConfig } from "astro/config";
import bun from "@wyattjoh/astro-bun-adapter";
export default defineConfig({
output: "server",
adapter: bun({ isr: true }),
});
`
To customize ISR options:
`js`
adapter: bun({
isr: {
maxByteSize: 100 1024 1024, // In-memory budget (default: 50 MB)
cacheDir: "/tmp/my-cache", // Disk cache directory (default: dist/server/.astro-bun-adapter/isr-cache)
preFillMemoryCache: false, // Load disk cache into memory on startup (default: false)
},
}),
- Responses must include Cache-Control: s-maxage=N to be cached. Stale entries within the stale-while-revalidate window are served immediately while revalidating in the background.s-maxage
- Concurrent requests for the same path are deduplicated — only one SSR render runs at a time.
- Image endpoint responses are automatically ISR-cacheable (the adapter adds to Astro's image Cache-Control).x-astro-cache
- The cache survives restarts: evicted entries stay on disk and reload on demand. Each build gets its own cache namespace, and old caches are cleaned up automatically.
- ISR responses include an header: HIT, STALE, MISS, or BYPASS.
> Note: This API is unstable and experimental. The function names and behavior may change in a future release without following semver.
You can expire individual ISR cache entries on demand using unstable_expirePath. The entry is deleted from the cache and will be lazily re-rendered on the next request.
`ts
import { unstable_expirePath, unstable_expireAll } from "@wyattjoh/astro-bun-adapter/cache";
// Expire a single path:
await unstable_expirePath("/blog/my-post");
// Expire all cached paths:
await unstable_expireAll();
`
Both functions are no-ops when ISR is not enabled, so they're safe to call unconditionally.
- PORT — Override the server port (default: from Astro config or 4321)HOST
- — Override the server hostnameDEBUG
- — Enable debug logging via the debug package. Use DEBUG=@wyattjoh/astro-bun-adapter:* for all adapter logs, or target specific subsystems:@wyattjoh/astro-bun-adapter:isr
- — ISR cache hits, misses, revalidations, and bypasses@wyattjoh/astro-bun-adapter:cache
- — LRU cache internals (evictions, disk persistence, restore)@wyattjoh/astro-bun-adapter:expire
- — On-demand cache expiration via unstable_expirePath / unstable_expireAll`
Inspired by astro-bun-adapter by @ido-pluto.
MIT