Deployment
Build both bundles, then serve the result:
deno task build # client + SSR build
deno task start # serve the buildServes on port 8000. To change it, run deno serve directly with --port before the entry:
deno serve -A --port 3000 server.prod.tsThe production entry
server.prod.ts serves static files from dist/client and falls through to the app's SSR routes. Content-hashed files under /assets/ are pinned forever; public/ files keep stable names, so they revalidate.
import app from "./dist/server/server.mjs";
import { serveStatic } from "chevalier/static";
const CLIENT_DIR = new URL("./dist/client", import.meta.url).pathname;
const IMMUTABLE = "public, max-age=31536000, immutable";
const REVALIDATE = "public, no-cache";
export default {
fetch: serveStatic({
fsRoot: CLIENT_DIR,
fallthrough: (req) => app.fetch(req),
cacheControl: (pathname) =>
pathname.startsWith("/assets/") ? IMMUTABLE : REVALIDATE,
}),
};A CDN in front is still recommended for high traffic.
Deno Deploy
Deploy doesn't run Vite, so build first, then ship dist/ — it's gitignored, so include it explicitly:
deno task build
deno install -Arf jsr:@deno/deployctl
deployctl deploy --include=dist --include=deno.json --entrypoint=server.prod.ts