DEV Community

Rishi Raj Jain
Rishi Raj Jain

Posted on

Experience of building a complete? font optimization package for Astro websites

Rishi is always in awe of how Vercel promotes open-source and use it as the medium to grow, staying relevant to developers. Not long ago, next/font was released and it set a great bar of how fonts DX (and ultimately UX) shall be.

As you'd know, Rishi loves Astro, so he thought of bringing this automatic font optimization to the Astro ecosystem. He set out for building astro-font inspired by next/font which'd:

  • let one specify a config and generate CSS based on off of it
  • generate fallback font CSS preventing layout shifts
  • allow to optionally preload fonts for best font loading practices

Rishi is an Astro Community Award Winner in 2022. Also, he's building LaunchFa.st - Astro Boilerplate.

On 15th December, 2023, Rishi released astro-font the community first npm package that aimed at enabling font optimization in all runtimes with Astro. Today, the adpotion has scaled to 4.4K NPM Downloads, LaunchFa.st maintaining a changelog for astro-font and people loving the ease of setting up Astro Font in their projects 👇🏻

Well, it's not all silver bullets. Here are some of the roadblocks Rishi faced in developing the ideal library for fonts (and still working on it):

1. Supporting all Astro adapters

As astro-font is an Astro component (allowing greater granular control) and not an Astro integration, it became increasingly difficult to detect the runtime (Node, Deno, etc.) and adjust the operations such as fetching & reading font buffer, localizing fonts to the project repo, cache & save the generated CSS in the right output directory.

This is still the reason why astro-font requires some work to support atomic + SSR-first Astro projects. Packages like carton aim at bridging this technical gap by allowing to render components in isolation, de-coupling it from the project specific requirements.

2. Detecting if read & writes are allowed

All of the sites today are built on two systems: user's local and on the cloud. Both runtimes use different OS (say developing on windows and deploying on ubuntu) AND read and write permissions (based on the cloud provider and configurations).

To detect this astro-font tries and handles the failure to do so. For example to check if file system module is accessible and writes are allowed:

// Check if file system can be accessed
async function getFS(): Promise<typeof import('node:fs') | undefined> {
  let fs
  try {
    fs = await import('node:fs')
    return fs
  } catch (e) {}
}

// Check if writing is permitted by the file system
async function ifFSOSWrites(dir: string): Promise<string | undefined> {
  try {
    const fs = await getFS()
    if (fs) {
      const testDir = join(dir, '.astro_font')
      if (!fs.existsSync(testDir)) fs.mkdirSync(testDir)
      fs.rmSync(testDir, { recursive: true, force: true })
      return dir
    }
  } catch (e) {}
}
Enter fullscreen mode Exit fullscreen mode

Well, that was it. Hope you gained some insight into what's going on with astro-font and Rishi's excitement around it.

Drop your suggestions & feedback on Astro Font, or just some tips for someone learning to build a npm package and help developers!

Top comments (0)