Chamar de «WebView» esconde o que ele é. Não é um retângulo barato que desenha seu HTML; é um motor de navegador completo carregado na memória —e uma app de tráfego que abre um por mini-programa hospedado está pagando o aluguel desse motor repetidamente. A conta chega como uma tela em branco, um reinício e um usuário que não volta.
Duas plataformas, o mesmo imposto
No Android, a própria documentação do Google é franca: WebView «tem uma pegada de memória significativa» porque é essencialmente um motor de navegador Chromium completo com uma arquitetura multiprocesso complexa. O conteúdo web roda em um processo renderizador isolado em sandbox; o processo do app apenas hospeda a view e a lógica do lado do navegador. No iOS, cada WKWebView levanta seu próprio processo WebContent. Como diz a empresa de confiabilidade móvel Embrace, criar um WebView significa «lançar outro aplicativo dentro do seu app móvel e adicionar dois processos extras». Não há economias de escala: um WebView são três processos do SO, dois são cinco, três são sete. Quantos mais você cria, mais lento —e mais perto de um kill.
Os números não são pequenos
Um WebView em branco não é de graça. As pegadas medidas colocam uma página em branco em cerca de 50–80 MB no Android e 50–70 MB no iOS; uma lista simples em 100–120 MB / 80–100 MB; uma página de detalhe de e-commerce em 150–200 MB no Android e 120–150 MB no iOS; uma tela de live-stream ou SPA em 180–300 MB. O exercício MemoryLab do Google mostra um processo renderizador saltando para cerca de 55 MB após apenas algumas alocações de JavaScript. Um teste de estresse documentado de uma plataforma de mini-programas descobriu que cada instância de WebView é um processo WebKit separado carregando uma base de 80–150 MB —«essa sobrecarga é da WebKit, não nossa, e nenhuma flag a torna menor».
O crash que você não consegue reproduzir
É aqui que vira um incidente de estabilidade. Naquele mesmo teste de estresse de mini-programas em um build de release de iPhone 15, um WebView em segundo plano ficou estável, cinco ficaram estáveis, mas dez foram jetsammed —mortos pelo sistema em cerca de um segundo, com a memória total do host em torno de 1,0–1,2 GB. A projeção é brutal em dispositivos pequenos: um iPhone SE (3ª ger, 4 GB) sustenta só um ou dois; um SE (2ª ger, 3 GB) sustenta zero ou um. No iOS, ultrapassar o limite de memória duro do processo WebContent faz o sistema matá-lo sem negociação —o usuário vê uma tela em branco. No Android, o assassino de pouca memória encerra o renderizador de forma independente, e sem tratamento você tem a mesma tela em branco ao voltar. A regra da Embrace: nunca mantenha mais de dois WebViews na memória para um carrossel. Para uma app de tráfego que hospeda centenas de telas de comerciantes, uma página pesada basta para dar OOM em todo o app —reinício forçado, sessão perdida, carrinho perdido, churn.
A solução do runtime
Um runtime de propriedade do host se recusa a levantar um motor de navegador completo para cada programa. Em vez de cada mini-programa ser seu próprio processo de WebView pesado, o runtime agrupa e recicla um conjunto limitado de views, compartilha um processo de renderização onde a plataforma permite, e dá ao programa leve comum —um checkout, um formulário, um cartão de conteúdo— uma pegada muito menor através de um único contexto de runtime compartilhado em vez de N motores independentes. O host impõe um orçamento de memória por mini-programa e em todo o catálogo, recicla instâncias em vez de vazá-las, e degrada com graça em vez de ser jetsammed. Uma página pesada de um comerciante deixa de poder levar o app inteiro junto.
| Dimensão | WebView | Runtime de propriedade do host |
|---|---|---|
| Custo por tela | Motor completo; 50–200+ MB cada | Runtime compartilhado; limitado, agrupado |
| Escalonamento | Sem economias; N motores = N× sobrecarga | Um contexto compartilhado; teto por programa |
| Pior caso | Jetsam / kill do renderizador → tela em branco | Orçamento imposto; degradação com graça |
| Raio de blast | App inteiro OOM por uma página pesada | Isolado por mini-programa |
| Ciclo de vida de instância | Vaza se não destruída à mão | Agrupada, reciclada pelo host |
O fio condutor desta série é o controle. Um WebView te deixa abrir uma tela mas entrega a conta de memória —e o crash— ao sistema operacional. Um runtime te deixa definir o orçamento você mesmo. Para uma plataforma cujo catálogo são centenas de páginas de terceiros, esse orçamento é a linha entre um app fluido e uma tela em branco em um telefone campeão de vendas.
Fontes
- Android Developers: WebView e memória — WebView é um motor Chromium completo com pegada significativa e um processo renderizador isolado em sandbox.
- Embrace: por que WKWebView é tão pesado e vaza — cada WebView lança outro app dentro do seu mais dois processos extras; sem economias de escala; limite carrosséis a dois.
- MentraOS: teste de estresse de WebView de mini-programas (10 WebViews jetsammed em ~1s) — cada instância é um processo WebKit separado com base de 80–150 MB; dispositivos tipo iPhone SE sustentam 0–2.
- Juejin: governança de memória WebView e OOM em produção — pegadas medidas por tipo de página; instância única 80–150 MB, complexo 200 MB+; teto duro do iOS mata o processo.
- iOS OOM治理: princípio Jetsam e otimização de pico de memória — o processo WebContent do WKWebView tem limite de memória mais estrito e é morto de forma independente, surgindo como tela em branco / crash para o usuário.