Static rendering in Sveltekit
Sveltekit is pretty neat. I just rewrote this blog in it, mostly for fun but also because I was getting tired of how absurdly slow Gatsby was. One of the coolest things about it is how easy it was to set up in a way that would work even if the end user didn’t have javascript. Mostly, this was trivial, but getting Vega graphs to render at compile time was a little tricky.
Vega works by taking a JSON specification of a visualization and converting it into HTML. In general, this can’t be done statically, because the visualizations can involve interactivity or simulation, but in most cases that I’ve run into the graph I was trying to produce was in fact static. Creating a component that would render such vega charts with javascript was simple, but when javascript was unavailable all it would ever show was the fallback text. In keeping with the framework-as-a-compiler mindset of Svelte, it seemed like we should be able to do better.
Sveltekit endpoints represent code that will run on the “server” and return some data. When using Sveltekit to produce a static site, this means that they run at build time and produce some static result. By setting up an endpoint which returns an image URL of our vega charts, we can get the charts to be rendered to a static image at compile time and embedded in that form into the blog.
This chart is statically rendered! if you disable javascript you’ll still be able to see it.
There are real costs to this approach from an ergonomics perspective however. Rather than being able to put the vega specifications inline where the chart will be rendered, they instead need to be specified in a module level script, and then pulled in as props in an instance level script. The inline part then becomes an @html
directive, which still gives me scary dangerouslySetInnerHTML
feelings.
The utility for fetching the rendered charts is also significantly harder to read than the original Svelte component. In a personal learning project, this complexity is something I’m willing to accept, but in a production space I’d want real evidence that javascript free pages were of value before implementing something like this.