Cumplimiento de los marcos de trabajo

Cumplimiento en el ecosistema del framework de JavaScript

En nuestra entrada de blog introductoria, explicamos cómo aprendimos mucho mientras compilamos y usamos frameworks y herramientas para desarrollar y mantener aplicaciones web a gran escala, como la Búsqueda de Google, Maps, Fotos, etcétera. Cuando se protege a los desarrolladores de escribir código que puede afectar de forma negativa la experiencia del usuario, comprobamos que los frameworks pueden desempeñar un papel clave en el cambio de los resultados por el rendimiento y la calidad de la aplicación.

De forma interna en Google, usamos el término "Cumplimiento" para describir esta metodología, y en este artículo, se explica cómo planeamos crear código abierto para este concepto en el ecosistema del framework de JavaScript.

¿Qué es el cumplimiento?

En Google, el cumplimiento fue una evolución. Los equipos dependían de un pequeño grupo de encargados de mantenimiento muy experimentados que realizaban revisiones exhaustivas del código y marcaban los aspectos que afectaban la calidad y la capacidad de mantenimiento de la app más allá de los problemas de corrección. Para escalar esto a equipos de desarrolladores de apps en crecimiento, se desarrolló un sistema de cumplimiento con el objetivo de codificar las prácticas recomendadas de forma automática y aplicable. Esto garantizaba un nivel alto y coherente de calidad de la app y capacidad de mantenimiento de la base de código, independientemente de la cantidad de colaboradores de código.

El cumplimiento es un sistema que garantiza que los desarrolladores permanezcan en el camino bien iluminado, genera confianza y garantiza resultados predecibles. Hace que los equipos sean productivos y se vuelve fundamental para el escalamiento, a medida que los equipos crecen y se desarrollan más atributos en simultáneo. Les permite a los desarrolladores enfocarse en compilar funciones de productos y liberarlos de detalles mínimos y los cambios en el panorama en diversas áreas, como el rendimiento, la accesibilidad, la seguridad, etc. Cualquier persona puede inhabilitar el cumplimiento en cualquier momento y debe ser personalizable en la medida en que los equipos tengan la opción de aplicar lo que decidan.

El cumplimiento se basa en valores predeterminados sólidos y proporciona reglas prácticas que se puedan aplicar en el momento de la creación. Esto se desglosa en los siguientes 3 principios.

1. Valores predeterminados seguros

Un aspecto fundamental del cumplimiento es garantizar que las herramientas que usan los desarrolladores tengan valores predeterminados sólidos. Esto significa que las soluciones no solo se integran en los frameworks, sino que también los patrones de diseño del framework facilitan el trabajo correcto y dificultan el seguimiento de antipatrones. El framework asiste a los desarrolladores con el diseño de la aplicación y la estructura del código.

Para obtener un buen rendimiento de carga, se deben optimizar todos los recursos (fuentes, CSS, JavaScript, imágenes, etc.). Este es un desafío complejo que implica el recorte de bytes, la reducción de las idas y vueltas y la separación de lo que se necesita para la primera renderización, la preparación visual y la interacción del usuario. Por ejemplo, mediante la extracción de CSS críticas y la configuración de prioridad de las imágenes importantes.

2. Reglas accionables

Incluso con las optimizaciones básicas implementadas, los desarrolladores deben tomar decisiones. Existe un espectro de posibilidades de optimizaciones en lo que respecta a la cantidad de aportes de los desarrolladores que se necesitan:

  • Valores predeterminados que no requieren entradas del desarrollador, como intercalar CSS crítico.
  • Requerir la aceptación del desarrollador Por ejemplo, puedes usar un componente de imagen proporcionado por el framework para ajustar el tamaño y la escala de las imágenes.
  • Requerir la aceptación y personalización del desarrollador Por ejemplo, etiquetar imágenes importantes para que se carguen antes.
  • No se trata de una función específica, sino de aspectos que aún requieren una decisión del desarrollador. Por ejemplo, evita las fuentes o las secuencias de comandos síncronas que retrasan la renderización temprana.

Diagrama en el que se muestra un espectro entre las optimizaciones automáticas y manuales para desarrolladores

Las optimizaciones que requieren cualquier decisión de los desarrolladores representan un riesgo para el rendimiento de la aplicación. A medida que se agregan funciones y se escala tu equipo, incluso los desarrolladores más experimentados no pueden seguir el ritmo de las prácticas recomendadas que cambian constantemente, ni tampoco es el mejor uso de su tiempo. Para el cumplimiento, las reglas accionables adecuadas son tan importantes como los valores predeterminados sólidos a fin de garantizar que la aplicación continúe cumpliendo con un cierto estándar incluso cuando los desarrolladores continúan realizando cambios.

3. Tiempo de creación

Es importante detectar y excluir problemas de rendimiento al principio del ciclo de vida de desarrollo. Lo ideal es que el tiempo de creación, antes de confirmar el código, sea adecuado para detectar y abordar problemas. Cuanto más tarde se detecte un problema en el ciclo de vida de desarrollo, más difícil y costoso será solucionarlo. Si bien esto se aplica a los problemas de corrección, también lo es para los problemas de rendimiento, ya que muchos de estos problemas no se abordarán de forma retroactiva una vez que se confirmen en la base de código.

En la actualidad, la mayoría de los comentarios sobre el rendimiento están fuera de banda mediante documentación o auditorías únicas, o bien llegan demasiado tarde a través de la regresión de métricas después de la implementación en producción. Queremos llevar esto a la hora de crearla.

Cumplimiento en los frameworks

Para mantener un nivel alto de experiencia del usuario en el rendimiento de carga, debes responder las siguientes preguntas:

  1. ¿Qué constituye una carga óptima y cuáles son los problemas habituales que podrían afectarla de forma negativa?
  2. ¿Qué soluciones se pueden preparar que no requieren la participación de los desarrolladores?
  3. ¿Cómo podemos asegurarnos de que el desarrollador use estas soluciones y las aproveche de manera óptima?
  4. ¿Qué otras decisiones podría tomar el desarrollador que afecten el rendimiento de carga?
  5. ¿Cuáles son los patrones de código que pueden indicarnos estas opciones (no 3 y 4, arriba) al momento de la creación?
  6. ¿Qué reglas podemos formular para evaluar estos patrones de código? ¿Cómo se pueden mostrar al desarrollador en el momento de la creación y, al mismo tiempo, se integran sin inconvenientes en su flujo de trabajo?

Para llevar el modelo de cumplimiento que tenemos internamente en Google a los frameworks de código abierto, nuestro equipo realizó grandes experimentos en Next.js y nos entusiasma compartir nuestros planes y una visión perfeccionados. Nos dimos cuenta de que el mejor conjunto de reglas para evaluar patrones de código deberá ser una combinación de análisis de código estático y verificaciones dinámicas. Estas reglas pueden abarcar varias plataformas, incluidas las siguientes:

  • ESLint
  • TypeScript
  • Verificaciones dinámicas en el servidor de desarrollo del usuario (después de la creación del DOM)
  • Agrupador de módulos (webpack)
  • Herramientas de CSS (aún exploratorias)

Si aprovechamos la posibilidad de proporcionar reglas a través de diferentes herramientas, podemos asegurarnos de que sean cohesivas, pero también abarcan cualquier problema de experiencia del usuario que afecte directamente el rendimiento de carga. Además, estas reglas también se pueden mostrar a los desarrolladores en diferentes momentos:

  • Durante el desarrollo local en el servidor de desarrollo, el navegador y el IDE del usuario mostrarán advertencias para solicitarles a los desarrolladores que realicen pequeños cambios en el código.
  • Durante el tiempo de compilación, los problemas sin resolver volverán a aparecer en la terminal del usuario.

En pocas palabras, los equipos elegirán los resultados que les interesen, como las Métricas web esenciales o el rendimiento de carga, y habilitarán conjuntos de reglas relevantes para que sigan todos los colaboradores de código.

Si bien esto funciona muy bien para proyectos nuevos, no es fácil actualizar bases de código grandes para que cumplan con los conjuntos de reglas completos. En Google, tenemos un sistema extenso para inhabilitar opciones en diferentes niveles, como líneas individuales de código fuente, directorios completos, bases de código heredadas o partes de la app que no están en desarrollo activo. Estamos explorando de forma activa estrategias eficaces para ofrecer esto a los equipos que utilizan frameworks de código abierto.

Cumplimiento en Next.js

ESLint es muy utilizado entre los desarrolladores de JavaScript. Más del 50% de las aplicaciones de Next.js usan ESLint en alguna parte de su flujo de trabajo de compilación. Next.js v11 introdujo compatibilidad con ESLint lista para usar que incluye un complemento personalizado y una configuración compartible para facilitar la detección de problemas comunes específicos del framework durante el desarrollo y el tiempo de compilación. Esto puede ayudar a los desarrolladores a solucionar problemas importantes durante la creación. Por ejemplo, cuando se usa o no un componente determinado de una manera que podría afectar el rendimiento, como en el caso de No hay un vínculo HTML a la página. O bien, si una fuente, una hoja de estilo o una secuencia de comandos determinada pueden afectar negativamente la carga de recursos en una página. Por ejemplo, Sin secuencia de comandos síncrona.

Además de ESLint, la comprobación de tipos integrada en el desarrollo y la producción se admite en Next.js desde la versión 9 y compatible con TypeScript. Los múltiples componentes que proporciona el framework (imagen, secuencia de comandos y vínculo) se compilaron como una extensión de los elementos HTML (<img>, <script>, <a>) para proporcionar a los desarrolladores un enfoque eficaz para agregar contenido a una página web. La verificación de tipos admite el uso adecuado de estas funciones, ya que garantiza que las propiedades y las opciones asignadas estén dentro del alcance aceptable de los valores y tipos admitidos. Consulta el artículo Ancho y altura de imagen obligatorios para ver un ejemplo.

Cómo resolver errores con avisos y superposiciones

Como se mencionó anteriormente, las reglas de cumplimiento se pueden mostrar en varias áreas. Actualmente, se están explorando los avisos y las superposiciones como una manera de mostrar errores directamente en el navegador dentro del entorno de desarrollo local del usuario.

Los errores que surgen a través de avisos

Muchas herramientas de comprobación de errores y auditoría en las que confían los desarrolladores (Lighthouse y la pestaña Problemas de las Herramientas para desarrolladores de Chrome) son pasivas y requieren algún tipo de interacción por parte del usuario para recuperar información. Es más probable que los desarrolladores actúen cuando los errores aparecen directamente en sus herramientas existentes y cuando proporcionan acciones concretas y específicas que se deben tomar para solucionar el problema.

Cumplimiento en otros marcos

Se está explorando el cumplimiento en Next.js primero con el objetivo de expandirse a otros frameworks (Nuxt, Angular, etcétera). ESLint y TypeScript ya se usan en muchos frameworks de muchas maneras diferentes, pero el concepto de un sistema de entorno de ejecución cohesivo a nivel del navegador se está explorando de forma activa.

Conclusión

El cumplimiento codifica las prácticas recomendadas en conjuntos de reglas que los desarrolladores pueden usar como patrones de código simples. El equipo de Aurora se enfocó en el rendimiento de carga, pero otras prácticas recomendadas, como la accesibilidad y la seguridad, son igual de aplicables.

Seguir las reglas de cumplimiento debería generar resultados predecibles, y lograr un estándar alto para la experiencia del usuario puede convertirse en un efecto secundario de compilar en tu pila tecnológica. El cumplimiento hace que los equipos sean productivos y garantiza una barra de alta calidad para la aplicación, incluso a medida que los equipos y las bases de código crecen con el tiempo.