The Duel: React Native vs. Cordova
Publicados: 2022-03-11Como resultado dos smartphones e aplicativos móveis se tornarem tão populares, os desenvolvedores da Web têm procurado maneiras de criar aplicativos móveis usando JavaScript. Essa popularidade resultou no desenvolvimento de muitos frameworks JavaScript capazes de executar aplicativos nativos em dispositivos móveis. Atualmente, Cordova e React Native são as escolhas mais populares. O Cordova é compatível com as plataformas móveis iOS, Android e Windows Phone. Com React Native, por outro lado, Android, iOS e UWP são alvos para desenvolvedores. (UWP significa Plataforma Universal do Windows, plataforma da Microsoft que permite que o mesmo aplicativo seja executado no Windows Phone 10 Mobile, XBox One e Windows 10.)
Da superfície, parece que React Native e Cordova estão ocupando o mesmo espaço. No entanto, como em todas as tecnologias, há aspectos em que um brilha e o outro fica aquém. Portanto, para obter uma imagem melhor de cada tecnologia e aprender suas vantagens e armadilhas, vamos mergulhar nos detalhes de cada uma e compará-las em diferentes disciplinas.
Diferenças na filosofia
É importante lembrar que o slogan do React Native, “Aprenda uma vez, escreva em qualquer lugar” difere do mantra multiplataforma usual, “Escreva uma vez, execute em qualquer lugar”. Isso leva a duas coisas: Em primeiro lugar, não podemos simplesmente pegar nossa base de código React existente de nosso projeto da web e transformá-la em um aplicativo móvel com apenas alguns cliques. No entanto, React e React Native compartilham muitos conceitos-chave com um exemplo sendo seus sistemas de componentes e, como resultado, o React Native parece instantaneamente familiar. Embora o React compartilhe muitas semelhanças com o React Native, existem algumas diferenças principais, que vão desde a maneira como as folhas de estilo são tratadas até o tipo de componentes que podemos usar.
Em segundo lugar, podemos não conseguir compartilhar o código React Native ao segmentar diferentes plataformas. Isso acontece quando preferimos que os elementos da interface do usuário se comportem nativamente em sua plataforma específica, proporcionando ao usuário uma experiência melhor e uma sensação mais nativa do aplicativo. Um exemplo óbvio é o menu lateral da gaveta em aplicativos Android, que é muito incomum em aplicativos iOS.
Cordova não compartilha dessa filosofia. Não é incomum começar a desenvolver um aplicativo da Web puro, depois agrupá-lo como um aplicativo Cordova e reutilizar o máximo de código possível para todas as plataformas (móveis) que desejamos atingir.
Liberdade de Desenvolvimento
Em dispositivos móveis, o Cordova está executando um aplicativo de página única dentro do navegador da Web móvel integrado, chamado WebView, e o envolve como um aplicativo nativo. Embora pareça um aplicativo nativo do lado de fora, nosso código da Web está sendo executado dentro do mecanismo do navegador móvel. Para nós, isso significa que não estamos vinculados a uma biblioteca ou estrutura específica. Se estivermos usando JavaScript vanilla, jQuery, Angular ou qualquer outra coisa, qualquer uma dessas opções pode ser empacotada em um aplicativo móvel com o Cordova. Cordova não impõe em nossa pilha de tecnologia. Contanto que tenhamos um arquivo index.html
, estamos prontos. Um exemplo simples seria o seguinte trecho de código:
<html> <head> <title>My Cordova App</title> </head> <body> <div>Tap me</div> <script> // Select our element var element = document.getElementById('tapme'); // Send an alert once it was tapped/clicked element.addEventListener('click', function() { alert('Hello there!'); }); </script> </body> </html>
Este exemplo significa que podemos usar praticamente qualquer coisa que desejarmos, como usar um gerenciador de pacotes como NPM ou Bower, usar um transpilador como Babel, CoffeeScript ou TypeScript, um empacotador como Webpack ou Rollup, ou algo completamente diferente. Não importa, desde que o resultado seja um arquivo index.html
que carregue todo o JavaScript e folhas de estilo que precisamos.
O React Native, como o nome indica, baseia-se no React. É importante entender que a parte React no React Native é um de seus principais recursos. Se você não é fã da natureza declarativa do React, incluindo JSX, sua componentização e fluxo de dados, provavelmente você não ficará feliz com o React Native. Embora o React Native pareça instantaneamente familiar para os desenvolvedores do React, à primeira vista, existem algumas diferenças a serem lembradas. Com React Native não temos HTML ou CSS. Em vez disso, essa tecnologia está focada no lado do JavaScript. Como alternativa ao CSS, os estilos estão sendo escritos inline e o Flexbox é o modelo de estilo padrão.
O aplicativo React Native mais básico seria semelhante a este exemplo:
// Import the React module for JSX conversion import { React } from 'react'; // Import React Native's components import { View, Text, AppRegistry, TouchableOpacity, } from 'react-native'; // Create an App component const App = () => { // Define our press handler const onPress = () => alert('Hello there!'); // Compose the components we are going to render return ( <View> <TouchableOpacity onPress={onPress} /> <Text>Tap me!</Text> </TouchableOpacity> </View> ); }; // Registers the `App` component as our main entry point AppRegistry.registerComponent('App', () => App);
O React Native tem seu próprio empacotador. Ele agrupa todos os arquivos JavaScript em um arquivo gigante, que é então consumido e executado pelo JavaScriptCore, o mecanismo JavaScript da Apple. JavaScriptCore está sendo usado em iOS e Android, enquanto ChakraCore está alimentando aplicativos React Native UWP. Por padrão, o React Native usa o transpilador JavaScript Babel, permitindo-nos usar a sintaxe ECMAScript 2015+ (ECMAScript 6). Embora não seja necessário usar a sintaxe ECMAScript 2015+, é definitivamente recomendado, pois todos os exemplos oficiais e módulos de terceiros estão adotando-a. Como o React Native está cuidando do processo de empacotamento e transpilação, nosso código de aplicativo e módulos de terceiros podem aproveitar esses recursos sem a necessidade de configurar as ferramentas por conta própria.
Para resumir, o React Native é uma abordagem opinativa centrada no React para o desenvolvimento móvel, enquanto o Cordova nos permite agrupar tecnologias da Web dentro do shell do WebView.
Aparência e sensação nativas
Uma coisa que é importante para os usuários é ter uma aparência nativa de um aplicativo. Como os aplicativos Cordova geralmente são aplicativos da Web simples, há algumas coisas que podem parecer estranhas no início. Os problemas podem variar de falta de feedback visual nas áreas de toque, a rolagem que não parece tão suave como em aplicativos nativos, até um atraso de 300 milissegundos nos eventos de toque. Embora existam soluções para todos esses problemas, devemos lembrar que podemos precisar fazer um esforço extra se quisermos que nosso aplicativo Cordova pareça o mais próximo possível dos aplicativos nativos. Em Cordova, não temos acesso a nenhum controle nativo. Se quisermos ter uma aparência nativa, temos duas opções: recriar os controles nativos, como botões e elementos de entrada, com HTML e CSS, ou implementar módulos nativos que acessam diretamente esses controles nativos. Poderíamos fazer isso sozinhos ou usando uma biblioteca de terceiros, como Ionic ou Onsen UI. Observe que é importante mantê-los atualizados com as atualizações do sistema operacional à medida que elas surgem. Às vezes, a aparência de um sistema operacional móvel recebe um facelift, como aconteceu quando o iOS 7 foi lançado. Ter um aplicativo que não é capaz de adaptar tirará os usuários da experiência. Também poderíamos recorrer à inclusão de plugins Cordova que nos conectam ao lado nativo das coisas. Um dos controles nativos mais completos é a biblioteca Ace da Microsoft.
Com React Native, por outro lado, temos acesso a controles nativos e interação imediata. Componentes como Text
, TextInput
ou Slider
mapeiam para suas contrapartes nativas. Enquanto alguns componentes estão disponíveis para todas as plataformas, outros componentes funcionam apenas em plataformas específicas. Quanto mais próximo queremos que nosso aplicativo tenha uma aparência nativa, mais precisamos usar componentes que estão disponíveis apenas para essa plataforma específica e, portanto, mais nossa base de código diverge. As interações e gestos de toque mental também fazem parte do React Native.

Comparando o desempenho
Com o Cordova tendo apenas um WebView à sua disposição, estamos presos às limitações do WebView. Por exemplo, após sua versão 4.0, o Android finalmente começou a usar o mecanismo Chrome (muito mais rápido) como o WebView padrão. Enquanto com iOS, por muito tempo, o aplicativo executado dentro do mecanismo padrão do WebView foi significativamente mais lento do que o mesmo aplicativo no navegador móvel Safari. Além disso, como o JavaScript é de thread único, podemos ter problemas se houver muitas coisas acontecendo em nosso código de aplicativo. Essas limitações levam a animações lentas e nosso aplicativo pode não ser tão responsivo quanto gostaríamos que fosse. Embora possa haver alguns truques que podemos empregar aqui e ali, no final, estamos limitados aos limites do navegador móvel.
O React Native utiliza vários threads, portanto, renderizando elementos de interface do usuário executados em seu próprio thread. Como os componentes do React são vinculados a visualizações nativas, o JavaScript não está fazendo o trabalho pesado no React Native.
Fluxo de trabalho do desenvolvedor
O Cordova oferece um utilitário de linha de comando para criar novos modelos de projeto, iniciando o aplicativo no simulador e construindo o aplicativo para o dispositivo real em modo de produção. Na maioria das vezes, estamos desenvolvendo o aplicativo em um navegador de desktop e, posteriormente, podemos agrupá-lo como um aplicativo móvel. Com a liberdade que o Cordova oferece, precisamos lidar com o fluxo de trabalho de desenvolvimento por conta própria. Se quisermos recarregar ao vivo no dispositivo, precisamos implementá-lo nós mesmos. Para depurar aplicativos Cordova, aplicamos os mesmos princípios usados para depurar um site. No iOS, por exemplo, conectaríamos nosso dispositivo móvel via USB, abriríamos o Safari e suas ferramentas de desenvolvedor.
O React Native oferece uma interface de linha de comando semelhante e oferece um fluxo de trabalho de desenvolvimento familiar aos desenvolvedores da web. Recebemos recarga ao vivo fora da caixa. Uma vez que alteramos um componente React, nosso aplicativo recarrega com as alterações que fizemos. Um dos recursos mais interessantes é a substituição do módulo a quente, que recarrega parcialmente as alterações no componente que fizemos, sem alterar o estado do aplicativo. Poderíamos até nos conectar a um dispositivo real e ver se nossas alterações funcionam como esperávamos em um dispositivo real. Nossos aplicativos React Native podem ser depurados remotamente com o Chrome for Desktop. O tratamento de erros é óbvio no React Native; se encontrarmos um erro, nosso aplicativo exibirá um plano de fundo vermelho e o rastreamento de pilha será mostrado. Graças aos mapas de origem, podemos ver a localização exata do erro. Quando clicamos nele, nosso editor de escolha abre no local exato do código.
Extensibilidade e acesso aos recursos nativos
Do lado do JavaScript, somos livres para usar qualquer biblioteca JavaScript, incluindo pacotes do NPM. No entanto, como o React Native não é um ambiente de navegador, podemos achar difícil utilizar código que dependa do DOM. O React Native adota os módulos CommonJS e ES2015, portanto, qualquer biblioteca que use esses formatos é fácil de integrar.
Tanto o Cordova quanto o React Native têm a capacidade de criar e usar plugins que se conectam ao lado nativo das coisas. O Cordova fornece uma API de baixo nível para criar a nossa própria, o que nos dá muito controle, mas leva ao uso de mais clichês nativos e JavaScript.
Se fôssemos hipoteticamente escrever um plug-in Cordova iOS em Objective-C, ele poderia se parecer com o próximo trecho de código. Nosso plugin apenas registrará o parâmetro de entrada.
#import <Cordova/CDVPlugin.h> // Create a class that inherits from CDVPlugin @interface Log : CDVPlugin - (void)log:(CDVInvokedUrlCommand*)command; @end // The actual implementation of the class we just defined @implementation Log - (void)log:(CDVInvokedUrlCommand*)command { CDVPluginResult* pluginResult = nil; // We are getting all parameters and taking the first one NSString* echo = [command.arguments objectAtIndex:0]; // We are checking for the validity of the parameters if (echo != nil && [echo length] > 0) { // We are just printing the parameter using the native log method NSLog(echo); // Let's create a result for the plugin pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:echo]; } // Let's send a signal back with the plugin's result [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; } @end
Para usar o módulo, este pedaço de código JavaScript ajudará:
window.log = function(str, callback) { cordova.exec(callback, function(err) { callback('Nothing to echo.'); }, "Log", "log", [str]); };
Para usar o plugin, basta chamar a função log
:
window.log('Hello native!');
O React Native, por outro lado, segue uma filosofia diferente; ele mapeia automaticamente os tipos de JavaScript para suas contrapartes nativas ao escrever plugins, o que facilita a conexão de código nativo com JavaScript. Vamos dar uma olhada em um pedaço de código que é necessário para criar um módulo nativo com React Native:
#import "RCTBridgeModule.h" @interface Log : NSObject <RCTBridgeModule> @end @implementation Log RCT_EXPORT_MODULE(); // This makes this method available NativeModules.Log.log RCT_EXPORT_METHOD(log:(NSString *)message) { NSLog(message); } @end
React Native liga o módulo para nós com as chamadas RCT_EXPORT_MODULE
e RCT_EXPORT_METHOD
. Agora podemos acessá-lo com NativeModules.Log.log
assim:
import { React } from 'react'; import { View, Text, AppRegistry, NativeModules TouchableOpacity, } from 'react-native'; // Create an App component const App = () => { // Log with our module once we tap the text const onPress = () => NativeModules.Log.log('Hello there'); return ( <View> <TouchableOpacity onPress={onPress} /> <Text>Tap me!</Text> </TouchableOpacity> </View> ); }; // Registers the `App` component as our main entry point AppRegistry.registerComponent('App', () => App);
Embora tenhamos apenas examinado de perto a criação de um módulo no iOS usando Objective-C, os mesmos princípios se aplicam à criação de um módulo para Android usando Java.
Precisamos vincular plugins nativos dentro dos arquivos do projeto para cada plataforma. Com iOS, por exemplo, isso significa que devemos vincular a parte nativa compilada ao nosso aplicativo e adicionar os arquivos de cabeçalho correspondentes. Este pode ser um processo longo, especialmente se houver muitos módulos nativos. Felizmente, isso é significativamente simplificado usando um utilitário de linha de comando chamado rnpm que se tornou parte do próprio React Native.
Conclusão: Reagir Nativo ou Cordova?
React Native e Cordova têm propósitos diferentes e, portanto, atendem a necessidades diferentes. Portanto, é difícil dizer que uma tecnologia é melhor que a outra em todas as disciplinas.
Ao usar o Cordova, você pode transformar rapidamente seu aplicativo de página única existente em um aplicativo móvel para diferentes plataformas, ao custo de interações que não necessariamente têm a sensação nativa de sua plataforma específica.
Com o React Native, os aplicativos têm uma aparência mais nativa, mas ao custo de reimplementar pedaços de código para determinadas plataformas de destino. Se você já se interessou pelo React e está interessado em desenvolver aplicativos móveis, o React Native parece uma extensão natural.