Rendimiento front-end 2021: definición del entorno

Publicado: 2022-03-10
Resumen rápido ↬ ¡Hagamos el 2021... rápido! Una lista de verificación anual de rendimiento de front-end con todo lo que necesita saber para crear experiencias rápidas en la web hoy, desde métricas hasta herramientas y técnicas de front-end. Actualizado desde 2016.

Tabla de contenido

  1. Preparándose: planificación y métricas
  2. Establecer metas realistas
  3. Definición del entorno
  4. Optimizaciones de activos
  5. Optimizaciones de compilación
  6. Optimizaciones de entrega
  7. Redes, HTTP/2, HTTP/3
  8. Pruebas y monitoreo
  9. Triunfos rápidos
  10. Todo en una página
  11. Descargar la lista de verificación (PDF, Apple Pages, MS Word)
  12. Suscríbase a nuestro boletín de correo electrónico para no perderse las próximas guías.

Definición del entorno

  1. Elija y configure sus herramientas de compilación.
    No prestes demasiada atención a lo que supuestamente está de moda en estos días. Cíñete a tu entorno para construir, ya sea Grunt, Gulp, Webpack, Parcel o una combinación de herramientas. Mientras obtenga los resultados que necesita y no tenga problemas para mantener su proceso de compilación, lo estará haciendo bien.

    Entre las herramientas de compilación, Rollup sigue ganando terreno, al igual que Snowpack, pero Webpack parece ser la más establecida, con literalmente cientos de complementos disponibles para optimizar el tamaño de sus compilaciones. Esté atento a la hoja de ruta de Webpack 2021.

    Una de las estrategias más notables que apareció recientemente es la fragmentación granular con Webpack en Next.js y Gatsby para minimizar el código duplicado. Por defecto, los módulos que no se comparten en todos los puntos de entrada se pueden solicitar para las rutas que no lo utilizan. Esto termina convirtiéndose en una sobrecarga ya que se descarga más código del necesario. Con la fragmentación granular en Next.js, podemos usar un archivo de manifiesto de compilación del lado del servidor para determinar qué fragmentos de salida utilizan los diferentes puntos de entrada.

    Para reducir el código duplicado en los proyectos de Webpack, podemos usar la fragmentación granular, habilitada en Next.js y Gatsby de forma predeterminada.
    Para reducir el código duplicado en los proyectos de Webpack, podemos usar la fragmentación granular, habilitada en Next.js y Gatsby de manera predeterminada. Crédito de la imagen: Addy Osmani. (Vista previa grande)

    Con SplitChunksPlugin, se crean varios fragmentos divididos en función de una serie de condiciones para evitar obtener código duplicado en varias rutas. Esto mejora el tiempo de carga de la página y el almacenamiento en caché durante las navegaciones. Enviado en Next.js 9.2 y en Gatsby v2.20.7.

    Sin embargo, comenzar con Webpack puede ser difícil. Entonces, si desea sumergirse en Webpack, existen algunos recursos excelentes:

    • La documentación de Webpack, obviamente, es un buen punto de partida, al igual que Webpack: The Confusing Bits de Raja Rao y An Annotated Webpack Config de Andrew Welch.
    • Sean Larkin tiene un curso gratuito sobre Webpack: The Core Concepts y Jeffrey Way ha lanzado un fantástico curso gratuito sobre Webpack para todos. Ambos son excelentes introducciones para sumergirse en Webpack.
    • Webpack Fundamentals es un curso muy completo de 4 horas con Sean Larkin, publicado por FrontendMasters.
    • Los ejemplos de Webpack tienen cientos de configuraciones de Webpack listas para usar, clasificadas por tema y propósito. Bonificación: también hay un configurador de configuración de Webpack que genera un archivo de configuración básico.
    • awesome-webpack es una lista seleccionada de útiles recursos, bibliotecas y herramientas de Webpack, incluidos artículos, videos, cursos, libros y ejemplos para proyectos Angular, React y sin marco.
    • El viaje hacia compilaciones de activos de producción rápida con Webpack es el estudio de caso de Etsy sobre cómo el equipo pasó de usar un sistema de compilación de JavaScript basado en RequireJS a usar Webpack y cómo optimizaron sus compilaciones, administrando más de 13 200 activos en 4 minutos en promedio.
    • Los consejos de rendimiento de Webpack son una mina de oro de Ivan Akulov, que presenta muchos consejos centrados en el rendimiento, incluidos los que se centran específicamente en Webpack.
    • impresionante-webpack-perf es un repositorio de GitHub de mina de oro con útiles herramientas y complementos de Webpack para el rendimiento. También mantenido por Ivan Akulov.
Una visualización del viaje de Etsy hacia compilaciones de producción rápida con Webpack
El viaje de Etsy hacia compilaciones de producción rápida con Webpack (a través de Addy Osmani) (vista previa grande)
  1. Utilice la mejora progresiva como opción predeterminada.
    Aun así, después de todos estos años, mantener la mejora progresiva como el principio rector de la implementación y la arquitectura de front-end es una apuesta segura. Primero diseñe y cree la experiencia central y luego mejore la experiencia con funciones avanzadas para navegadores compatibles, creando experiencias resilientes. Si su sitio web se ejecuta rápido en una máquina lenta con una pantalla deficiente en un navegador deficiente en una red subóptima, solo se ejecutará más rápido en una máquina rápida con un buen navegador en una red decente.

    De hecho, con el servicio de módulos adaptativos, parece que estamos llevando la mejora progresiva a otro nivel, brindando experiencias básicas "ligeras" a dispositivos de gama baja y mejorando con funciones más sofisticadas para dispositivos de gama alta. No es probable que la mejora progresiva desaparezca pronto.

  2. Elija una base de referencia de rendimiento sólida.
    Con tantas incógnitas que afectan la carga: la red, el estrangulamiento térmico, el desalojo de caché, scripts de terceros, patrones de bloqueo del analizador, E/S de disco, latencia de IPC, extensiones instaladas, software antivirus y firewalls, tareas de CPU en segundo plano, restricciones de hardware y memoria, diferencias en el almacenamiento en caché L2/L3, RTTS: JavaScript tiene el costo más alto de la experiencia, junto con las fuentes web que bloquean el procesamiento de forma predeterminada y las imágenes que a menudo consumen demasiada memoria. Con los cuellos de botella de rendimiento alejándose del servidor al cliente, como desarrolladores, tenemos que considerar todas estas incógnitas con mucho más detalle.

    Con un presupuesto de 170 KB que ya contiene la ruta crítica HTML/CSS/JavaScript, el enrutador, la administración de estado, las utilidades, el marco y la lógica de la aplicación, tenemos que examinar minuciosamente el costo de transferencia de la red, el tiempo de análisis/compilación y el costo del tiempo de ejecución. del marco de nuestra elección. Afortunadamente, hemos visto una gran mejora en los últimos años en la rapidez con la que los navegadores pueden analizar y compilar scripts. Sin embargo, la ejecución de JavaScript sigue siendo el principal cuello de botella, por lo que prestar mucha atención al tiempo de ejecución del script y la red puede tener un impacto.

    Tim Kadlec realizó una investigación fantástica sobre el rendimiento de los marcos modernos y los resumió en el artículo "Los marcos de JavaScript tienen un costo". A menudo hablamos sobre el impacto de los marcos independientes, pero como señala Tim, en la práctica, no es raro tener múltiples marcos en uso . Tal vez una versión anterior de jQuery que se está migrando lentamente a un marco moderno, junto con algunas aplicaciones heredadas que usan una versión anterior de Angular. Por lo tanto, es más razonable explorar el costo acumulativo de los bytes de JavaScript y el tiempo de ejecución de la CPU que pueden hacer que las experiencias de los usuarios sean apenas utilizables, incluso en dispositivos de gama alta.

    En general, los marcos modernos no dan prioridad a los dispositivos menos potentes , por lo que las experiencias en un teléfono y en una computadora de escritorio a menudo serán dramáticamente diferentes en términos de rendimiento. Según la investigación, los sitios con React o Angular pasan más tiempo en la CPU que otros (lo que, por supuesto, no significa necesariamente que React sea más costoso en la CPU que Vue.js).

    Según Tim, una cosa es obvia: "si está utilizando un marco para construir su sitio, está haciendo una compensación en términos de rendimiento inicial , incluso en el mejor de los escenarios".

El costo de los marcos, el tiempo de CPU de JavaScript: los sitios SPA funcionan mal
El costo de los marcos, byes de JavaScript: los sitios SPA (todavía) funcionan mal
Tiempo de CPU relacionado con secuencias de comandos para dispositivos móviles y bytes de JavaScript para dispositivos de escritorio. En general, los sitios con React o Angular pasan más tiempo en la CPU que otros. Pero depende de cómo construyas el sitio. Investigación de Tim Kadlec. (Vista previa grande)
  1. Evaluar marcos y dependencias.
    Ahora, no todos los proyectos necesitan un marco y no todas las páginas de una aplicación de una sola página necesitan cargar un marco. En el caso de Netflix, "al eliminar React, varias bibliotecas y el código de la aplicación correspondiente del lado del cliente se redujo la cantidad total de JavaScript en más de 200 KB, lo que provocó una reducción de más del 50 % en el tiempo de interactividad de Netflix para la página de inicio sin sesión. ." Luego, el equipo utilizó el tiempo que los usuarios pasaban en la página de destino para precargar React para las páginas posteriores a las que los usuarios probablemente llegarían (siga leyendo para obtener más detalles).

    Entonces, ¿qué pasa si elimina por completo un marco existente en páginas críticas? Con Gatsby, puede verificar gatsby-plugin-no-javascript que elimina todos los archivos JavaScript creados por Gatsby de los archivos HTML estáticos. En Vercel, también puede permitir la desactivación de JavaScript en tiempo de ejecución en producción para ciertas páginas (experimental).

    Una vez que se elige un marco, nos quedaremos con él durante al menos unos años, por lo que si necesitamos usar uno, debemos asegurarnos de que nuestra elección esté informada y bien considerada, y eso se aplica especialmente a las métricas de rendimiento clave que necesitamos. preocuparse.

    Los datos muestran que, de forma predeterminada, los marcos son bastante caros: el 58,6 % de las páginas de React envían más de 1 MB de JavaScript, y el 36 % de las cargas de páginas de Vue.js tienen una primera pintura con contenido de <1,5 s. Según un estudio de Ankur Sethi, "su aplicación React nunca se cargará más rápido que aproximadamente 1,1 segundos en un teléfono promedio en la India, sin importar cuánto la optimice. Su aplicación Angular siempre tardará al menos 2,7 segundos en iniciarse. los usuarios de su aplicación Vue deberán esperar al menos 1 segundo antes de poder comenzar a usarla". Es posible que no tenga como objetivo la India como su mercado principal de todos modos, pero los usuarios que accedan a su sitio con condiciones de red subóptimas tendrán una experiencia comparable.

    Por supuesto, es posible hacer que los SPA sean rápidos, pero no son rápidos desde el primer momento, por lo que debemos tener en cuenta el tiempo y el esfuerzo necesarios para hacerlos y mantenerlos rápidos. Probablemente será más fácil elegir un costo de rendimiento de referencia ligero desde el principio.

    Entonces, ¿cómo elegimos un marco ? Es una buena idea considerar al menos el costo total del tamaño + los tiempos iniciales de ejecución antes de elegir una opción; las opciones ligeras como Preact, Inferno, Vue, Svelte, Alpine o Polymer pueden hacer el trabajo perfectamente. El tamaño de su línea base definirá las restricciones para el código de su aplicación.

    Como señaló Seb Markbage, una buena manera de medir los costos iniciales de los marcos es primero renderizar una vista, luego eliminarla y luego volver a renderizar, ya que puede indicarle cómo se escala el marco. El primer renderizado tiende a calentar un montón de código compilado perezosamente, del cual un árbol más grande puede beneficiarse cuando escala. El segundo renderizado es básicamente una emulación de cómo la reutilización del código en una página afecta las características de rendimiento a medida que la página crece en complejidad.

    Puede ir tan lejos como para evaluar a sus candidatos (o cualquier biblioteca de JavaScript en general) en el sistema de puntuación de escala de 12 puntos de Sacha Greif explorando características, accesibilidad, estabilidad, rendimiento, ecosistema de paquetes , comunidad, curva de aprendizaje, documentación, herramientas, historial , equipo, compatibilidad, seguridad por ejemplo.

    Perf Track rastrea el rendimiento del marco a escala
    Perf Track realiza un seguimiento del rendimiento del marco a escala. (Vista previa grande)

    También puede confiar en los datos recopilados en la web durante un período de tiempo más largo. Por ejemplo, Perf Track realiza un seguimiento del rendimiento del marco a escala, mostrando puntuaciones de Core Web Vitals agregadas por origen para sitios web creados en Angular, React, Vue, Polymer, Preact, Ember, Svelte y AMP. Incluso puede especificar y comparar sitios web creados con Gatsby, Next.js o Create React App, así como sitios web creados con Nuxt.js (Vue) o Sapper (Svelte).

    Un buen punto de partida es elegir una buena pila predeterminada para su aplicación. Gatsby (React), Next.js (React), Vuepress (Vue), Preact CLI y PWA Starter Kit proporcionan valores predeterminados razonables para una carga rápida lista para usar en hardware móvil promedio. Además, eche un vistazo a la guía de rendimiento específica del marco web.dev para React y Angular ( ¡gracias, Phillip! ).

    Y tal vez podría adoptar un enfoque un poco más refrescante para crear aplicaciones de una sola página: Turbolinks, una biblioteca de JavaScript de 15 KB que usa HTML en lugar de JSON para representar las vistas. Entonces, cuando sigue un enlace, Turbolinks busca automáticamente la página, intercambia su <body> y fusiona su <head> , todo sin incurrir en el costo de una carga completa de la página. Puede consultar detalles rápidos y documentación completa sobre la pila (Hotwire).

Un gráfico similar a un histograma que muestra el rendimiento informático de los teléfonos más vendidos
CPU y rendimiento informático de los teléfonos más vendidos (Crédito de la imagen: Addy Osmani) (Vista previa grande)
  1. ¿Representación del lado del cliente o representación del lado del servidor? ¡Ambas cosas!
    Esa es una conversación bastante acalorada. El enfoque final sería configurar algún tipo de arranque progresivo: use la representación del lado del servidor para obtener una primera pintura con contenido rápida, pero también incluya un mínimo de JavaScript necesario para mantener el tiempo de interacción cerca de la primera pintura con contenido. Si JavaScript llega demasiado tarde después del FCP, el navegador bloqueará el hilo principal mientras analiza, compila y ejecuta JavaScript descubierto tarde, por lo tanto, limita la interactividad del sitio o la aplicación.

    Para evitarlo, siempre divida la ejecución de funciones en tareas asíncronas separadas y, cuando sea posible, use requestIdleCallback . Considere la carga diferida de partes de la interfaz de usuario utilizando el soporte de import() de WebPack, evitando el costo de carga, análisis y compilación hasta que los usuarios realmente los necesiten ( ¡gracias Addy! ).

    Como se mencionó anteriormente, Time to Interactive (TTI) nos dice el tiempo entre la navegación y la interactividad. En detalle, la métrica se define mirando la primera ventana de cinco segundos después de que se representa el contenido inicial, en la que ninguna tarea de JavaScript tarda más de 50 ms ( Tareas largas ). Si se produce una tarea de más de 50 ms, la búsqueda de una ventana de cinco segundos comienza de nuevo. Como resultado, el navegador primero asumirá que llegó a Interactive , solo para cambiar a Frozen , solo para eventualmente volver a cambiar a Interactive .

    Una vez que llegamos a Interactivo , podemos, ya sea a pedido o según lo permita el tiempo, iniciar partes no esenciales de la aplicación. Desafortunadamente, como notó Paul Lewis, los marcos generalmente no tienen un concepto simple de prioridad que se pueda mostrar a los desarrolladores y, por lo tanto, el arranque progresivo no es fácil de implementar con la mayoría de las bibliotecas y marcos.

    Aún así, estamos llegando allí. En estos días hay un par de opciones que podemos explorar, y Houssein Djirdeh y Jason Miller brindan una excelente descripción general de estas opciones en su charla sobre Rendering on the Web y el artículo de Jason y Addy sobre Modern Front-End Architectures. La descripción general a continuación se basa en su trabajo estelar.

    • Representación completa del lado del servidor (SSR)
      En SSR clásico, como WordPress, todas las solicitudes se manejan completamente en el servidor. El contenido solicitado se devuelve como una página HTML terminada y los navegadores pueden procesarlo de inmediato. Por lo tanto, las aplicaciones SSR no pueden realmente hacer uso de las API DOM, por ejemplo. La brecha entre First Contentful Paint y Time to Interactive suele ser pequeña, y la página se puede representar de inmediato a medida que HTML se transmite al navegador.

      Esto evita viajes de ida y vuelta adicionales para obtener datos y crear plantillas en el cliente, ya que se maneja antes de que el navegador obtenga una respuesta. Sin embargo, terminamos con un tiempo de reflexión del servidor más largo y, en consecuencia, Tiempo hasta el primer byte y no hacemos uso de las características ricas y receptivas de las aplicaciones modernas.

    • Representación estática
      Creamos el producto como una aplicación de una sola página, pero todas las páginas se procesan previamente en HTML estático con JavaScript mínimo como paso de creación. Eso significa que con el renderizado estático, producimos archivos HTML individuales para cada URL posible con anticipación, algo que no muchas aplicaciones pueden permitirse. Pero debido a que el código HTML de una página no tiene que generarse sobre la marcha, podemos lograr un tiempo hasta el primer byte consistentemente rápido. Por lo tanto, podemos mostrar una página de destino rápidamente y luego precargar un marco SPA para las páginas posteriores. Netflix ha adoptado este enfoque para reducir la carga y el tiempo de interacción en un 50 %.

    • Renderización del lado del servidor con (re)hidratación (representación universal, SSR + CSR)
      Podemos tratar de usar lo mejor de ambos mundos: los enfoques SSR y CSR. Con la hidratación en la mezcla, la página HTML devuelta por el servidor también contiene un script que carga una aplicación completa del lado del cliente. Idealmente, eso logra una primera pintura con contenido rápida (como SSR) y luego continúa renderizando con (re) hidratación. Desafortunadamente, ese es raramente el caso. Más a menudo, la página parece lista pero no puede responder a la entrada del usuario, lo que produce clics de rabia y abandonos.

      Con React, podemos usar el módulo ReactDOMServer en un servidor Node como Express y luego llamar al método renderToString para representar los componentes de nivel superior como una cadena HTML estática.

      Con Vue.js, podemos usar vue-server-renderer para representar una instancia de Vue en HTML usando renderToString . En Angular, podemos usar @nguniversal para convertir las solicitudes de los clientes en páginas HTML totalmente procesadas por el servidor. También se puede lograr una experiencia completamente renderizada en el servidor desde el primer momento con Next.js (React) o Nuxt.js (Vue).

      El enfoque tiene sus desventajas. Como resultado, obtenemos una flexibilidad total de las aplicaciones del lado del cliente al mismo tiempo que brindamos una representación más rápida del lado del servidor, pero también terminamos con una brecha más larga entre la primera pintura con contenido y el tiempo para la interacción y un mayor retraso de la primera entrada. La rehidratación es muy costosa y, por lo general, esta estrategia por sí sola no será lo suficientemente buena, ya que retrasa mucho el tiempo de interacción.

    • Streaming del lado del servidor con hidratación progresiva (SSR + CSR)
      Para minimizar la brecha entre Time To Interactive y First Contentful Paint, procesamos varias solicitudes a la vez y enviamos contenido en fragmentos a medida que se generan. Por lo tanto, no tenemos que esperar la cadena completa de HTML antes de enviar contenido al navegador y, por lo tanto, mejorar el tiempo hasta el primer byte.

      En React, en lugar de renderToString() , podemos usar renderToNodeStream() para canalizar la respuesta y enviar el HTML en fragmentos. En Vue, podemos usar renderToStream() que se puede canalizar y transmitir. Con React Suspense, también podríamos usar el renderizado asíncrono para ese propósito.

      En el lado del cliente, en lugar de iniciar toda la aplicación a la vez, iniciamos los componentes progresivamente . Las secciones de las aplicaciones se dividen primero en secuencias de comandos independientes con división de código y luego se hidratan gradualmente (en orden de nuestras prioridades). De hecho, podemos hidratar los componentes críticos primero, mientras que el resto podría hidratarse más tarde. La función de representación del lado del cliente y del lado del servidor se puede definir de manera diferente por componente. Luego, también podemos diferir la hidratación de algunos componentes hasta que estén a la vista, o sean necesarios para la interacción del usuario, o cuando el navegador esté inactivo.

      Para Vue, Markus Oberlehner ha publicado una guía sobre cómo reducir el tiempo de interacción de las aplicaciones SSR utilizando la hidratación en la interacción del usuario, así como vue-lazy-hydration, un complemento de etapa inicial que permite la hidratación de los componentes en la visibilidad o la interacción específica del usuario. El equipo de Angular trabaja en la hidratación progresiva con Ivy Universal. También puede implementar la hidratación parcial con Preact y Next.js.

    • Representación trisomórfica
      Con los trabajadores del servicio en su lugar, podemos usar la representación del servidor de transmisión para navegaciones iniciales/no JS, y luego hacer que el trabajador del servicio asuma la representación de HTML para las navegaciones después de que se haya instalado. En ese caso, el trabajador del servicio renderiza previamente el contenido y habilita las navegaciones de estilo SPA para renderizar nuevas vistas en la misma sesión. Funciona bien cuando puede compartir la misma plantilla y código de enrutamiento entre el servidor, la página del cliente y el trabajador del servicio.

    Una ilustración que muestra cómo funciona la representación trisomórfica en 3 lugares, como la representación DOM, la representación previa del trabajador de servicios y la representación del lado del servidor
    Representación trisomórfica, con la misma representación de código en 3 lugares cualquiera: en el servidor, en el DOM o en un trabajador de servicio. (Fuente de la imagen: Google Developers) (Vista previa grande)
    • CSR con representación previa
      La renderización previa es similar a la renderización del lado del servidor, pero en lugar de renderizar páginas en el servidor dinámicamente, renderizamos la aplicación en HTML estático en el momento de la compilación. Si bien las páginas estáticas son completamente interactivas sin mucho JavaScript del lado del cliente, la representación previa funciona de manera diferente . Básicamente, captura el estado inicial de una aplicación del lado del cliente como HTML estático en el momento de la compilación, mientras que con la representación previa, la aplicación debe iniciarse en el cliente para que las páginas sean interactivas.

      Con Next.js, podemos usar la exportación de HTML estático prerenderizando una aplicación en HTML estático. En Gatsby, un generador de sitios estáticos de código abierto que usa React, usa el método renderToStaticMarkup en lugar del método renderToString durante las compilaciones, con el fragmento JS principal precargado y las rutas futuras precargadas, sin atributos DOM que no son necesarios para páginas estáticas simples.

      Para Vue, podemos usar Vuepress para lograr el mismo objetivo. También puede usar prerender-loader con Webpack. Navi también proporciona renderizado estático.

      El resultado es un mejor tiempo para el primer byte y la primera pintura con contenido, y reducimos la brecha entre el tiempo para la interacción y la primera pintura con contenido. No podemos usar el enfoque si se espera que el contenido cambie mucho. Además, todas las URL deben conocerse con anticipación para generar todas las páginas. Por lo tanto, algunos componentes pueden renderizarse mediante renderizado previo, pero si necesitamos algo dinámico, tenemos que confiar en la aplicación para obtener el contenido.

    • Representación completa del lado del cliente (CSR)
      Toda la lógica, el renderizado y el arranque se realizan en el cliente. El resultado suele ser una gran brecha entre Time To Interactive y First Contentful Paint. Como resultado, las aplicaciones a menudo se sienten lentas , ya que toda la aplicación debe iniciarse en el cliente para generar cualquier cosa.

      Como JavaScript tiene un costo de rendimiento, a medida que la cantidad de JavaScript crece con una aplicación, la división de código agresiva y el aplazamiento de JavaScript serán absolutamente necesarios para controlar el impacto de JavaScript. Para tales casos, una representación del lado del servidor generalmente será un mejor enfoque en caso de que no se requiera mucha interactividad. Si no es una opción, considere usar The App Shell Model.

      En general, SSR es más rápido que CSR. Sin embargo, es una implementación bastante frecuente para muchas aplicaciones.

    Entonces, ¿del lado del cliente o del lado del servidor? En general, es una buena idea limitar el uso de marcos completamente del lado del cliente a páginas que los requieran absolutamente. Para aplicaciones avanzadas, tampoco es una buena idea confiar solo en el renderizado del lado del servidor. Tanto la representación del servidor como la representación del cliente son un desastre si se hacen mal.

    Ya sea que se incline por CSR o SSR, asegúrese de renderizar los píxeles importantes lo antes posible y minimice la brecha entre ese renderizado y el tiempo de interacción. Considere la posibilidad de renderizar previamente si sus páginas no cambian mucho, y posponga el inicio de los marcos si puede. Transmita HTML en fragmentos con renderizado del lado del servidor e implemente una hidratación progresiva para el renderizado del lado del cliente, e hidrátese en la visibilidad, la interacción o durante el tiempo de inactividad para obtener lo mejor de ambos mundos.

Una tabla que compara las opciones de renderizado del lado del cliente frente al del lado del servidor
El espectro de opciones para la representación del lado del cliente frente al lado del servidor. Además, consulte la charla de Jason y Houssein en Google I/O sobre las implicaciones de rendimiento de la arquitectura de aplicaciones. (Fuente de la imagen: Jason Miller) (Vista previa grande)
Un ejemplo del sitio web de AirBnB que se muestra sin hidratación progresiva a la izquierda y con hidratación progresiva a la derecha
AirBnB ha estado experimentando con la hidratación progresiva; difieren los componentes innecesarios, se cargan en la interacción del usuario (desplazamiento) o durante el tiempo de inactividad y las pruebas muestran que puede mejorar el TTI. (Vista previa grande)
  1. ¿Cuánto podemos servir de forma estática?
    Ya sea que esté trabajando en una aplicación grande o en un sitio pequeño, vale la pena considerar qué contenido podría servirse estáticamente desde un CDN (es decir, JAM Stack), en lugar de generarse dinámicamente sobre la marcha. Incluso si tiene miles de productos y cientos de filtros con muchas opciones de personalización, es posible que desee publicar sus páginas de destino críticas de forma estática y desvincular estas páginas del marco de su elección.

    Hay muchos generadores de sitios estáticos y las páginas que generan suelen ser muy rápidas. Cuanto más contenido podamos preconstruir con anticipación en lugar de generar vistas de página en un servidor o cliente en el momento de la solicitud, mejor rendimiento lograremos.

    En Creación de sitios web estáticos parcialmente hidratados y mejorados progresivamente, Markus Oberlehner muestra cómo crear sitios web con un generador de sitios estáticos y un SPA, mientras se logra una mejora progresiva y un tamaño mínimo de paquete de JavaScript. Markus usa Eleventy y Preact como sus herramientas y muestra cómo configurar las herramientas, agregar hidratación parcial, hidratación perezosa, archivo de entrada del cliente, configurar Babel para Preact y agrupar Preact con Rollup, de principio a fin.

    Con el uso de JAMStack en sitios grandes en estos días, apareció una nueva consideración de rendimiento: el tiempo de compilación . De hecho, crear incluso miles de páginas con cada nueva implementación puede llevar minutos, por lo que promete ver compilaciones incrementales en Gatsby que mejoran los tiempos de compilación en 60 veces , con una integración en soluciones de CMS populares como WordPress, Contentful, Drupal, Netlify CMS. y otros.

    Un diagrama de flujo que muestra al Usuario 1 en la parte superior izquierda y al Usuario 2 en la parte inferior izquierda que muestra el proceso de regeneración de estado incremental
    Regeneración estática incremental con Next.js. (Crédito de la imagen: Prisma.io) (Vista previa grande)

    Además, Next.js anunció la generación estática incremental y anticipada, lo que nos permite agregar nuevas páginas estáticas en tiempo de ejecución y actualizar las páginas existentes después de que ya se hayan creado, volviéndolas a renderizar en segundo plano a medida que ingresa el tráfico. .

    ¿Necesita un enfoque aún más ligero? En su charla sobre Eleventy, Alpine y Tailwind: Hacia un Jamstack liviano, Nicola Goutay explica las diferencias entre CSR, SSR y todo lo demás, y muestra cómo usar un enfoque más liviano, junto con un repositorio de GitHub que muestra el enfoque. en la práctica.

  2. Considere usar el patrón PRPL y la arquitectura de shell de la aplicación.
    Diferentes marcos tendrán diferentes efectos en el rendimiento y requerirán diferentes estrategias de optimización, por lo que debe comprender claramente todos los aspectos básicos del marco en el que confiará. Al crear una aplicación web, observe el patrón PRPL y la arquitectura de shell de la aplicación. La idea es bastante sencilla: presione el código mínimo necesario para que la ruta inicial se vuelva interactiva y se procese rápidamente, luego use el trabajador de servicio para almacenar en caché y almacenar previamente en caché los recursos y luego cargue las rutas que necesita, de forma asíncrona.
Patrón PRPL en la arquitectura shell de la aplicación
PRPL significa Empujar recurso crítico, Representar ruta inicial, Pre-caching rutas restantes y Lazy-loading rutas restantes a pedido.
Arquitectura de shell de aplicación
Un shell de aplicación es el HTML, CSS y JavaScript mínimos que alimentan una interfaz de usuario.
  1. ¿Ha optimizado el rendimiento de sus API?
    Las API son canales de comunicación para que una aplicación exponga datos a aplicaciones internas y de terceros a través de puntos finales . Al diseñar y construir una API, necesitamos un protocolo razonable para permitir la comunicación entre el servidor y las solicitudes de terceros. La transferencia de estado representacional ( REST ) ​​es una opción lógica y bien establecida: define un conjunto de restricciones que los desarrolladores siguen para hacer que el contenido sea accesible de manera eficiente, confiable y escalable. Los servicios web que se ajustan a las restricciones REST se denominan servicios web RESTful .

    Al igual que con las buenas solicitudes HTTP, cuando los datos se recuperan de una API, cualquier retraso en la respuesta del servidor se propagará al usuario final, lo que retrasará la representación . Cuando un recurso quiere recuperar algunos datos de una API, deberá solicitar los datos del punto final correspondiente. Un componente que representa datos de varios recursos, como un artículo con comentarios y fotos del autor en cada comentario, puede necesitar varios viajes de ida y vuelta al servidor para obtener todos los datos antes de poder procesarlos. Además, la cantidad de datos devueltos a través de REST suele ser mayor de lo que se necesita para representar ese componente.

    Si muchos recursos requieren datos de una API, la API podría convertirse en un cuello de botella de rendimiento. GraphQL proporciona una solución eficaz para estos problemas. En sí, GraphQL es un lenguaje de consulta para su API y un tiempo de ejecución del lado del servidor para ejecutar consultas mediante el uso de un sistema de tipos que defina para sus datos. A diferencia de REST, GraphQL puede recuperar todos los datos en una sola solicitud , y la respuesta será exactamente lo que se requiere, sin obtener más o menos datos como suele suceder con REST.

    Además, debido a que GraphQL usa un esquema (metadatos que indican cómo se estructuran los datos), ya puede organizar los datos en la estructura preferida, por lo que, por ejemplo, con GraphQL, podríamos eliminar el código JavaScript que se usa para manejar la administración del estado, produciendo un código de aplicación más limpio que se ejecuta más rápido en el cliente.

    Si desea comenzar con GraphQL o tiene problemas de rendimiento, estos artículos pueden ser muy útiles:

    • Introducción a GraphQL: Por qué necesitamos un nuevo tipo de API por Eric Baer,
    • Introducción a GraphQL: la evolución del diseño de API por Eric Baer,
    • Diseño de un servidor GraphQL para un rendimiento óptimo por Leonardo Losoviz,
    • Rendimiento de GraphQL explicado por Wojciech Trocki.
Dos ejemplos de interfaces móviles para mensajes al usar Redux/REST (izquierda) y Apollo/GraphQL (derecha)
Una diferencia entre REST y GraphQL, ilustrada a través de una conversación entre Redux + REST a la izquierda, un Apollo + GraphQL a la derecha. (Fuente de la imagen: Hacker Noon) (Vista previa grande)
  1. ¿Usarás AMP o artículos instantáneos?
    Según las prioridades y la estrategia de su organización, es posible que desee considerar el uso de AMP de Google, Instant Articles de Facebook o Apple News de Apple. Puede lograr un buen rendimiento sin ellos, pero AMP proporciona un marco de rendimiento sólido con una red de entrega de contenido (CDN) gratuita , mientras que los artículos instantáneos aumentarán su visibilidad y rendimiento en Facebook.

    El beneficio aparentemente obvio de estas tecnologías para los usuarios es el rendimiento garantizado , por lo que a veces incluso pueden preferir enlaces AMP-/Apple News/Instant Pages-en lugar de páginas "normales" y potencialmente infladas. Para los sitios web con mucho contenido que manejan una gran cantidad de contenido de terceros, estas opciones podrían ayudar a acelerar drásticamente los tiempos de procesamiento.

    A menos que no lo hagan. Según Tim Kadlec, por ejemplo, "los documentos AMP tienden a ser más rápidos que sus contrapartes, pero eso no significa necesariamente que una página tenga un buen rendimiento. AMP no es lo que marca la mayor diferencia desde la perspectiva del rendimiento".

    Un beneficio para el propietario del sitio web es obvio: la visibilidad de estos formatos en sus respectivas plataformas y una mayor visibilidad en los motores de búsqueda.

    Bueno, al menos así solía ser. Como AMP ya no es un requisito para Top Stories , los editores podrían estar pasando de AMP a una pila tradicional ( ¡gracias, Barry! ).

    Aún así, también podría crear AMP web progresivos reutilizando AMP como fuente de datos para su PWA. ¿Abajo? Obviamente, una presencia en un jardín amurallado coloca a los desarrolladores en posición de producir y mantener una versión separada de su contenido, y en el caso de Instant Articles y Apple News sin URL reales (¡gracias Addy, Jeremy!) .

  2. Elija sabiamente su CDN.
    Como se mencionó anteriormente, dependiendo de la cantidad de datos dinámicos que tenga, es posible que pueda "subcontratar" una parte del contenido a un generador de sitios estáticos, empujándolo a un CDN y sirviendo una versión estática desde él, evitando así solicitudes al servidor. De hecho, algunos de esos generadores son en realidad compiladores de sitios web con muchas optimizaciones automáticas provistas de fábrica. A medida que los compiladores agregan optimizaciones con el tiempo, la salida compilada se vuelve más pequeña y más rápida con el tiempo.

    Tenga en cuenta que las CDN también pueden servir (y descargar) contenido dinámico. Por lo tanto, no es necesario restringir su CDN a activos estáticos. Vuelva a verificar si su CDN realiza compresión y conversión (p. ej., optimización de imágenes y cambio de tamaño en el borde), si brinda soporte para trabajadores de servidores, pruebas A/B, así como también incluye el lado del borde, que ensambla partes estáticas y dinámicas de las páginas. en el borde de la CDN (es decir, el servidor más cercano al usuario) y otras tareas. Además, verifique si su CDN es compatible con HTTP sobre QUIC (HTTP/3).

    Katie Hempenius ha escrito una guía fantástica sobre las CDN que brinda información sobre cómo elegir una buena CDN , cómo ajustarla y todos los pequeños detalles que se deben tener en cuenta al evaluar una. En general, es una buena idea almacenar en caché el contenido de la forma más agresiva posible y habilitar funciones de rendimiento de CDN como Brotli, TLS 1.3, HTTP/2 y HTTP/3.

    Nota : según la investigación de Patrick Meenan y Andy Davies, la priorización de HTTP/2 se rompe de manera efectiva en muchas CDN, así que tenga cuidado al elegir una CDN. Patrick tiene más detalles en su charla sobre Priorización de HTTP/2 ( ¡gracias, Barry! ).

    Vista previa de CDNPerf de nombres de CDN y velocidad de consulta en ms
    CDNPerf mide la velocidad de consulta de CDN recopilando y analizando 300 millones de pruebas todos los días. (Vista previa grande)

    Al elegir un CDN, puede utilizar estos sitios de comparación con una descripción detallada de sus características:

    • Comparación de CDN, una matriz de comparación de CDN para Cloudfront, Aazure, KeyCDN, Fastly, Verizon, Stackpach, Akamai y muchos otros.
    • CDN Perf mide la velocidad de consulta de CDN recopilando y analizando 300 millones de pruebas todos los días, con todos los resultados basados ​​en datos RUM de usuarios de todo el mundo. Consulte también la Comparación de rendimiento de DNS y la Comparación de rendimiento de la nube.
    • CDN Planet Guides proporciona una descripción general de las CDN para temas específicos, como Servicio obsoleto, Purga, Escudo de origen, Prefetch y Compresión.
    • Web Almanac: Adopción y uso de CDN brinda información sobre los principales proveedores de CDN, su administración de RTT y TLS, el tiempo de negociación de TLS, la adopción de HTTP/2 y otros. (Lamentablemente, los datos son solo de 2019).

Tabla de contenido

  1. Preparándose: planificación y métricas
  2. Establecer metas realistas
  3. Definición del entorno
  4. Optimizaciones de activos
  5. Optimizaciones de compilación
  6. Optimizaciones de entrega
  7. Redes, HTTP/2, HTTP/3
  8. Pruebas y monitoreo
  9. Triunfos rápidos
  10. Todo en una página
  11. Descargar la lista de verificación (PDF, Apple Pages, MS Word)
  12. Suscríbase a nuestro boletín de correo electrónico para no perderse las próximas guías.