Um WebView não é uma view; é um motor de navegador que precisa inicializar antes de desenhar. A primeira vez que seu app cria um, toda a pilha Chromium —biblioteca nativa, V8, processo de render, pilha de rede— é inicializada na thread de UI, bloqueando a entrada e arriscando um ANR. No Android essa primeira init leva 200–500 ms; no iOS, só o lançamento do processo WebContent pode travar dois segundos num dispositivo frio. E o pior: o motor é um componente do sistema atualizado independentemente via Play Store, então uma atualização pendente do WebView pode quebrar seu boot em silêncio. Um runtime próprio do host aquece, faz pool e gerencia a versão do motor em vez de deixar o SO te surpreender.
O primeiro WebView inicializa todo o motor
Diferente de um navegador, que pode já estar quente, o primeiro WebView de um app começa do zero. Os próprios documentos de desenvolvedor do Android alertam que esse boot implícito acontece inteiramente na thread principal e «aumenta drasticamente o risco de erros ANR». Internamente ele carrega libwebviewchromium.so (~50 MB), inicializa V8, faz fork do sandbox de render e sobe a pilha de rede. O custo medido de primeira init é 200–500 ms em Android de gama média; o Meituan mediu a primeira init do WKWebView no iOS em 763 ms (segunda: 457 ms) e no Android 193 ms. O custo é pago antes de carregar um único byte da sua página.
iOS: a travamento oculta de dois segundos
No iOS o gargalo real não é o objeto WebView —é o processo WebContent. Um relato de engenharia mediu uma lacuna de 1.999 ms entre webView.load() retornar e a navegação realmente começar, inteiramente por lançar o processo WebContent; o WebKit sobe um processo WebContent separado por instância de WKWebView, então o pré-aquecimento ingênuo sai pela culatra —acrescentou 2.797 ms de overhead em vez de economizar. Você não sai do isolamento de processos do WebKit pré-aquecendo.
A travamento por atualização do WebView do sistema
Como o WebView do Android é um app do sistema atualizado via Play Store, sua versão está fora do seu controle. Um dispositivo com uma atualização do WebView pendente ou parcialmente aplicada pode crashear ou travar o render quando seu app o toca pela primeira vez. O motor de que seu boot depende não é o que você testou —e você descobre no lançamento.
O band-aid: delay(300) fixo
Os desenvolvedores respondem com delay(300) antes de carregar, ou com inflação XML ansiosa que corre com a configuração do Chromium —ambos disfarçam a mesma verdade: você está pagando um imposto de boot de motor que não orçou, na rota crítica, sem garantia de quão grande ele é. Uma espera fixa é curta demais num dispositivo lento e longa demais num rápido; de qualquer forma o usuário encara um frame em branco.
A solução do runtime
Um runtime próprio do host trata o boot do motor como um recurso gerenciado. Ele aquece o motor fora da rota crítica, faz pool e reutiliza um conjunto limitado de views em vez de fazer fork de N motores, e fixa a versão do runtime para que uma atualização stray do sistema não quebre o boot. A página abre quando o usuário toca, não depois que o SO termina de inicializar um navegador.
| Dimensão | WebView | Runtime próprio do host |
|---|---|---|
| Primeira init | 200–500 ms na thread de UI (Android); 763 ms (iOS WKWebView) | Aquecido fora da rota crítica |
| Processo iOS | WebContent separado por instância; lançamento até ~2 s | Em pool, reutilizado, não fork por view |
| Versão do motor | Componente do sistema, via Play Store | Fixada pelo runtime |
| Risco de boot | ANR, travamento de render em atualização pendente | Controlado, determinístico |
| Padrão de mitigação | delay(300) band-aid, inflação XML ansiosa | Aquecimento gerenciado + pool limitado |
O fio condutor desta série é o controle. Um WebView faz seu app pagar um imposto de boot de navegador na rota crítica, a partir de um motor cuja versão você não escolhe nem conhece, de um tamanho que não pode prever. Um runtime transforma o boot do motor em um recurso que você agenda, faz pool e fixa. Para um catálogo de páginas alheias que precisam abrir na hora dentro do seu app, essa é a diferencia entre um toque que parece instantâneo e um toque que primeiro inicializa um navegador.
Fontes
- Android Developers — Otimizar o boot do WebView: boot implícito na thread de UI aumenta risco de ANR; use
startUpWebView(Jetpack Webkit 1.16.0) — orientação oficial para tirar a init do WebView da thread principal. - Internos do WebView (Tencent Cloud) — primeira init 200–500 ms: libwebviewchromium.so ~50 MB, V8 ~80 ms, fork de render ~100 ms — por que o pré-aquecimento do WebView é a primeira alavanca de performance.
- Meituan — Performance do WebView: primeira init WKWebView iOS 763 ms / segunda 457 ms; Android 193 ms primeiro — custo de init medido entre plataformas.
- Discussão catalyst-core — lançamento de WebContent até ~2 s; pré-aquecimento ingênuo acrescentou 2.797 ms; iPhone X 294 ms vs iPhone 17 Pro 8,8 ms — o isolamento de processos do WebKit não se contorna pré-aquecendo.