Reagir nativo - aplicação e crítica

Na maioria das vezes, ao escolher esse idioma, espera-se que o desenvolvimento de um aplicativo para duas plataformas leve metade do tempo que o desenvolvimento de dois aplicativos. Mas, no final, verifica-se que o desenvolvimento leva muito, se não mais, devido às dificuldades ocultas sob o brilho externo e o marketing. Falaremos sobre algumas das dificuldades semelhantes que encontramos nos últimos meses de trabalho com o React Native.


O React Native adapta o Javascript para o desenvolvimento móvel. Isso é obtido pelo fato de ele usar vários coletores para construir projetos - o Metro Bundler, que interpreta o código JS e representa os recursos e o coletor do sistema de destino. No nosso caso, era um gradle para Android. Em teoria, o aplicativo React Native deve iniciar de maneira bastante simples. O comando react-native run-android ativa o Metro Bundler e cria o aplicativo para todos os dispositivos e emuladores Android conectados.


Na realidade, descobriu-se que mesmo nesta fase há dificuldades. Um erro "Não foi possível baixar o pacote JS" constantemente aparecia em nosso projeto, o que significava que o pacote não pôde traduzir o código no código nativo. Como se viu depois, devido ao fato de não ter iniciado. O StackOverflow confirmou a adivinhação e sugeriu que você execute o bundler em um encadeamento separado usando o comando react-native start. Isso permite que você reinicie o bundler apenas se o package.json tiver sido alterado, porque o procedimento não diminui muito o desenvolvimento.


Package.json é um arquivo que contém um conjunto de módulos externos para o aplicativo. No npmjs.com, há um grande número de bibliotecas diferentes para o React Native, expandindo a funcionalidade e simplificando o desenvolvimento. Muitas bibliotecas (por exemplo, Firebase) usam funções nativas e, portanto, devem ser associadas diretamente ao código nativo. Para fazer isso, use o comando <library-name> do link react-native, que deve configurar esses relacionamentos com o código nativo.


Devido ao fato de todas as bibliotecas serem gravadas em momentos diferentes, elas usam versões diferentes do SDK e exigem uma abordagem diferente. Às vezes acontece que as bibliotecas são incompatíveis entre si, ou a versão mais recente da biblioteca é experimental, e os próprios desenvolvedores aconselham fazer o downgrade para a penúltima. Frequentemente, o link não configura todas as dependências necessárias. Portanto, para a base de firmas mencionada acima, você precisa adicionar muitas bibliotecas adicionais no código nativo, conectar vários repositórios externos, modificar mainApplication.java (e isso é apenas para o Android!). Para o Firebase, há uma instrução bastante compreensível para executar essas ações, mas para outras bibliotecas nem sempre está presente.


Após a configuração das conexões com o código nativo, você pode criar o projeto na esperança de que a biblioteca conectada funcione. Ao montar, vale lembrar que, se você receber um erro, verifique se ele ocorreu precisamente por causa de suas ações, e não por um erro do coletor. Para total confiança, você deve executar a seguinte sequência de ações:


rmdir node_modules /s /q && npm cache clean - force && npm i 

Este comando excluirá a pasta node_modules e a recarregará. Essa é uma das tarefas mais longas, portanto, vale a pena usá-la extremamente raramente. Em alguns projetos, o node_modules pode ocupar vários gigabytes no disco rígido e, portanto, a reinstalação levará tempo.


 rmdir android/app/build /s /q 

Durante o desenvolvimento, percebeu-se que a compilação geralmente malsucedida é uma conseqüência do fato de o coletor não poder criar (ou excluir) uma pasta do diretório de depuração. Esta ação resolve o problema que reage e não pode excluir a pasta por conta própria. Mas, ao mesmo tempo, gerar arquivos para esta pasta do zero novamente levará um tempo extra.


 react-native start-reset-cache 

Inicie o Metro Bundler. Essa guia deve permanecer aberta durante todo o processo de depuração. Se ocorrer um erro, o log de erros pode aparecer aqui. Provavelmente, se ocorrer um erro, esse processo será encerrado e precisará ser reiniciado novamente.


 react-native run-android 

Instale o aplicativo em um dispositivo ou emulador conectado. A maioria dos erros de construção acontece aqui, e alguns deles são compreensíveis, mas alguns são bastante irracionais e são "curados" ao reiniciar todo o processo.


Imagine o processo de construção com uma sequência de comandos para um projeto (já tendo domínio, redux, navegação de reação, cerca de dez outras bibliotecas) depois de conectar o Firebase.


 react-native start react-native run-android >>    debug react-native run-android >> , metro bundler  react-native start react-native run-android >>    debug react-native run-android >>  !  metro bundler ,   JS-   react-native start >>   restart         -  

Escusado será dizer que leva muito tempo? E este não é um processo único: no momento descrito, esse procedimento era necessário após quase todas as alterações no código do programa. A cada nova biblioteca, o projeto se torna cada vez menos estável e esse processo pode mudar, na maioria das vezes para pior. Depurar um aplicativo é uma das funções mais importantes para um desenvolvedor e, nesse caso, sua velocidade diminui bastante.


Falando em depuração. O depurador do React Native tem problemas não apenas com o lançamento. A correção dos erros encontrados como resultado do teste também é um processo bastante doloroso. No react-native, o código JS é traduzido para o código nativo, mas é ofuscado durante a tradução. Portanto, se você não deseja ver erros como "exceção de ponteiro nulo em zzz.yyy ()", precisará usar o depurador embutido, não pode simplesmente ler exceções no logcat. Em caso de erro, o depurador exibe uma "tela da morte" vermelha com sua descrição, empurrando mais ou menos para o caminho da correção. Mas há problemas com esta parte.


Bem, quando o erro se parece com isso:



É realmente claro o que está acontecendo aqui - em vez do objeto esperado da matriz, this.state.noteArray.map é indefinido na variável, o que causa o notório TypeError. Você pode corrigi-lo acessando app.js: 14 e verificando o valor nessa variável antes de usar.


Pior quando o erro se parece com isso:



Então:



Ou então:



Imagens foram tiradas da Internet, mas as vimos ao vivo. E, apesar de serem mostrados em tempo de execução, esse erro não se deve ao fato de que algo foi feito incorretamente no seu código. Isso pode ter ocorrido porque você instalou a biblioteca incorretamente ou se suas importações têm dependências incompatíveis ou algo deu errado no código nativo e o React tenta capturar o erro. Cada erro é individual e é resolvido de maneira muito diferente. É bom que exista StackOverflow e pelo menos algum tipo de modo de depuração.


Pior ainda, quando um erro não é reproduzido na depuração. Encontramos essa situação ao tentar criar um aplicativo com uma nova versão do React com suporte para arquitetura x64 para Android. Ao instalar um aplicativo com um depurador, tudo funciona bem. Mas assim que construímos o testador no telefone, tudo para de funcionar e quebra assim que se trata de interagir com o banco de dados. Para depurar sem depuração às pressas, usamos mensagens do console, que nesse caso foram o componente react toastAndroid. Este componente exibe um texto breve para alcançar uma determinada linha de código. Metodicamente, preferencialmente dividindo o código pela metade, localizamos a função na qual o erro ocorre e descobrimos que o método Object.assign ({}, item) não funciona na nova versão do React. Foi uma sorte que você pudesse substituir essa função por um {... item} menor, mantendo a funcionalidade do aplicativo, mas a busca por esse erro custou cerca de uma dúzia de horas de trabalho.


Após um pequeno estudo foi realizado em busca de razões. Como se viu, o React Native usa mecanismos Javascript diferentes para interpretar o código JS nas versões de depuração e produção: para depurar o mecanismo JS do Chrome e no JavaScriptCore. Sim, o React Native não converte JavaScript em código nativo, mas interpreta à medida que é executado. Ao mesmo tempo, o mecanismo de depuração funciona muito mais estável e, portanto, os bugs estão cada vez mais entrando na produção. Por exemplo, este artigo mostra como a formatação da data funciona em diferentes condições. Voltando ao erro: depois de atualizar a versão React Native, o mecanismo da Web de produção e produção perdeu o suporte a Object.assign (). Mas o mecanismo de depuração permaneceu o mesmo.


Talvez a pior opção ocorra quando o aplicativo é interrompido em locais aleatórios, apenas na versão de produção e sem nenhum registro do React Native. Exemplo: após instalar a versão do aplicativo no telefone, ele "funciona por um tempo" e depois "desliga sem erro ou aviso em um momento aleatório". Além disso, o erro não é reproduzido em todos os dispositivos. No final, por tentativa e erro (e detectando que o mencionado Firebase Crashlytics não envia os erros correspondentes), conseguimos capturar os logs de queda que eram assim:



Este texto nem se aplica ao nosso aplicativo, nem foi marcado em vermelho. Porém, depois que chegamos e fomos aos fóruns, descobrimos que a nova versão do React Native está quebrada. E o anterior foi quebrado. No Issue Tracker oficial, o erro "Android trava: sinal 11 (SIGSEGV)" existe por dois meses e, para nossa sorte, dois dias antes de voltarmos para lá (!) Foi proposta uma solução experimental que corrigia o erro.


É irônico que alguns desenvolvedores que tiveram que lidar com o Android Studio não tenham certeza de que o IDE tenha opções como construir / limpar projeto ou arquivar / invalidar caches. Isso é necessário para se livrar do comportamento anormal do gradle, de falsas mensagens de erro e avisos, de erros de sincronização. Os desenvolvedores perguntaram: "por que devemos fazer o trabalho para o nosso IDE, em tais situações, esses comandos devem ser executados automaticamente". E eles podem ser entendidos, mas, ao mesmo tempo, os IDEs modernos fazem todo o trabalho difícil nos bastidores. E esses desenvolvedores simplesmente não funcionaram com o React Native.


Todos os itens acima são casos isolados que ocorreram nas últimas semanas. Aqui, não descrevemos a complexidade de executar aplicativos com a Expo, definindo o estilo do código em babel / eslint, não censuramos o Javascript por flexibilidade excessiva, não informamos como a depuração devido à ligação redux / região foi quase completamente perdida em um dos projetos. Considerando as dificuldades descritas de suporte e desenvolvimento e o fato de que para dois sistemas tudo se multiplica por dois, vale a pena considerar se o React Native é realmente rentável? Depois que concluímos nosso terceiro projeto nesse idioma, decidimos que não. O que você acha?

Source: https://habr.com/ru/post/pt468901/


All Articles