Una introducción a la ejecución de Lighthouse mediante programación

Publicado: 2022-03-10
Resumen rápido ↬ Ser capaz de ejecutar la suite de análisis Lighthouse de Google mediante programación ofrece muchas ventajas, especialmente para aplicaciones web más grandes o más complejas. El uso de Lighthouse de forma programática permite a los ingenieros configurar un control de calidad para los sitios que necesitan más personalización de lo que permiten las aplicaciones sencillas de Lighthouse (como Lighthouse CI). Este artículo contiene una breve introducción a Lighthouse, analiza las ventajas de ejecutarlo mediante programación y recorre una configuración básica.

Lighthouse es el conjunto de herramientas de análisis de calidad de sitios web de Google. Le permite evaluar el rendimiento, la accesibilidad, el SEO y más de su sitio. También es altamente configurable, lo que lo hace lo suficientemente flexible como para ser útil para todos los sitios, desde los más simples hasta los más complejos. Esta flexibilidad incluye varias formas diferentes de ejecutar las pruebas, lo que le permite elegir el método que mejor se adapte a su sitio o aplicación.

Una de las formas más sencillas de ejecutar Lighthouse es a través del panel Lighthouse de DevTools de Chrome. Si abre su sitio en Chrome y luego abre DevTools de Chrome, debería ver una pestaña "Lighthouse". A partir de ahí, si hace clic en "Generar informe", debería obtener un informe completo de las métricas de calidad de su sitio.

Sin embargo, en lo que me estoy enfocando en este artículo está en el otro extremo del espectro. Ejecutar Lighthouse mediante programación con JavaScript nos permite configurar ejecuciones personalizadas, seleccionando y eligiendo las funciones que queremos probar, recopilando y analizando resultados, y especificando opciones de configuración únicas para nuestros sitios y aplicaciones.

Por ejemplo, tal vez trabaje en un sitio al que se puede acceder a través de varias URL, cada una con sus propios datos y estilo, y tal vez incluso marcas que desee poder analizar. O tal vez desee recopilar los datos de cada ejecución de prueba y compilarlos o analizarlos de diferentes maneras. Tener la capacidad de elegir cómo desea ejecutar un análisis de Lighthouse en función de lo que funciona mejor para su sitio o aplicación hace que sea más fácil monitorear la calidad del sitio e identificar dónde hay problemas con su sitio antes de que se acumulen o causen demasiados problemas para su los usuarios del sitio.

Ejecutar Lighthouse de manera programática no es la mejor opción para todos los sitios y lo animo a explorar todos los diferentes métodos que el equipo de Lighthouse ha creado para usar la herramienta. Sin embargo, si decide usar Lighthouse mediante programación, la información y el tutorial a continuación deberían ayudarlo a comenzar.

Personalización de las opciones de Lighthouse

La ventaja de ejecutar Lighthouse mediante programación no es solo la capacidad de configurar Lighthouse en sí mismo, sino todas las cosas que puede querer o necesitar hacer en torno a las pruebas de Lighthouse. Lighthouse tiene una excelente documentación para que pueda comenzar. Sin embargo, para aprovechar al máximo la ejecución programática, hay dos lugares principales en los que deberá profundizar y aprender más sobre cómo funciona Lighthouse: configurar sus ejecuciones de prueba e informar sus resultados de prueba.

Configuración de ejecución de prueba de Lighthouse

Configurar una ejecución de prueba de Lighthouse es una de esas tareas que puede ser tan simple o tan compleja como desee.

Cuando ejecuta Lighthouse mediante programación, hay tres lugares donde puede proporcionar opciones personalizadas: la URL que probará, las opciones de Chrome y el objeto de configuración de Lighthouse. Puede ver que estos tres son parámetros en la función para ejecutar Lighthouse en la documentación de Lighthouse:

 function launchChromeAndRunLighthouse(url, opts, config = null) { return chromeLauncher.launch({chromeFlags: opts.chromeFlags}).then(chrome => { opts.port = chrome.port; return lighthouse(url, opts, config).then(results => { return chrome.kill().then(() => results.lhr) }); }); }

Puede usar cualquier código que necesite para crear estos parámetros. Por ejemplo, supongamos que tiene un sitio con varias páginas o URL que le gustaría probar. Tal vez quiera ejecutar esa prueba en un entorno de CI como parte de sus tareas de CI, verificando todas las páginas necesarias cada vez que se ejecuta la tarea. Con esta configuración, puede usar JavaScript para crear sus URL y crear un ciclo que ejecutará Lighthouse para cada uno.

Cualquier opción de Chrome que pueda necesitar se puede especificar en un objeto que se pasa a Chrome-launcher. En el ejemplo de la documentación, el objeto opts contiene una matriz que llamamos chromeFlags que puede pasar a chrome-launcher y un puerto donde puede guardar el puerto que usa chrome-launcher y luego pasarlo a Lighthouse.

Finalmente, el objeto de configuración de Lighthouse le permite agregar cualquier opción específica de Lighthouse. El paquete Lighthouse proporciona un objeto de configuración predeterminado que puede usarse tal cual o ampliarse y modificarse. Puede usar este objeto para hacer una multitud de cosas, incluida la especificación de las categorías de prueba de Lighthouse que desea probar.

¡Más después del salto! Continúe leyendo a continuación ↓

Puede utilizar el emulatedFormFactor para especificar si desea que la prueba se ejecute en un emulador móvil o de escritorio. Puede usar extraHeaders para agregar cualquier cookie que necesite usar en el navegador. Por ejemplo, una prueba que ejecuta solo la categoría de accesibilidad en un emulador de escritorio que muestra los resultados como HTML podría tener un objeto de configuración similar a este:

 const lighthouseOptions = { extends: 'lighthouse:default', settings: { onlyCategories: ['accessibility'], emulatedFormFactor:'desktop', output: ['html'], }, }

Este ejemplo representa una configuración mínima. Hay mucho más que puedes hacer. Los documentos de configuración de Lighthouse tienen mucha más información. También tienen un conjunto de objetos de configuración de muestra para algunas implementaciones más complejas.

Informes de resultados personalizados

Cuando ejecuta Lighthouse de forma programática, puede obtener los resultados en una o más de tres opciones formateadas y, y esta es la pieza más emocionante en mi opinión, puede tener acceso al objeto Lighthouse Result (LHR) sin procesar.

HTML, JSON, CSV

Lighthouse formateará automáticamente los resultados de tres maneras diferentes: HTML, JSON o CSV. Todos estos son resultados preconfigurados basados ​​en la plantilla básica de informes de Lighthouse, que es lo que ve si ejecuta una prueba de Lighthouse dentro de Chrome DevTools, por ejemplo. En el objeto de configuración lighthouseOptions de la sección anterior, puede ver una clave para la output que contiene una matriz con una sola cadena: html . Esto especifica que solo quiero que los resultados se devuelvan con formato HTML. Si quisiera los resultados como HTML y JSON, esa matriz se vería como ['html', 'json'] .

Una vez que Lighthouse se haya ejecutado, devolverá un objeto de resultados que contendrá dos claves: report y lhr . Hablaremos sobre el contenido de la clave lhr en la siguiente sección, pero la clave de report contiene una matriz con los resultados con el formato que solicitó. Entonces, por ejemplo, si hemos solicitado ['html', 'json'] , entonces results.report[0] contendrá nuestros resultados formateados como HTML y results.report[1] contendrá nuestros resultados formateados como JSON.

El objeto LHR

Ejecutar Lighthouse mediante programación también le da acceso a un objeto de resultados mucho más flexible: el objeto LHR. Este objeto contiene los resultados sin procesar y algunos metadatos de su ejecución de Lighthouse. Se puede encontrar documentación más completa en el repositorio de Lighthouse Github.

Puede usar estos resultados de varias maneras, incluida la creación de informes personalizados y la recopilación de datos de varias ejecuciones para su análisis.

Ejemplo: ejecución de una prueba de accesibilidad para dispositivos móviles y de escritorio

Digamos que tengo un sitio que carga diferentes componentes dependiendo de si el usuario está usando una pantalla más pequeña o más grande, lo que significa que el HTML para cada versión del sitio será ligeramente diferente. Quiero asegurarme de que ambas versiones del sitio obtengan una puntuación de 95 en las pruebas de accesibilidad de Lighthouse y que no se comprometa ningún código en nuestra rama main que no cumpla con ese estándar.

Nota : si desea ver un ejemplo de trabajo del código a continuación analizando la página de inicio de Sparkbox, puede encontrar el repositorio aquí.

Puedo configurar Lighthouse para ejecutar la categoría de accesibilidad dos veces, proporcionando diferentes objetos de configuración para cada uno: uno configurando el emulatedFormFactor para desktop y otro configurando para mobile . Una manera fácil de hacer esto es crear una matriz con ambos objetos, como se muestra a continuación.

 const lighthouseOptionsArray = [ { extends: 'lighthouse:default', settings: { onlyCategories: ['accessibility'], emulatedFormFactor:'desktop', output: ['html', 'json'], }, }, { extends: 'lighthouse:default', settings: { onlyCategories: ['accessibility'], emulatedFormFactor:'mobile', output: ['html', 'json'], }, }, ]

Luego, puedo crear una función que recorrerá esta matriz y ejecutará una prueba de Lighthouse para cada objeto que se encuentre dentro de la matriz.

Una cosa a tener en cuenta es que es necesario introducir un retraso entre cada ejecución, de lo contrario, Chromium puede confundirse y las ejecuciones fallarán. Para hacer esto, agregué una función de wait que devuelve una promesa cuando se completa el intervalo setTimeout .

 function wait(val) { return new Promise(resolve => setTimeout(resolve, val)); } function launchLighthouse(optionSet, opts, results) { return chromeLauncher .launch({ chromeFlags: opts.chromeFlags }) .then(async chrome => { opts.port = chrome.port; try { results = await lighthouse(url, opts, optionSet); } catch (e) { console.error("lighthouse", e); } if (results) reportResults(results, runEnvironment, optionSet, chrome); await wait(500); chrome.kill(); }); } async function runLighthouseAnalysis() { let results; const opts = { chromeFlags: ["--no-sandbox", "--headless"] }; for (const optionSet of lighthouseOptionsArray) { console.log("****** Starting Lighthouse analysis ******"); await launchLighthouse(optionSet, opts, results); } }

En este caso, envío los resultados a una función reportResults . Desde allí, guardo los resultados en archivos locales, imprimo los resultados en la consola y envío los resultados a una función que determinará si las pruebas superan o no nuestro umbral de accesibilidad.

 async function reportResults(results, runEnvironment, optionSet, chrome) { if (results.lhr.runtimeError) { return console.error(results.lhr.runtimeError.message); } await writeLocalFile(results, runEnvironment, optionSet); printResultsToTerminal(results.lhr, optionSet); return passOrFailA11y(results.lhr, optionSet, chrome); }

Para este proyecto, quiero poder guardar los resultados de JSON en un directorio específico para nuestras ejecuciones de prueba de CI y el archivo HTML en un directorio específico para nuestras ejecuciones de prueba locales. La forma en que Lighthouse devuelve estos diferentes tipos de resultados es en una matriz en el orden en que fueron solicitados.

Entonces, en este ejemplo, en nuestro objeto lighthouseOptions , nuestra matriz solicita HTML primero, luego JSON. Por lo tanto, la matriz del report contendrá los resultados con formato HTML primero y los resultados con formato JSON en segundo lugar. La función writeToLocalFile luego guarda la versión correcta de los resultados en un archivo con un nombre personalizado.

 function createFileName(optionSet, fileType) { const { emulatedFormFactor } = optionSet.settings; const currentTime = new Date().toISOString().slice(0, 16); const fileExtension = fileType === 'json' ? 'json' : 'html'; return `${currentTime}-${emulatedFormFactor}.${fileExtension}`; } function writeLocalFile(results, runEnvironment, optionSet) { if (results.report) { const fileType = runEnvironment === 'ci' ? 'json' : 'html'; const fileName = createFileName(optionSet, fileType); fs.mkdirSync('reports/accessibility/', { recursive: true }, error => { if (error) console.error('error creating directory', error); }); const printResults = fileType === 'json' ? results.report[1] : results.report[0]; return write(printResults, fileType, `reports/accessibility/${fileName}`).catch(error => console.error(error)); } return null; }

También quiero imprimir los resultados en el terminal cuando terminen las pruebas. Esto proporciona una manera rápida y fácil de ver los resultados sin tener que abrir un archivo.

 function printResultsToTerminal(results, optionSet) { const title = results.categories.accessibility.title; const score = results.categories.accessibility.score * 100; console.log('\n********************************\n'); console.log(`Options: ${optionSet.settings.emulatedFormFactor}\n`); console.log(`${title}: ${score}`); console.log('\n********************************'); }

Y finalmente, quiero poder fallar en mis ejecuciones de prueba si los puntajes de accesibilidad no alcanzan mi puntaje de umbral de 95.

 function passOrFailA11y(results, optionSet, chrome) { const targetA11yScore = 95; const { windowSize } = optionSet; const accessibilityScore = results.categories.accessibility.score * 100; if (accessibilityScore) { if (windowSize === 'desktop') { if (accessibilityScore < targetA11yScore) { console.error(`Target accessibility score: ${targetA11yScore}, current accessibility score ${accessibilityScore}`); chrome.kill(); process.exitCode = 1; } } if (windowSize === 'mobile') { if (accessibilityScore < targetA11yScore) { console.error(`Target accessibility score: ${targetA11yScore}, current accessibility score ${accessibilityScore}`); chrome.kill(); process.exitCode = 1; } } } }

Los invito a todos a jugar con él y explorar las diferentes formas en que Lighthouse puede ayudarlo a monitorear la calidad de su sitio.

Notas finales

Si bien intencionalmente mantuve el ejemplo anterior relativamente simple, espero que le haya dado una buena visión general de lo que se puede lograr cuando se ejecuta Lighthouse mediante programación. Y espero que lo inspire a encontrar nuevas formas de usar esta herramienta flexible y poderosa.

Como dijo Peter Drucker:

“Si no puedes medirlo, no puedes mejorarlo”.

Poder no solo medir sino también monitorear la calidad de nuestro sitio web, especialmente para sitios complejos, contribuirá en gran medida a ayudarnos a construir una mejor web.

Lectura adicional en SmashingMag:

  • Pruebas A/B para experiencias móviles primero
  • Cómo probar la eficacia de un concepto de diseño
  • La importancia de las pruebas de accesibilidad manual
  • Aprendizaje automático para desarrolladores front-end con Tensorflow.js
  • Comience con el diseño de la interfaz de usuario con estos consejos para acelerar su flujo de trabajo

The Smashing Cat explorando nuevos conocimientos, en Smashing Workshops, por supuesto.

Bits útiles de front-end y UX, entregados una vez a la semana.

Con herramientas para ayudarlo a hacer mejor su trabajo. Suscríbase y obtenga el PDF de listas de verificación de diseño de interfaz inteligente de Vitaly por correo electrónico.

En front-end y UX. Con la confianza de 190.000 personas.