Repository navigation
perf(artifacts): precompile artifacts at save time so the frame skips Sucrase and Tailwind - #28
Merged
Conversation
Add a React-free precompileArtifact() that runs the Sucrase JSX transform and a Tailwind build against the same input the sandboxed frame compiles at runtime. Class candidates come from a bracket-aware source scanner, and code that builds class names dynamically is detected so it keeps the runtime path. A generated fingerprint over the compiler, extractor, theme and pinned versions marks compiled output as current. Nothing is wired yet. Pin tailwindcss and @tailwindcss/browser to one catalog version so the precompiled CSS and the runtime fallback agree. Claude-Session: https://claude.ai/code/session_019ZE3j9YzRKxT4LaiDCBv6S
…nder reads Add an optional ArtifactCompiler port to the executor config. When a host provides one, artifacts.save compiles the source and stores the fingerprint, JS and CSS in three new nullable columns. The compile step is fail-open: a failure saves the artifact with empty compiled columns. artifacts.get stays light and does not read the compiled columns. The new artifacts.getForRender returns them, and recompiles and writes back output stored under an older fingerprint, guarded on the source it compiled so a concurrent save wins. The HTTP get endpoint now returns an optional compiled field. The save payload is unchanged, so clients cannot supply compiled output. host-cloudflare wires the compiler through a lazy import. Includes the cloud schema and migration regeneration for the new columns. Claude-Session: https://claude.ai/code/session_019ZE3j9YzRKxT4LaiDCBv6S
…in the frame When an artifact arrives with output from the server compiler that matches the shell's own fingerprint, the renderer frame embeds the stored CSS and runs the stored JS. It loads neither the Tailwind browser compiler nor Sucrase, so the srcdoc is smaller and the first paint is already styled. Any mismatch, or a missing half (classes built at runtime keep Tailwind, uncompilable code keeps Sucrase), falls back to the previous behavior per half. Sucrase moves out of the inner renderer into its own bundle served as virtual:executor-inner-compiler and only included when needed. The console passes the stored compiled output to the shell on both the tool input and the tool result. The artifact-style skill now tells the model to write every class as a complete literal. Claude-Session: https://claude.ai/code/session_019ZE3j9YzRKxT4LaiDCBv6S
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #27.
Why
Every artifact view compiled the stored JSX with Sucrase, and JIT-compiled its Tailwind classes, inside the sandboxed frame. The srcdoc also carried both compilers: the 271 KB Tailwind browser bundle and about 200 KB of Sucrase.
What changes
Three commits:
precompileArtifactthat runs Sucrase (same options as the frame) and then the Tailwind v4compile()API (same input as the frame).css: null.tailwindcssand@tailwindcss/browserare pinned to one version (4.2.2).compiled_fingerprint,compiled_jsandcompiled_css.getForRenderrecompiles stale or missing output and writes it back. The write is guarded on the compiledcode, so a concurrent save always wins.getand every tool-call path skip the compiled columns.GET /api/artifacts/:idreturnscompiled. Clients cannot send it.0022is generated. D1 adds the columns at runtime.Measurements
Tests
getForRenderbackfill, and the concurrent-save race.compiledis returned, and a client-sentcompiledis not stored.cloudflare/artifact-precompiled-styles.test.tspasses in workerd.@executor-js/desktop(electron.vite.config.tsplugin type mismatch), a known upstream issue not touched here.https://claude.ai/code/session_019ZE3j9YzRKxT4LaiDCBv6S