---
title: "Optimización de fuentes para sitios web de Astro"
description: "Encuentre los obstáculos y puntos de control del creador de astro-font, la biblioteca de optimización de fuentes de LaunchFa.st para sitios web de Astro."
source: "https://www.launchfa.st/es/blog/building-astro-font"
author: "Rishi Raj Jain"
created_at: 2024-01-17T00:00:00.000Z
---

> **Site index for agents**
> Fetch https://www.launchfa.st/llms.txt to discover every page on this site.
> Every page is also available as Markdown by appending `.md` to its URL.

<img width="632" height="580" alt="astro-font by LaunchFa.st" loading="eager" class="mt-4 border rounded-sm bg-cover bg-center bg-no-repeat transform will-change-auto" src="https://pbs.twimg.com/media/GEC7gffWUAA0HJZ?format=png&name=small" />

En ~1 mes, `astro-font` ha aumentado a 57.000 descargas 🤯

## Punto de control n.° 1

Todo comenzó cuando pensé en lo que le falta al ecosistema Astro. Después de revisar algunos de los sitios web (incluido mi propio sitio web híbrido Astro, [launchfast](https://launchfast)), descubrí que faltaba una biblioteca de optimización de fuentes de extremo a extremo 👇

## Punto de control #2

Así que me propuse crear un paquete Astro que cumpliera la promesa que pensé que sería súper fácil: usar los scripts `next/font` de @vercel y enviarlo (¡y lo hice desde el principio!) ¡Funcionó muy bien para sitios web estáticos! PERO, ingrese a los sitios web de SSR👇

## Barricada #1

`next/font`, al estar acoplado con el proceso de compilación de Next, tiene acceso a los directorios de salida y a la configuración de tiempo de ejecución esperada y, por lo tanto, aloja automáticamente las fuentes incluso en los sitios web SSR-first. Este espacio se volvió más complejo para los sitios web de Astro SSR a medida que `astro- font` es un componente de Astro y no una integración de Astro. Esto es lo que hice para resolver ese problema 👇

```javascript
async function getOS(): Promise<typeof import('node:os') | undefined> {
  let os
  try {
    os = await import('node:os')
    return os
  } 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) {}
}
```

## Barricada #2

¡Excelente! Eso funcionó y me permitió determinar si la compilación SSR tenía fuentes incluidas y, por lo tanto, me permitió calcular la fuente alternativa en el tiempo de ejecución, PERO, algunos usuarios querían usar URL de CDN o estaban usando fuentes de fuente. No había forma de saberlo. qué [Vite](https://vitejsdev) resolvió las fuentes internas. Por lo tanto, construí un analizador CSS en tiempo de ejecución similar a Google Fonts 👇

```javascript
// Custom script to parseGoogleCSS
function parseGoogleCSS(tmp: string) {
  let match
  const fontFaceMatches = []
  const fontFaceRegex = /@font-face\s*{([^}]+)}/g
  while ((match = fontFaceRegex.exec(tmp)) !== null) {
    const fontFaceRule = match[1]
    const fontFaceObject: any = {}
    fontFaceRule.split(';').forEach((property) => {
      if (property.includes('src: ')) {
        const formatPosition = property.indexOf('for')
        fontFaceObject['path'] = property
          .trim()
          .substring(9, formatPosition ? formatPosition - 5 : property.length - 1)
          .trim()
      }
      if (property.includes('-style: ')) {
        fontFaceObject['style'] = property.split(':').map((i) => i.trim())[1]
      }
      if (property.includes('-weight: ')) {
        fontFaceObject['weight'] = property.split(':').map((i) => i.trim())[1]
      }
      if (property.includes('unicode-range: ')) {
        if (!fontFaceObject['css']) {
          fontFaceObject['css'] = {}
        }
        fontFaceObject['css']['unicode-range'] = property.split(':').map((i) => i.trim())[1]
      }
    })
    fontFaceMatches.push(fontFaceObject)
  }
  return fontFaceMatches
}
```

## Punto de control n.º 3

Parece completo, ¿verdad? Ahora funciona con fuentes locales y fuentes a través de CDN, pero la búsqueda y computación en tiempo de ejecución nos costará tiempo SSR. Para resolver eso, ingrese el almacenamiento en caché de fuentes en tiempo de ejecución 👇

```javascript
const [os, fs] = await Promise.all([getOS(), getFS()])
if (fs) {
    if (os) {
      writeAllowed = await Promise.all([ifFSOSWrites(os.tmpdir()), ifFSOSWrites('/tmp')])
      tmpDir = writeAllowed.find((i) => i !== undefined)
      cacheDir = fontCollection.cacheDir || tmpDir
      if (cacheDir) {
        // Create a json based on slugified path, style and weight
        const slugifyPath = (i: Source) => `${i.path}_${i.style}_${i.weight}`
        const slugifiedCollection = fontCollection.src.map(slugifyPath)
        const cachedFileName = simpleHash(slugifiedCollection.join('_')) + '.txt'
        cachedFilePath = join(cacheDir, cachedFileName)
        if (fs.existsSync(cachedFilePath)) {
          try {
            const tmpCachedFilePath = fs.readFileSync(cachedFilePath, 'utf8')
            return JSON.parse(tmpCachedFilePath)
          } catch (errorReadingCache) {}
        }
      }
    }
}
```

## Punto de control #4

¿Ahora? ¡Solo nos queda una cosa por hacer: Permitir precargas por fuente por configuración (y soporte hacia atrás para precargas globales (no))!

```javascript
// If the parent preload is set to be false, look for true only preload values
if (fontCollection.preload === false) {
    return fontCollection.src
        .filter((i) => i.preload === true)
        .map((i) => getRelativePath(getBasePath(fontCollection.basePath), i.path))
}

// If the parent preload is set to be true (or not defined), look for non-false values
return fontCollection.src
    .filter((i) => i.preload !== false)
    .map((i) => getRelativePath(getBasePath(fontCollection.basePath), i.path))
```

Y terminamos, y está en producción para [muchos sitios web de Astro](/blog/astro-font-showcase) ✨

<typeof import('node:os') | undefined><string | undefined>¡Gracias por ese increíble paquete que me ayudó a luchar contra el "cambio de diseño"!<blockquote class="twitter-tweet">Lo agregaré a Best of JS, ya que tenemos una etiqueta `Astro` [[ HTML_TAG]]https://tco/38Akqa5IQd<p lang="en" dir="ltr"><br>- Michael Rambeau (@michaelrambeau) <a href="https://t.co/38Akqa5IQd">17 de enero de 2024</a></p> [[HTML_TAG] ]<a href="https://twitter.com/michaelrambeau/status/1747612731728179669?ref_src=twsrc%5Etfw">

</a> </blockquote><script defer src="https://platform.twitter.com/widgets.js" charset="utf-8"></script><div class="columns-2"><img alt="Astro Font development screenshot" loading="lazy" class="mt-8 w-full rounded-sm" src="https://ik.imagekit.io/vjeqenuhn/launchfast-website/Screenshot%202024-01-11%20at%2011.36.59%E2%80%AFAM.png" ><img alt="Astro Font development screenshot" loading="lazy" class="mt-8 w-full rounded-sm" src="https://ik.imagekit.io/vjeqenuhn/launchfast-website/Screenshot%202024-01-18%20at%208.39.40%E2%80%AFPM.png" ><img alt="Astro Font development screenshot" loading="lazy" class="mt-8 w-full rounded-sm" src="https://ik.imagekit.io/vjeqenuhn/launchfast-website/Screenshot%202024-01-18%20at%208.40.02%E2%80%AFPM.png" ><img alt="Astro Font development screenshot" loading="lazy" class="mt-8 w-full rounded-sm" src="https://ik.imagekit.io/vjeqenuhn/launchfast-website/Screenshot%202024-01-18%20at%208.37.44%E2%80%AFPM.png" ><img alt="Astro Font development screenshot" loading="lazy" class="mt-8 w-full rounded-sm" src="https://ik.imagekit.io/vjeqenuhn/launchfast-website/Screenshot%202024-01-18%20at%2010.07.00%E2%80%AFAM.png" > <img alt="Astro Font development screenshot" loading="lazy" class="mt-8 w-full rounded-sm" src="https://ik.imagekit.io/vjeqenuhn/launchfast-website/Screenshot%202024-01-18%20at%208.38.50%E2%80%AFPM.png" ><img alt="Astro Font development screenshot" loading="lazy" class="mt-8 w-full rounded-sm" src="https://ik.imagekit.io/vjeqenuhn/launchfast-website/Screenshot%202024-01-18%20at%208.35.19%E2%80%AFPM.png" > <img alt="Astro Font development screenshot" loading="lazy" class="mt-8 w-full rounded-sm" src="https://ik.imagekit.io/vjeqenuhn/launchfast-website/Screenshot%202024-01-18%20at%208.36.25%E2%80%AFPM.png" >
