Um web app depende de temporizadores, polling e sincronização para se manter vivo: o chat avança, os painéis atualizam, os uploads terminam, os tokens renovam. Dentro de um WebView esse contrato quebra no instante em que o app vai para segundo plano. O Android pausa o JavaScript quando a activity pausa; o pauseTimers() congela todos os temporizadores do processo; e no iOS, os próprios engenheiros da Apple confirmam que o JavaScript de um WKWebView "simplesmente pausa/congela" quando o app vai para segundo plano — por design. Não há Background Fetch, não há Background Sync, não há keep-alive no lado do WebView. Um runtime próprio do host oferece uma ponte real de tarefas em segundo plano: agendamento nativo, deltas enviados pelo servidor e pontos de verificação em primeiro plano, para que a experiência sobreviva ao app em segundo plano.
O app vai para segundo plano e a página escurece
No Android, WebView.onPause() pausa animações e geolocalização, e o ciclo de vida documentado o combina com pauseTimers(), que interrompe "todo o layout, parsing e temporizadores de JavaScript de todos os WebView" globalmente. Uma vez em segundo plano, os callbacks de setInterval, as retentativas de fetch e as tarefas longas deixam de disparar. No iOS a resposta é mais direta: um engenheiro de Frameworks nos fóruns da Apple diz que isso é "por design, pelas mesmas razões pelas quais qualquer app suspenso deixa de executar código", com apenas "alguns segundos" de tolerância desde o iOS 13. O WKWebView precisa ainda estar na hierarquia de views para executar JavaScript, e instâncias fora da tela ou em segundo plano simplesmente entram em idle.
Sem background fetch, sem background sync
As respostas da plataforma web para ficar offline e voltar — Background Fetch, Background Sync e Periodic Background Sync — estão ausentes dentro de um WebView. Mesmo quando um navegador independente as suporta, o WebView não as faz chegar ao sistema operacional. Assim, uma H5 que enfileira um upload falho para "tentar de novo quando houver rede" não tem nada para acordá-la; um chat que sonda a cada três segundos simplesmente para; uma renovação de token agendada com setTimeout dispara tarde ou nunca.
O que se perde quando a página congela
- Tempo real paralisa. Chat, presença e painéis ao vivo param de atualizar no instante em que o usuário troca de app.
- Uploads e sincronização abortam. Requisições em andamento e gravações em fila nunca terminam nem retentam.
- Tokens expiram em silêncio. Uma renovação agendada na página dispara horas tarde, após a sessão já ter morrido.
- Laços de retentativa morrem. Os temporizadores de backoff exponencial congelam; a recuperação só ocorre na próxima abertura.
- Sem garantia offline-first. A sincronização em segundo plano do Service Worker é indisponível no WebView (veja "Caixa Silenciosa"), e a página não compensa.
A solução do runtime
Um runtime próprio do host tira o trabalho em segundo plano da página. Ele oferece uma ponte de tarefas nativa abaixo do WebView: o host agenda trabalho delimitado via APIs de tarefas em segundo plano da plataforma, envia deltas à página em primeiro plano e grava pontos de verificação antes de suspender o app. A H5 mantém seus temporizadores para primeiro plano, mas o runtime garante que o trabalho realmente acontece — retomável, observável e não à mercê da pausa ociosa do motor.
| Dimensão | WebView | Runtime próprio do host |
|---|---|---|
| JS em segundo plano | Congelado por design | Agendamento nativo |
| Temporizadores (setInterval) | Param ao pausar | Ponte retoma em primeiro plano |
| Background Fetch / Sync | Indisponível | Deltas enviados pelo servidor |
| iOS WKWebView | Suspenso, segundos de tolerância | Tarefa do host, independente |
| Retentativa de upload / sync | Morre em segundo plano | Enfileirada + retomada |
| Ponto de verificação de estado | Nenhum | Ao suspender / retomar |
Uma aba de navegador pode confiar na plataforma para manter seu trabalho vivo. Um WebView puro não. Um runtime dá à página um segundo plano em que confiar — ir para a tela inicial não significa ficar no escuro.
Fontes
- Apple Developer Forums — Execução de JS no WKWebView em segundo plano — engenheiro da Apple: suspensão "por design".
- AOSP — Boas práticas do ciclo de vida do WebView (Cap. 45) — onPause/pauseTimers congelam todos os temporizadores JS.
- Stack Overflow — WKWebView não roda JavaScript em segundo plano — WebView precisa estar na hierarquia de views.
- MDN — Background Synchronization API — a solução web que o WebView não ponteia.
- Apache Cordova — JS em segundo plano pouco confiável no WKWebView — iOS pausa, Android não garante.