Uma introdução à execução do Lighthouse programaticamente

Publicados: 2022-03-10
Resumo rápido ↬ Ser capaz de executar programaticamente a suíte de análise Lighthouse do Google oferece muitas vantagens, especialmente para aplicativos da Web maiores ou mais complexos. Usar o Lighthouse programaticamente permite que os engenheiros configurem o monitoramento de qualidade para sites que precisam de mais personalização do que os aplicativos simples do Lighthouse (como o Lighthouse CI) permitem. Este artigo contém uma breve introdução ao Lighthouse, discute as vantagens de executá-lo programaticamente e apresenta uma configuração básica.

Lighthouse é o conjunto de ferramentas de análise de qualidade de sites do Google. Ele permite que você avalie o desempenho, acessibilidade, SEO e muito mais do seu site. Também é altamente configurável, tornando-o flexível o suficiente para ser útil para todos os sites, dos mais simples aos mais complexos. Essa flexibilidade inclui várias maneiras diferentes de executar os testes, permitindo que você escolha o método que funciona melhor para seu site ou aplicativo.

Uma das maneiras mais simples de executar o Lighthouse é através do painel DevTools Lighthouse do Chrome. Se você abrir seu site no Chrome e, em seguida, abrir o DevTools do Chrome, você verá uma guia “Lighthouse”. A partir daí, se você clicar em “Gerar Relatório”, deverá obter um relatório completo das métricas de qualidade do seu site.

O que estou focando neste artigo, no entanto, está no outro extremo do espectro. A execução do Lighthouse programaticamente com JavaScript nos permite configurar execuções personalizadas, escolhendo os recursos que queremos testar, coletando e analisando resultados e especificando opções de configuração exclusivas para nossos sites e aplicativos.

Por exemplo, talvez você trabalhe em um site acessível por meio de vários URLs, cada um com seus próprios dados e estilo e talvez até marcação que você deseja analisar. Ou talvez você queira coletar os dados de cada execução de teste e compilá-los ou analisá-los de maneiras diferentes. Ter a capacidade de escolher como você deseja executar uma análise do Lighthouse com base no que funciona melhor para seu site ou aplicativo facilita o monitoramento da qualidade do site e identifica onde há problemas com seu site antes que eles se acumulem ou causem muitos problemas para o seu usuários do site.

A execução do Lighthouse programaticamente não é a melhor opção para todos os sites e recomendo que você explore todos os métodos diferentes que a equipe do Lighthouse criou para usar a ferramenta. Se você decidir usar o Lighthouse programaticamente, no entanto, as informações e o tutorial abaixo devem ajudá-lo a começar.

Personalizando as opções do farol

A vantagem de executar o Lighthouse programaticamente não é apenas a capacidade de configurar o Lighthouse em si, mas sim todas as coisas que você pode querer ou precisar fazer em relação aos testes do Lighthouse. O Lighthouse tem uma ótima documentação para você começar. No entanto, para obter o máximo da execução programaticamente, há dois lugares principais em que você precisará se aprofundar e aprender mais sobre como o Lighthouse funciona: configurando suas execuções de teste e relatando seus resultados de teste.

Configuração de execução de teste do Lighthouse

Configurar uma execução de teste do Lighthouse é uma daquelas tarefas que podem ser tão simples ou complexas quanto você desejar.

Ao executar o Lighthouse programaticamente, há três locais onde você pode fornecer opções personalizadas: o URL que você testará, as opções do Chrome e o objeto de configuração do Lighthouse. Você pode ver todos os três parâmetros na função para executar o Lighthouse na documentação do 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) }); }); }

Você pode usar qualquer código que precisar para criar esses parâmetros. Por exemplo, digamos que você tenha um site com várias páginas ou URLs que gostaria de testar. Talvez você queira executar esse teste em um ambiente de CI como parte de suas tarefas de CI, verificando todas as páginas necessárias sempre que a tarefa for executada. Usando essa configuração, você pode usar JavaScript para criar seus URLs e criar um loop que executará o Lighthouse para cada um.

Quaisquer opções do Chrome que você possa precisar podem ser especificadas em um objeto que é passado para o chrome-launcher. No exemplo da documentação, o objeto opts contém uma matriz que estamos chamando chromeFlags que você pode passar para o chrome-launcher e uma porta onde você pode salvar a porta que está sendo usada pelo chrome-launcher e depois passá-la para o Lighthouse.

Por fim, o objeto de configuração do Lighthouse permite adicionar quaisquer opções específicas do Lighthouse. O pacote Lighthouse fornece um objeto de configuração padrão que pode ser usado como está ou estendido e modificado. Você pode usar esse objeto para fazer várias coisas, incluindo especificar quais categorias de teste do Lighthouse você deseja testar.

Mais depois do salto! Continue lendo abaixo ↓

Você pode usar o emulatedFormFactor para especificar se deseja que o teste seja executado em um emulador móvel ou de desktop. Você pode usar extraHeaders para adicionar quaisquer cookies que precise usar no navegador. Por exemplo, um teste executando apenas a categoria de acessibilidade em um emulador de desktop que gera os resultados como HTML pode ter um objeto de configuração semelhante a este:

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

Este exemplo representa uma configuração mínima. Há muito mais que você pode fazer. Os documentos de configuração do Lighthouse têm muito mais informações. Eles também têm um conjunto de objetos de configuração de amostra para algumas implementações mais complexas.

Relatório de resultados personalizados

Ao executar o Lighthouse programaticamente, você pode ter os resultados retornados em uma ou mais das três opções formatadas e - e esta é a parte mais interessante na minha opinião - você pode ter acesso ao objeto Raw Lighthouse Result (LHR).

HTML, JSON, CSV

O Lighthouse formatará automaticamente os resultados de três maneiras diferentes: HTML, JSON ou CSV. Esses são todos resultados pré-configurados com base no modelo de relatório básico do Lighthouse, que é o que você vê se executar um teste do Lighthouse dentro do Chrome DevTools, por exemplo. No objeto de configuração lighthouseOptions da seção anterior, você pode ver uma chave para output que contém um array com uma única string: html . Isso especifica que eu só quero que os resultados sejam retornados formatados como HTML. Se eu quisesse os resultados como HTML e JSON, essa matriz seria ['html', 'json'] .

Depois que o Lighthouse for executado, ele retornará um objeto de resultados que conterá duas chaves: report e lhr . Falaremos sobre o conteúdo da chave lhr na próxima seção, mas a chave de report contém uma matriz com os resultados formatados conforme você solicitou. Assim, por exemplo, se tivermos solicitado ['html', 'json'] , results.report[0] conterá nossos resultados formatados como HTML e results.report[1] conterá nossos resultados formatados como JSON.

O objeto LHR

A execução do Lighthouse programaticamente também oferece acesso a um objeto de resultados muito mais flexível: o objeto LHR. Este objeto contém os resultados brutos e alguns metadados da sua execução do Lighthouse. Uma documentação mais completa pode ser encontrada no repositório do Lighthouse Github.

Você pode usar esses resultados de várias maneiras, incluindo a criação de relatórios personalizados e a coleta de dados de várias execuções para análise.

Exemplo: execução de um teste de acessibilidade para dispositivos móveis e computadores

Digamos que eu tenha um site que carrega componentes diferentes dependendo se o usuário está usando uma tela menor ou maior, o que significa que o HTML para cada versão do site será um pouco diferente. Quero garantir que ambas as versões do site obtenham uma pontuação de 95 nos testes de acessibilidade do Lighthouse e que nenhum código seja comprometido com nosso branch main que não atenda a esse padrão.

Nota : Se você quiser ver um exemplo funcional do código abaixo analisando a página inicial do Sparkbox, você pode encontrar o repositório aqui.

Posso configurar o Lighthouse para executar a categoria de acessibilidade duas vezes, fornecendo objetos de configuração diferentes para cada um — um definindo o emulatedFormFactor como desktop e outro definindo-o como mobile . Uma maneira fácil de fazer isso é criar um array com os dois objetos, mostrados abaixo.

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

Então, posso criar uma função que fará um loop por esse array e executará um teste do Lighthouse para cada objeto encontrado dentro do array.

Uma coisa a notar é que é necessário introduzir um atraso entre cada execução, caso contrário, o Chromium pode ficar confuso e as execuções apresentarão erros. Para fazer isso, adicionei uma função de wait que retorna uma promessa quando o intervalo setTimeout é concluído.

 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); } }

Nesse caso, estou enviando os resultados para uma função reportResults . A partir daí, salvo os resultados em arquivos locais, imprimo os resultados no console e envio os resultados para uma função que determinará se os testes passam ou falham em nosso limite de acessibilidade.

 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 projeto, quero poder salvar os resultados JSON em um diretório especificado para nossas execuções de teste de CI e o arquivo HTML em um diretório especificado para nossas execuções de teste locais. A maneira como o Lighthouse retorna esses diferentes tipos de resultados está em uma matriz na ordem em que foram solicitados.

Então, neste exemplo, em nosso objeto lighthouseOptions , nosso array pede primeiro HTML, depois JSON. Portanto, a matriz do report conterá primeiro os resultados formatados em HTML e depois os resultados formatados em JSON. A função writeToLocalFile salva a versão correta dos resultados em um arquivo com um nome 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; }

Eu também quero imprimir os resultados no terminal quando o teste terminar. Isso fornece uma maneira rápida e fácil de visualizar os resultados sem ter que abrir um arquivo.

 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********************************'); }

E, finalmente, quero ser capaz de falhar em minhas execuções de teste se as pontuações de acessibilidade não atingirem minha pontuação limite 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; } } } }

Convido todos vocês a brincar com ele e explorar todas as diferentes maneiras pelas quais o Lighthouse pode ajudar a monitorar a qualidade do seu site.

Notas Finais

Embora eu tenha intencionalmente mantido o exemplo acima relativamente simples, espero que ele tenha dado a você uma boa visão geral do que pode ser feito ao executar o Lighthouse programaticamente. E espero que inspire você a encontrar novas maneiras de usar essa ferramenta flexível e poderosa.

Como disse Peter Drucker:

“Se você não pode medi-lo, você não pode melhorá-lo.”

Ser capaz de não apenas medir, mas monitorar a qualidade do nosso site, especialmente para sites complexos, ajudará muito a construir uma web melhor.

Leitura adicional no SmashingMag:

  • Testes A/B para experiências mobile-first
  • Como testar a eficácia de um conceito de design
  • A importância do teste manual de acessibilidade
  • Aprendizado de máquina para desenvolvedores front-end com Tensorflow.js
  • Comece a usar o design de interface do usuário com essas dicas para acelerar seu fluxo de trabalho

The Smashing Cat explorando novos insights, nos Smashing Workshops, é claro.

Bits úteis de front-end e UX, entregues uma vez por semana.

Com ferramentas para ajudá-lo a fazer seu trabalho melhor. Assine e receba o PDF das listas de verificação de design de interface inteligente da Vitaly por e-mail.

No front-end e UX. Confiado por 190.000 pessoas.