Capacitor vs React Native: bridging nativo para apps híbridos
1. Contexto e definições: o que são Capacitor e React Native?
Capacitor é um runtime nativo mantido pela equipe do Ionic que permite executar aplicações web (HTML, CSS, JavaScript) dentro de uma WebView nativa, expondo APIs do dispositivo por meio de um sistema de plugins. Sua proposta central é permitir que times web reutilizem todo o código front-end existente e adicionem funcionalidades nativas sob demanda, sem precisar aprender Swift, Kotlin ou Objective-C.
React Native (RN) é um framework criado pelo Facebook que traduz componentes React para widgets nativos reais. Diferente do Capacitor, RN não renderiza em uma WebView — ele usa uma bridge JavaScript ↔ Nativo para converter <View> em UIView (iOS) ou ViewGroup (Android). A experiência é mais próxima de um app nativo puro, mas exige conhecimento do ecossistema React e, em casos avançados, código nativo.
A diferença fundamental está na abordagem: web-first (Capacitor) vs nativo-first (React Native). O bridging em Capacitor é uma camada fina sobre a WebView; em RN, o bridging é o coração da arquitetura, responsável por serializar e desserializar chamadas entre os dois mundos.
2. Arquitetura do bridging: como cada um acessa APIs nativas
Capacitor — plugin system com JavaScript Bridge
Capacitor expõe APIs nativas por meio de um sistema de plugins que se comunicam via mensagens serializadas em JSON. Quando seu código JavaScript chama Camera.getPhoto(), o Capacitor Bridge serializa a chamada e a envia para o lado nativo, que executa a operação e retorna o resultado.
// Exemplo: plugin de câmera no Capacitor
import { Camera, CameraResultType } from '@capacitor/camera';
const photo = await Camera.getPhoto({
resultType: CameraResultType.Uri,
source: 'camera',
quality: 90
});
O bridging é síncrono para leitura de dados simples e assíncrono para operações pesadas. A latência é baixa para a maioria dos casos, mas apps com muitas chamadas nativas consecutivas podem sofrer com overhead de serialização.
React Native — bridge assíncrona e JSI
React Native tradicional usa uma bridge assíncrona onde cada chamada a um módulo nativo é serializada em JSON, enviada pelo batbridge, processada no lado nativo e retornada. Isso cria uma fila de mensagens que pode causar atrasos perceptíveis em animações.
Com a nova arquitetura (JSI — JavaScript Interface), a comunicação passou a ser direta, sem serialização. O JavaScript pode invocar funções C++ nativas de forma síncrona, eliminando o gargalo da bridge antiga.
// Exemplo: módulo nativo personalizado no React Native (JSI)
// No lado JavaScript:
import { NativeModules } from 'react-native';
const { MyNativeModule } = NativeModules;
const result = await MyNativeModule.heavyComputation(data);
Trade-offs: Capacitor tem latência previsível e baixa complexidade, mas flexibilidade limitada a plugins existentes. React Native oferece mais controle sobre performance (especialmente com JSI), mas exige conhecimento de C++/Java/Kotlin para bridging personalizado.
3. Experiência de desenvolvimento: fluxo de trabalho e ferramentas
Capacitor — CLI simples e hot reload via browser
O fluxo de trabalho com Capacitor é familiar para qualquer desenvolvedor web:
# Criar projeto web (React, Vue, Angular)
npm create vite@latest my-app -- --template react-ts
cd my-app
# Adicionar Capacitor
npm install @capacitor/core @capacitor/cli
npx cap init MyApp com.example.myapp
npx cap add android
npx cap add ios
# Desenvolvimento com hot reload
npx cap run android --livereload
O grande diferencial é poder depurar no navegador (Chrome DevTools) para 90% das funcionalidades, e apenas testar no dispositivo para recursos nativos. O hot reload via browser é instantâneo, sem necessidade de recompilar o app nativo.
React Native — Metro bundler e Expo vs bare workflow
React Native usa o Metro bundler, que empacota o JavaScript e gerencia o Fast Refresh. O fluxo varia entre Expo (abstração de configuração nativa) e bare workflow (controle total):
# Expo (recomendado para iniciantes)
npx create-expo-app my-rn-app
cd my-rn-app
npx expo start
# Bare workflow (controle total)
npx react-native init MyRnApp
cd MyRnApp
npx react-native run-android
Ferramentas de debugging: React Native usa Flipper (debugger nativo) ou React DevTools. O Fast Refresh é rápido, mas qualquer mudança em código nativo exige recompilação completa.
4. Performance e UX: quando cada um brilha (ou sofre)
Capacitor — limitado pela WebView
A renderização em WebView impõe métricas de performance web: LCP (Largest Contentful Paint), CLS (Cumulative Layout Shift) e INP (Interaction to Next Paint). Para apps com UI padrão (formulários, listas simples, CRUD), a performance é aceitável. Para animações complexas ou listas com milhares de itens, a WebView sofre com jank e memory leaks.
// Estratégia para melhorar performance no Capacitor
// Usar virtual scrolling com bibliotecas web
import { VirtualScroller } from 'virtual-scroller-library';
// Evitar manipulação direta do DOM em animações
// Preferir CSS transforms e opacity (GPU acelerados)
React Native — renderização nativa
Componentes RN como <View>, <Text>, <FlatList> são mapeados diretamente para widgets nativos. Animações com Animated API ou react-native-reanimated rodam na thread nativa ou na UI thread, sem bloquear a JavaScript thread. Listas com FlatList (virtualização nativa) mantêm 60fps mesmo com 10.000 itens.
Casos de uso ideais:
- Capacitor: MVPs, apps corporativos com UI simples, CRUDs, protótipos rápidos, apps que precisam de versão PWA
- React Native: apps com animações complexas (Tinder, Instagram), listas infinitas, jogos simples, apps que exigem interação nativa (gestos, transições)
5. Ecossistema de plugins e acesso a recursos nativos
Capacitor — plugins oficiais e comunidade
Capacitor oferece plugins oficiais para câmera, geolocalização, notificações push, biometria, armazenamento, entre outros. A comunidade Capacitor Community mantém dezenas de plugins adicionais:
# Instalar plugin oficial
npm install @capacitor/camera @capacitor/geolocation
# Plugin da comunidade
npm install @capacitor-community/barcode-scanner
Para criar um plugin personalizado, basta estender a classe CAPPlugin no lado nativo e registrar no JavaScript:
// Plugin nativo Android (Kotlin)
@CapacitorPlugin(name = "MyPlugin")
class MyPlugin : Plugin() {
@PluginMethod
fun doSomething(call: PluginCall) {
// Implementação nativa
call.resolve()
}
}
React Native — bibliotecas maduras e Expo Modules
React Native possui bibliotecas maduras como react-native-camera, react-native-maps, react-native-firebase. Com Expo, os módulos são pré-empacotados e testados. Para bridging personalizado, usa-se Turbo Modules (nova arquitetura):
// Expo Modules API (simplificado)
// my-module.ts
import { requireNativeModule } from 'expo-modules-core';
export default requireNativeModule('MyModule');
6. Integração com frameworks e suporte a PWA
Capacitor oferece suporte nativo a PWA: o mesmo código web pode ser distribuído como PWA (instalável via navegador) e como app nativo (via Google Play/App Store). Basta configurar o manifest.json e o service worker:
// capacitor.config.ts
const config = {
appId: 'com.example.app',
appName: 'MyApp',
webDir: 'dist',
server: {
androidScheme: 'https'
}
};
React Native não tem suporte a PWA. O foco é exclusivamente mobile nativo. Para ter PWA, seria necessário reescrever o app em React web separadamente.
Caso híbrido: um time web pode usar Capacitor para transformar um PWA existente em app nativo sem reescrever uma linha de código. Isso é impossível com React Native.
7. Cenários práticos: qual escolher em 2025?
Escolha Capacitor quando:
- Time é predominantemente web (React, Vue, Angular)
- App tem baixa complexidade nativa (formulários, leitura de dados, notificações)
- Necessidade de entregar PWA + app nativo com mesmo código
- Orçamento limitado para desenvolvimento nativo
Escolha React Native quando:
- Performance nativa é crítica (animações, listas grandes, processamento em background)
- Time já domina React e tem recursos para bridging personalizado
- App precisa de interações complexas com hardware (câmera em tempo real, AR, Bluetooth)
- Não há requisito de PWA
Decisão final — análise de custo-benefício:
| Critério | Capacitor | React Native |
|---|---|---|
| Curva de aprendizado | Baixa (web) | Média (React + nativo) |
| Performance UI | Média | Alta |
| Acesso nativo | Plugins | Total |
| Suporte PWA | Nativo | Nenhum |
| Manutenção | Simples | Complexa |
| Custo de time | Menor | Maior |
Para 2025, a tendência é que Capacitor ganhe espaço em empresas com times web, enquanto React Native mantém domínio em apps que exigem experiência nativa premium. A escolha correta depende do equilíbrio entre tempo de desenvolvimento, performance necessária e habilidades do time.
Referências
- Capacitor Documentation — Official Guide — Documentação oficial do Capacitor com guias de instalação, plugins e bridging nativo
- React Native — Architecture Overview — Explicação detalhada da bridge antiga, JSI, Turbo Modules e nova arquitetura
- Capacitor vs React Native: A Detailed Comparison (2025) — Artigo técnico da Ionic comparando desempenho, ecossistema e casos de uso
- React Native — Performance Tuning — Guia oficial de otimização de performance com FlatList, Animated e Hermes
- Capacitor Community Plugins — Repositório oficial da comunidade com dezenas de plugins nativos mantidos pela comunidade
- Expo vs Bare Workflow — React Native — Comparação entre Expo e bare workflow no ecossistema React Native
- PWA com Capacitor — Guia Prático — Tutorial oficial sobre como transformar PWA em app nativo usando Capacitor