Reading assets on the server in SvelteKit
SvelteKit 2.4 brought a new read
helper function to read an asset from the filesystem. This is a quick post on how this function simplifies some very hacky code I wrote for an old demo.
Back in 2022 I wrote an extensive post on using Vercel's Satori library to create social sharing images using Svelte. I just went back and updated that post, so it should still be relevant for 2024. However, the most awkward part of that first demo was needing to write a custom Vite plugin to let us import a font and transform it into the raw font data that Satori needs.
Part of the reason we needed to do this is because there wasn't a great way to read the file from the filesystem at runtime. Sure, at dev time we can use Node's fs.readFileSync
to read the font data. However, once we deploy our app, we don't have the same guarantees about how the filesystem is structured, and accessing the asset gets more complicated.
SvelteKit's new read
helper simplifies this. If you give it the URL of an imported asset, it will return a Response with the contents of that asset. So instead of writing a custom plugin to get the raw font data, I can do this instead:
import {read} from '$app/server';
import sourceSerifPro from '$lib/fonts/SourceSerifPro-Regular.ttf';
const fontData = read(sourceSerifPro).arrayBuffer();
// then later, when calling Satori:
satori(markup, {
fonts: [
{
name: 'Source Serif Pro',
data: await fontData,
style: 'normal'
}
]
});
Much cleaner! You can take a look at the deployed demo to see it in action.
Other quick notes:
- this functionality needs to be implemented by the adapter you're using. The initial PR included support for Vercel and Netlify (for serverless functions, not edge functions), as well as the regular Node adapter.
- because this uses Vite's asset handling, glob imports work too
For another look at this feature, see Rich Harris' demo video:
Previous Blog Post: Svelte Radio Episode 70: View Transitions in SvelteKit and beyond
Next Blog Post: You can’t preload SVG sprites (but I want to)