Como procurar bugs no front end: 4 estágios principais


Neste artigo, considerarei a questão de identificar e manipular erros que ocorrem no front-end (navegador ou visualização na web).

No frontend, o código JS é executado no navegador. O JavaScript não é uma linguagem compilada; portanto, sempre há uma chance de erro de desempenho ao usar o programa diretamente. Um erro de execução bloqueia o código localizado após o local do erro e os usuários do programa correm o risco de permanecer com uma tela de aplicativo não funcional que só pode ser recarregada ou fechada. Mas existem métodos para detectar erros e seu acompanhamento seguro, para evitar tais situações.

1. Ferramentas JavaScript


Blocos de tentativa / captura


Funções que podem falhar podem ser agrupadas em blocos try / catch. Primeiro, o programa tenta executar o código no bloco try. Se, por algum motivo, a execução do código for interrompida, o programa entrará no bloco catch, onde três parâmetros estão disponíveis:

  • nome - nome padronizado do erro;
  • message - mensagem sobre os detalhes do erro;
  • stack - a pilha de chamadas atual em que ocorreu o erro.

Ou seja:

try {

   callFunc();

} catch (e) {

   console.log(e.name) // ReferenceError

   console.log(e.message) // callFunc is not defined

   console.log(e.stack) // ReferenceError: callFunc is not defined at window.onload

}

Para o desenvolvedor, o principal é que o programa possa continuar a execução após o bloco catch. Assim, a interação do usuário não será interrompida.

Usando o bloco try / catch, você também pode causar seus próprios erros, por exemplo, ao verificar dados:

const user = {

  name : «Mike»

};

try {

   if (!user.age) throw new SyntaxError(«User age is absent!»);

} catch (e) {

   console.log(e.name) // SyntaxError

   console.log(e.message) // User age is absent!

   console.log(e.stack) // SyntaxError: User age is absent! at window.onload

}

Por fim, você pode expandir essa instrução com mais um bloco - finalmente, que sempre é executado: no caso em que não houve erro na tentativa e no caso do controle passado para o bloco catch:

try {

   callFunc();

} catch (e) {

   console.log(e)

} finally {

   ...

}

Às vezes, eles usam a instrução try / finally (sem captura) para que você possa continuar usando o código sem manipular erros específicos.

Evento Window.onerror


Muitas vezes, é útil saber que o script na página foi quebrado, mesmo que o programa tenha sido interrompido e a sessão do usuário tenha sido concluída sem êxito. Geralmente, essas informações são usadas nos sistemas de registro de erros.

O objeto da janela global possui um evento onerror ( use-o com cuidado: a implementação pode diferir em diferentes navegadores! ):

window.onerror = function(message, url, line, col, error) {

   console.log(`${message}\n  ${line}:${col}  ${url}`);

};

Se você colocar esse código no início do script ou carregá-lo em um script separado, em primeiro lugar, por qualquer erro abaixo, o desenvolvedor estará disponível com informações detalhadas.

No entanto, informações completas estão disponíveis apenas para scripts que foram baixados do mesmo domínio. Se o script quebrado for carregado de outro domínio, o window.onerror funcionará, mas não haverá detalhes do erro.

Componentes da estrutura


Algumas estruturas JS ( React , Vue) oferecem suas próprias soluções de tratamento de erros. Por exemplo, o React poderá desenhar um layout especial no local do bloco em que ocorreu o erro:

class ErrorBoundary extends React.Component {

   constructor(props) {

       super(props);

       this.state = { hasError: false };

   }

   static getDerivedStateFromError(error) {

       //    ,      UI.

       return { hasError: true };

   }

   componentDidCatch(error, errorInfo) {

       //           

       logErrorToMyService(error, errorInfo);

   }

   render() {

       if (this.state.hasError) {

           //    UI  

           return <h1>-   .</h1>;

       }

       return this.props.children;

   }

}

<ErrorBoundary>

   <MyWidget />

</ErrorBoundary>

De fato, o componente React está envolvido em um componente especial que lida com erros. Isso é semelhante às funções de agrupamento com uma construção try / catch.

2. Ferramentas de montagem do projeto


Os scripts JS modernos geralmente são transpilados. Ou seja, o desenvolvimento é realizado usando os mais recentes padrões de ES. E, em seguida, o código do desenvolvedor que usa o construtor de projetos (como o Webpack) é convertido em código que garantirá que funcione no número selecionado de navegadores.

No estágio de compilação, o código é verificado quanto à sintaxe correta. Um suporte aberto ou uma designação incorreta de um campo de classe causará imediatamente um erro durante a montagem e o pacote configurável simplesmente não será montado. O desenvolvedor precisará corrigir imediatamente esses erros para continuar trabalhando.

Além disso, o coletor pode sugerir que algumas partes do código não sejam usadas ao executar o programa. Talvez isso leve o desenvolvedor a pensar em um estudo mais aprofundado do código, que pode afetar indiretamente a identificação de novos erros.

3. Teste


Outra maneira de evitar erros no código é testá-lo. Existem ferramentas no frontend para o uso eficaz de testes de unidade. Normalmente, estruturas como Jest, Karma, Mocha, Jasmine são usadas. Juntamente com as estruturas de teste, eles costumam usar extensões como Enzyme, React Testing Library, Sinon e outras, que permitem enriquecer os testes com a ajuda de zombaria, funções de espionagem e outras ferramentas.

Ao procurar por erros, os testes são úteis principalmente para carregar uma variedade de dados que podem levar a erros de execução. Portanto, o código a seguir passará na validação da sintaxe e funcionará conforme o esperado:

const func = (data) => {

   return JSON.parse(data)

}

func('{«a»:1}')

No entanto, ele será interrompido se você der o valor errado:

func() // Uncaught SyntaxError: Unexpected token u in JSON at position 0.


Este código também passa na validação durante a montagem:

const obj = {

   outer : {

       last : 9

   }

}

if (obj.outer.inner.last) {

   console.log(«SUCCESS»)

}

No entanto, também será interrompido durante a execução. Após o teste, o desenvolvedor provavelmente fará verificações adicionais:

if (obj.outer?.inner?.last) {

   console.log(«SUCCESS»)

}

Freqüentemente, esses erros ocorrem ao receber dados do servidor (por exemplo, com uma solicitação AJAX) com suas análises subsequentes. O teste do código permite identificar e eliminar antecipadamente os casos em que o código pode quebrar durante a execução no navegador do cliente.

4. Log


Suponha que tenhamos tomado todas as medidas possíveis para evitar erros durante o desenvolvimento e a montagem do projeto. No entanto, os erros ainda podem se infiltrar no código produtivo. Precisamos, de alguma forma, descobrir sua presença e tomar medidas corretivas imediatas. Pedir aos usuários para abrir um console do navegador e tirar capturas de tela não é a melhor opção. Portanto, é bom conectar o log de erros ao projeto.

O significado é simples: para cada evento window.onerror ou cada transição de execução de código para o bloco catch, é feita uma solicitação AJAX simples para um endereço de servidor alocado especialmente, no corpo do qual são colocadas informações sobre o erro. Em seguida, você precisará de uma ferramenta que notifique rapidamente o suporte técnico e os desenvolvedores sobre a presença de novos erros e permita que você trabalhe efetivamente com eles. A mais popular dessas ferramentas de front-end é o Sentry.

O sistema de registro de sentinelas permite coletar, agrupar e apresentar erros em tempo real. Existem assemblies para diferentes idiomas, incluindo JavaScript. O projeto fornece acesso pago com recursos avançados para negócios, no entanto, você pode experimentar seus principais recursos em uma conta de teste gratuita.

O Sentry pode ser conectado diretamente no arquivo HTML e nos componentes executados em uma das estruturas populares: React, Vue, Angular, Ember e outras.

Para conectar os recursos de log diretamente no navegador na seção, carregue o script:

<script

   src=«https://browser.sentry-cdn.com/5.13.0/bundle.min.js»

   integrity=«sha384-ePH2Cp6F+/PJbfhDWeQuXujAbpil3zowccx6grtsxOals4qYqJzCjeIa7W2UqunJ»

   crossorigin="anonymous"></script>


Em seguida, no código JS, inicializamos:

Sentry.init({

   dsn: 'https://<your account key here>@sentry.io/<your project id here>'

});

Todos. Se e quando ocorrer um erro no código abaixo desta linha, o Sentry o registrará. Os logs serão gravados mesmo quando o erro ocorreu devido à falha de scripts de outros domínios:



O Sentry tem ampla oportunidade de analisar uma variedade de mensagens de erro e configurar notificações. Também é possível agrupar logs de erros pelas versões do seu produto:

Sentry.init({

   dsn: 'https://<your account key here>@sentry.io/<your project id here>',

   release: '2020.03.06.1'

});

Usando o Sentry, as estatísticas podem ser usadas para transferir o contexto de um erro, por exemplo, informações do cliente, impressão digital, nível de erro (fatal, erro, aviso, informações, depuração) e tag.

É possível registrar eventos do usuário nas estatísticas. Por exemplo, você pode definir o rastreamento para alterar o tamanho da janela do navegador ou fazer uma solicitação AJAX. O Sentry também possui seu próprio widget com uma janela de feedback, que pode ser exibida ao usuário em caso de erro. Isso fornecerá informações adicionais para investigar as circunstâncias do erro.

Para implantar o Sentry junto com as estruturas, basta instalar o pacote e conectar:

# Using yarn

yarn add @sentry/browser

# Using npm

npm install @sentry/browser


Inicializamos no script principal do projeto (para React e Angular):

import * as Sentry from «@sentry/browser»;

Sentry.init({ dsn: 'https://<your account key here>@sentry.io/<your project id here>' });


Para Vue e Ember, passamos por outra linha de configuração necessária:

# Vue

Sentry.init({

   dsn: '<your account key here>@sentry.io/<your project id here>',

   integrations: [new Integrations.Vue({Vue, attachProps: true})],

});

# Ember

Sentry.init({

   dsn: '<your account key here>@sentry.io/<your project id here>',

   integrations: [new Integrations.Ember()]

});

O pacote de integrações é instalado separadamente:

# Using yarn

yarn add @sentry/integrations

# Using npm

npm install @sentry/integrations

Para evitar conflitos e duplicação de informações ao conectar vários scripts em um projeto, o Sentry permite criar um cliente separado para cada inicialização do log:

import { BrowserClient } from «@sentry/browser»;

const client = new BrowserClient({

   dsn: '<your account key here>@sentry.io/<your project id here>',

});

client.captureException(new Error('example'));

O site do projeto possui documentação detalhada com exemplos de uso: https://docs.sentry.io .

Este artigo foi preparado com o suporte da plataforma de nuvem Mail.ru Cloud Solutions .

O que mais se pode ler sobre o tópico:

  1. Componentes de reação reativa: Como parar de escrever o mesmo .
  2. Como evitar erros ao desenvolver no React .
  3. - .

All Articles