Blog

Lista de comprobación del rendimiento del front-end 2021

¿Está optimizada la entrega de fuentes web?
La primera pregunta que vale la pena hacerse es si podemos salirnos con la suya utilizando las fuentes del sistema de interfaz de usuario en primer lugar – sólo tenemos que asegurarnos de comprobar que aparecen correctamente en varias plataformas. Si no es así, es muy probable que las fuentes web que estamos sirviendo incluyan glifos y características y pesos adicionales que no se están utilizando. Podemos pedir a nuestra fundición tipográfica que subconjunto de fuentes web o si estamos usando fuentes de código abierto, subsetarlas por nuestra cuenta con Glyphhanger o Fontsquirrel. Incluso podemos automatizar todo nuestro flujo de trabajo con el programa de Peter Müller subfont, una herramienta de línea de comandos que analiza estáticamente tu página para generar los subconjuntos de fuentes web más óptimos, y luego inyectarlos en nuestras páginas.

Soporte para WOFF2 es genial, y podemos utilizar WOFF como alternativa para los navegadores que no lo soportan – o tal vez los navegadores heredados podrían recibir fuentes del sistema. Hay muchos, muchos, muchos opciones para la carga de fuentes web, y podemos elegir una de las estrategias de Zach Leatherman “Guía completa de estrategias de carga de fuentes,” (fragmentos de código también disponibles como Recetas de carga de fuentes web).

Probablemente las mejores opciones a considerar hoy en día son FOFT crítico con preload y “Método “El Compromiso. Ambos utilizan un de dos etapas para entregar las fuentes web en pasos – primero un pequeño supersubconjunto necesario para renderizar la página de forma rápida y precisa con la fuente web, y luego cargar el resto de la familia de forma asíncrona. La diferencia es que la técnica “The Compromise” carga el polyfill de forma asíncrona sólo si eventos de carga de fuentes no son compatibles, por lo que no es necesario cargar el polyfill por defecto. ¿Necesitas una victoria rápida? Zach Leatherman tiene un tutorial rápido de 23 minutos y un caso práctico para poner en orden sus fuentes.

En general, puede ser una buena idea utilizar el preload para precargar las fuentes, pero en su marcado incluya las sugerencias después de el enlace con el CSS y el JavaScript críticos. Con preload, hay un rompecabezas de prioridades, así que considere la posibilidad de inyectar rel="preload" en el DOM justo antes de los scripts externos de bloqueo. Según Andy Davies, “los recursos inyectados mediante un script se ocultan al navegador hasta que el script se ejecuta, y podemos utilizar este comportamiento para retrasar el momento en que el navegador descubre el preload pista”. De lo contrario, la carga de la fuente le costará en el primer tiempo de renderizado.

Una captura de pantalla de la diapositiva 93 que muestra dos ejemplos de imágenes con un título al lado que dice 'Priorización de métricas: precarga de una de cada familia'
Cuando todo es crítico, nada es crítico. precargue sólo una o un máximo de dos fuentes de cada familia. (Crédito de la imagen: Zach Leatherman – diapositiva 93) (Vista previa grande)

Es una buena idea ser selectivo y escoge los archivos que más importan, por ejemplo, los que son críticos para el renderizado o los que te ayudarían a evitar reflujos de texto visibles y molestos. En general, Zach aconseja precargar una o dos fuentes de cada familia – también tiene sentido retrasar la carga de algunas fuentes si son menos críticas.

Se ha vuelto bastante común el uso de local() (que se refiere a una fuente local por su nombre) cuando se define un font-family en el @font-face regla:

/* Warning! Not a good idea! */
@font-face {
  font-family: Open Sans;
  src: local('Open Sans Regular'),
       local('OpenSans-Regular'),
       url('opensans.woff2') format ('woff2'),
       url('opensans.woff') format('woff');
}

La idea es razonable: algunas fuentes populares de código abierto, como Open Sans, vienen preinstaladas con algunos controladores o aplicaciones, por lo que si la fuente está disponible localmente, el navegador no necesita descargar la fuente web y puede mostrar la fuente local inmediatamente. Como Bram Stein señaló“aunque una fuente local coincida con el nombre de una fuente web, lo más probable es que no sea la misma fuente. Muchas fuentes web difieren de su versión “de escritorio”. El texto puede representarse de forma diferente, algunos caracteres pueden retroceder a otras fuentes, las características OpenType pueden faltar por completo o la altura de la línea puede ser diferente”.

Además, como los tipos de letra evolucionan con el tiempo, la versión instalada localmente podría ser muy diferente de la fuente web, con caracteres de aspecto muy distinto. Así que, según Bram, es mejor no mezclar nunca fuentes instaladas localmente y fuentes web en @font-face reglas. Google Fonts ha seguido su ejemplo desactivando local() en los resultados del CSS para todos los usuarios, aparte de las solicitudes de Android para Roboto.

A nadie le gusta esperar a que se muestre el contenido. Con la font-display Descriptor CSSpodemos controlar el comportamiento de carga de la fuente y permitir que el contenido sea legible inmediatamente (con font-display: optional) o casi inmediatamente (con un tiempo de espera de 3s, siempre y cuando la fuente se descargue con éxito – con font-display: swap). (Bueno, es un un poco más complicado que eso.)

Sin embargo, si quiere minimizar el impacto de los reflujos de textopodríamos utilizar el API de carga de fuentes (compatible con todos los navegadores modernos). Específicamente eso significa que para cada fuente, crearíamos un FontFace y luego tratar de obtenerlas todas, y sólo entonces aplicarlas a la página. De esta manera, nosotros agrupamos todos los repintados cargando todas las fuentes de forma asíncrona, y luego cambiar de las fuentes de reserva a la fuente web exactamente una vez. Echa un vistazo a La explicación de Zacha partir del minuto 32:15, y la fragmento de código):

/* Load two web fonts using JavaScript */
/* Zach Leatherman: https://noti.st/zachleat/KNaZEg/the-five-whys-of-web-font-loading-performance#sWkN4u4 */

// Remove existing @font-face blocks
// Create two
let font = new FontFace("Noto Serif", /* ... */);
let fontBold = new FontFace("Noto Serif, /* ... */);

// Load two fonts
let fonts = await Promise.all([
  font.load(),
  fontBold.load()
])

// Group repaints and render both fonts at the same time!
fonts.forEach(font => documents.fonts.add(font));

Para iniciar una obtención muy temprana de las fuentes con la API de carga de fuentes en uso, Adrian Bece sugiere añadir un espacio de no ruptura nbsp; en la parte superior del bodyy ocultarlo visualmente con aria-visibility: hidden y un .hidden clase:

<body class="no-js">
  <!-- ... Website content ... -->
  <div aria-visibility="hidden" class="hidden" style="font-family: '[web-font-name]'">
      <!-- There is a non-breaking space here -->
  </div>
  <script>
    document.getElementsByTagName("body")[0].classList.remove("no-js");
  </script>
</body>

Esto va junto con el CSS que tiene diferentes familias de fuentes declaradas para diferentes estados de carga, con el cambio activado por la API de carga de fuentes una vez que las fuentes se han cargado con éxito:

body:not(.wf-merriweather--loaded):not(.no-js) {
  font-family: [fallback-system-font];
  /* Fallback font styles */
}

.wf-merriweather--loaded,
.no-js {
  font-family: "[web-font-name]";
  /* Webfont styles */
}

/* Accessible hiding */
.hidden {
  position: absolute;
  overflow: hidden;
  clip: rect(0 0 0 0);
  height: 1px;
  width: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
}

Si alguna vez te has preguntado por qué, a pesar de todas tus optimizaciones, Lighthouse sigue sugiriendo eliminar los recursos que bloquean la renderización (las fuentes), en el mismo artículo Adrian Bece proporciona algunas técnicas para hacer feliz a Lighthouse, junto con un Gatsby Omni Font Loader, un plugin de carga asíncrona de fuentes y manejo de texto sin estilo (FOUT) para Gatsby.

Ahora, muchos de nosotros podríamos estar usando un CDN o un host de terceros para cargar las fuentes web. En general, es siempre mejor para alojar por sí mismo todos sus activos estáticos si puedes, así que considera usar google-webfonts-helper, una forma de autoalojar Google Fonts sin complicaciones. Y si no es posible, quizás puedas proxy los archivos de Google Font a través del origen de la página.

Sin embargo, cabe destacar que Google está haciendo bastante trabajo fuera de la caja, por lo que un servidor puede necesitar un poco de ajuste para evitar retrasos (¡gracias, Barry!)

Esto es bastante importante sobre todo porque desde Chrome v86 (lanzado en octubre de 2020), los recursos cross-site como las fuentes no pueden ser compartidas en el mismo CDN debido a la caché del navegador particionado. Este comportamiento fue por defecto en Safari durante años.

Pero si no es posible en absoluto, hay una manera de llegar a más rápido posible de Google Fonts con el fragmento de Harry Roberts:

<!-- By Harry Roberts.
https://csswizardry.com/2020/05/the-fastest-google-fonts/

- 1. Preemptively warm up the fonts’ origin.
- 2. Initiate a high-priority, asynchronous fetch for the CSS file. Works in
-    most modern browsers.
- 3. Initiate a low-priority, asynchronous fetch that gets applied to the page
-    only after it’s arrived. Works in all browsers with JavaScript enabled.
- 4. In the unlikely event that a visitor has intentionally disabled
-    JavaScript, fall back to the original method. The good news is that,
-    although this is a render-blocking request, it can still make use of the
-    preconnect which makes it marginally faster than the default.
-->

<!-- [1] -->
<link rel="preconnect"
      href="https://fonts.gstatic.com"
      crossorigin />

<!-- [2] -->
<link rel="preload"
      as="style"
      href="$CSS&display=swap" />

<!-- [3] -->
<link rel="stylesheet"
      href="$CSS&display=swap"
      media="print" onload="this.media="all"" />

<!-- [4] -->
<noscript>
  <link rel="stylesheet"
        href="$CSS&display=swap" />
</noscript>

La estrategia de Harry consiste en calentar primero el origen de las fuentes. Luego iniciamos una búsqueda asíncrona de alta prioridad para el archivo CSS. Después, iniciamos una búsqueda asíncrona de baja prioridad que se aplica a la página sólo después de que haya llegado (con un truco para imprimir la hoja de estilo). Por último, si no se admite JavaScript, volvemos al método original.

Ah, hablando de Google Fonts: se puede reducir hasta el 90% del tamaño de las solicitudes de Google Fonts mediante declarando sólo los caracteres que necesita con &text. Además, el soporte para la visualización de fuentes fue añadido recientemente a Google Fonts también, así que podemos usarlo de forma inmediata.

Una palabra rápida de precaución sin embargo. Si usted utiliza font-display: optional, se podría ser subóptimo utilizar también preload ya que activará esa solicitud de fuente web antes de tiempo (causando congestión de la red si tiene otros recursos de ruta crítica que necesitan ser recuperados). Utilice preconnect para solicitudes más rápidas de fuentes entre orígenes, pero tenga cuidado con preload ya que la precarga de fuentes desde un origen diferente provocará contención en la red. Todas estas técnicas están cubiertas en el artículo de Zach Recetas de carga de fuentes web.

Por otro lado, podría ser una buena idea no utilizar las fuentes web (o al menos la segunda etapa de renderizado) si el usuario ha habilitado Reducir movimiento en las preferencias de accesibilidad o ha optado por Modo de ahorro de datos (ver Save-Data cabecera), o cuando el usuario tiene una conectividad lenta (mediante API de información de red).

También podemos utilizar el prefers-reduced-data CSS media query para no definir las declaraciones de fuentes si el usuario ha optado por el modo de ahorro de datos (hay otros casos de uso, también). La consulta de medios básicamente expondría si el Save-Data de la extensión HTTP Client Hint está activada/desactivada para permitir su uso con CSS. Actualmente soportado sólo en Chrome y Edge detrás de una bandera.

¿Métrica? Para medir el rendimiento de la carga de las fuentes web, considere el Todo el texto visible (el momento en que todas las fuentes se han cargado y todo el contenido se muestra en fuentes web), Tiempo de cursiva real así como Recuento de fuentes web después de la primera renderización. Obviamente, cuanto más bajas sean ambas métricas, mejor será el rendimiento.

¿Qué pasa con fuentes variables¿se preguntará? Es importante tener en cuenta que variable las fuentes pueden requerir un consideración significativa de rendimiento. Nos dan un espacio de diseño mucho más amplio para las opciones tipográficas, pero tiene el coste de una única petición en serie frente a una serie de peticiones de archivos individuales.

Mientras que las fuentes variables reducen drásticamente el tamaño total combinado de los archivos de fuentes, esa única petición podría ser lenta, bloqueando la representación de todo contenido de una página. Así que el subconjunto y la división de la fuente en conjuntos de caracteres siguen siendo importantes. En el lado bueno, sin embargo, con una fuente variable en su lugar, vamos a obtener exactamente un reflujo por defecto, por lo que no se requiere JavaScript para agrupar repintados.

Ahora, lo que haría un estrategia de carga de fuentes web a prueba de balas ¿entonces? Subconjuntar las fuentes y prepararlas para el renderizado en 2 etapas, declararlas con un font-display descriptor, utilizar la API de carga de fuentes para agrupar los repintados y almacenar las fuentes en la caché de un trabajador de servicio persistente. En la primera visita, inyecte la precarga de scripts justo antes de los scripts externos de bloqueo. Puedes recurrir a la técnica de Bram Stein Observador de caras de fuentes si es necesario. Y si está interesado en medir el rendimiento de la carga de fuentes, Andreas Marschke explora el seguimiento del rendimiento con Font API y UserTiming API.

Por último, no olvide incluir unicode-range para dividir una fuente grande en fuentes más pequeñas específicas para el idioma, y utilizar la herramienta de Monica Dinculescu font-style-matcher para minimizar un cambio brusco en el diseño, debido a las discrepancias de tamaño entre las fuentes de reserva y las fuentes web.

Alternativamente, para emular una fuente web para una fuente de reserva, podemos usar descriptores @font-face para anular las métricas de las fuentes (demohabilitado en Chrome 87). (Sin embargo, tenga en cuenta que los ajustes son complicados con pilas de fuentes complicadas).

¿El futuro es prometedor? Con enriquecimiento progresivo de fuentesEn el futuro, podremos “descargar sólo la parte necesaria de la fuente en una página determinada y, en las siguientes solicitudes de esa fuente, “parchear” dinámicamente la descarga original con conjuntos adicionales de glifos según sea necesario en las sucesivas visitas a la página”, como explica Jason Pamental. Demostración de la transferencia incremental ya está disponible, y es trabajo en curso.

Publicaciones relacionadas

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Botón volver arriba
Cerrar
Cerrar