To prevent massive Shiki source code from being inlined in HTML and bloating the initial payload, move highlighting from build-time to on-demand.
- Create an API route at
app/api/highlight/route.ts to handle highlighting requests. - Modify the component wrapper (e.g.,
DocsPreviewWrapper) to receive raw sourceCode instead of pre-rendered HTML. Use fetch to call the API route only when the user clicks "View Source". - Update layouts to pass only the raw
sourceCode string and sourceCodeFilename instead of sourceCodeContent. - Remove build-time calls to
readComponentSource() from individual docs components.
// 1. API Route: app/api/highlight/route.ts
import { highlightCode } from "@/lib/shiki"
import { NextRequest, NextResponse } from "next/server"
export async function POST(req: NextRequest) {
const { code, lang = "tsx" } = await req.json()
const html = await highlightCode(code, lang)
return NextResponse.json({ html })
}
// 2. Client-side implementation in DocsPreviewWrapper
const [sourceHtml, setSourceHtml] = useState<string | null>(null)
const [isLoadingSource, setIsLoadingSource] = useState(false)
const handleViewSource = async () => {
setShowSource(true)
if (!sourceHtml && sourceCode) {
setIsLoadingSource(true)
const res = await fetch("/api/highlight", {
method: "POST",
body: JSON.stringify({ code: sourceCode }),
})
const { html } = await res.json()
setSourceHtml(html)
setIsLoadingSource(false)
}
}