Reading assets on the server in SvelteKit

— 3 minute read

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:

Want to find out when I post a new article? Follow me on Mastodon or Bluesky or subscribe to my RSS feed. I also have an email newsletter that I'll send out when I post something new, along with anything else I find interesting.

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)