Como o Wails funciona
Entenda a arquitetura do Wails e como ela alcança desempenho nativo
Wails é um framework para criar aplicativos desktop usando Go no backend e tecnologias web no frontend. Porém, ao contrário do Electron, o Wails não inclui um navegador no pacote — ele usa a WebView nativa do sistema operacional.
Principais diferenças em relação ao Electron:
| Aspecto | Wails | Electron |
|---|---|---|
| Navegador | WebView fornecida pelo sistema operacional | Chromium incluído no pacote (~100 MB) |
| Backend | Go (compilado) | Node.js (interpretado) |
| Comunicação | Ponte em memória | IPC (entre processos) |
| Tamanho do pacote | ~15 MB | ~150 MB |
| Memória | ~10 MB | ~100 MB+ |
| Inicialização | <0.5s | 2-3 s |
Componentes principais
1. WebView nativa
O Wails usa o mecanismo de renderização web integrado ao sistema operacional:
WebView2 (Microsoft Edge WebView2)
- Baseada no Chromium (o mesmo mecanismo do navegador Edge)
- Pré-instalada no Windows 10/11
- Atualizações automáticas pelo Windows Update
- Compatibilidade total com os padrões web modernos
WebKit (mecanismo de renderização do Safari)
- Integrado ao macOS
- O mesmo mecanismo do navegador Safari
- Excelente desempenho e duração da bateria
- Compatibilidade total com os padrões web modernos
WebKitGTK (port do WebKit para GTK)
- Instalado pelo gerenciador de pacotes
- O mesmo mecanismo do GNOME Web (Epiphany)
- Boa compatibilidade com os padrões
- Leve e eficiente
Por que isso é importante:
- Nenhum navegador incluído no pacote → Aplicativo menor
- Nativo do sistema operacional → Melhor integração e desempenho
- Atualizações automáticas → Correções de segurança fornecidas pelas atualizações do sistema operacional
- Renderização familiar → A mesma do navegador do sistema
2. A ponte do Wails
A ponte é o núcleo do Wails — ela permite a comunicação direta entre Go e JavaScript.
Como funciona:
- O frontend chama um método Go (por meio de um binding gerado automaticamente)
- A ponte codifica a chamada em JSON (nome do método + argumentos)
- O roteador localiza o método Go nos serviços registrados
- O método Go é executado e retorna um valor
- A ponte decodifica o resultado e o envia de volta ao frontend
- A Promise é resolvida no JavaScript com o resultado
Características de desempenho:
- Em memória: sem sobrecarga de rede e sem HTTP
- Sem cópias quando possível (para grandes volumes de dados)
- Assíncrona por padrão: não bloqueia nenhum dos lados
- Com segurança de tipos: definições TypeScript geradas automaticamente
3. Sistema de serviços
Os serviços são a maneira recomendada de expor funcionalidades Go ao frontend.
// Define a service (just a regular Go struct)
type GreetService struct {
prefix string
}
// Methods with exported names are automatically available
func (g *GreetService) Greet(name string) string {
return g.prefix + name + "!"
}
func (g *GreetService) GetTime() time.Time {
return time.Now()
}
// Register the service
app := application.New(application.Options{
Services: []application.Service{
application.NewService(&GreetService{prefix: "Hello, "}),
},
})Descoberta de serviços:
- O Wails inspeciona sua struct durante a inicialização
- Os métodos exportados podem ser chamados pelo frontend
- As informações de tipos são extraídas para os bindings TypeScript
- O tratamento de erros é automático (erros Go → exceções JS)
Binding TypeScript gerado:
// Auto-generated in frontend/bindings/GreetService.ts
export function Greet(name: string): Promise<string>
export function GetTime(): Promise<Date>Por que usar serviços?
- Tipagem segura: suporte completo ao TypeScript
- Descoberta automática: não é necessário registrar métodos manualmente
- Organização: agrupe funcionalidades relacionadas
- Testabilidade: os serviços são apenas structs Go
4. Sistema de eventos
Os eventos permitem a comunicação por publicação/assinatura entre componentes.
Casos de uso:
- Comunicação entre janelas: uma janela notifica as demais
- Tarefas em segundo plano: o serviço Go notifica a interface sobre o progresso
- Sincronização de estado: mantenha várias janelas sincronizadas
- Baixo acoplamento: os componentes não precisam de referências diretas
Exemplo:
// Go: Emit an event
app.Event.Emit("user-logged-in", user)// JavaScript: Listen for event
import { Events } from '@wailsio/runtime'
Events.On('user-logged-in', (user) => {
console.log('User logged in:', user)
})Ciclo de vida da aplicação
Compreender o ciclo de vida ajuda você a saber quando inicializar e liberar recursos.
Hooks do ciclo de vida:
app := application.New(application.Options{
Name: "My App",
// Cleanly intercept quit requests (e.g. unsaved changes).
ShouldQuit: func() bool { return true },
// Called when the app is confirmed to be quitting — save state, close connections, etc.
OnShutdown: func() {},
})Não existe um campo OnStartup em application.Options. O trabalho de inicialização deve ficar no ServiceStartup(ctx, options) de um serviço, em um callback registrado por meio de app.Event.OnApplicationEvent(events.Common.ApplicationStarted, ...) ou simplesmente antes de app.Run().
Saiba mais sobre o ciclo de vida →
Processo de build
Entenda como o Wails faz o build da sua aplicação:
Etapas do build:
- Analisar o código Go
- Examinar os serviços em busca de métodos exportados
- Extrair os tipos dos parâmetros e dos valores de retorno
- Gerar assinaturas de métodos
- Gerar bindings TypeScript
- Criar arquivos
.tspara cada serviço - Incluir definições completas de tipos
- Adicionar comentários JSDoc
- Fazer o build do frontend
- Executar seu empacotador (Vite, webpack etc.)
- Minificar e otimizar
- Gerar a saída em
frontend/dist/
- Compilar o código Go
- Compilar com otimizações (
-ldflags="-s -w") - Incluir metadados do build
- Compilar especificamente para cada plataforma
- Incorporar os recursos
- Incorporar os arquivos do frontend ao binário Go
- Compactar os recursos
- Criar um único executável
Resultado: um único executável nativo com tudo incorporado.
Saiba mais sobre o processo de build →
Desenvolvimento vs. produção
O Wails se comporta de maneira diferente nos ambientes de desenvolvimento e produção:
Características:
- Recarregamento automático: as alterações no frontend são recarregadas imediatamente
- Mapas de código-fonte: depuração com o código-fonte original
- DevTools: as ferramentas de desenvolvimento do navegador ficam disponíveis
- Logs: logs detalhados ficam habilitados
- Frontend externo: servido pelo servidor de desenvolvimento (Vite)
Como funciona:
Benefícios:
- Retorno imediato sobre as alterações
- Recursos completos de depuração
- Iterações mais rápidas
Características:
- Recursos incorporados: o frontend é incluído no binário durante o build
- Otimizado: minificado e compactado
- Sem DevTools: desabilitadas por padrão
- Logs mínimos: somente erros
- Arquivo único: tudo em um único executável
Como funciona:
Benefícios:
- Distribuição em um único arquivo
- Tamanho menor (minificado)
- Melhor desempenho
- Sem dependências externas
Modelo de memória
Entender o uso da memória ajuda você a criar aplicações eficientes.
Regiões da memória:
- Heap do Go
- Seus serviços e o estado da aplicação
- Gerenciado pelo coletor de lixo do Go
- Normalmente 5-10MB para aplicações simples
- Memória do WebView
- DOM, heap do JavaScript e CSS
- Gerenciada pelo mecanismo do WebView
- Normalmente 10-20MB para aplicações simples
- Memória da ponte
- Buffers de mensagens para comunicação
- Sobrecarga mínima (<1MB)
- Cópia zero para grandes volumes de dados, quando possível
Dicas de otimização:
- Evite transferir grandes volumes de dados: passe IDs e busque os detalhes sob demanda
- Use eventos para atualizações: não faça polling no frontend
- Transmita arquivos grandes por streaming: não os carregue por completo na memória
- Remova os listeners: remova os listeners de eventos quando não forem mais necessários
Modelo de segurança
O Wails oferece uma arquitetura segura por padrão:
Recursos de segurança:
- Lista de métodos permitidos
- Somente métodos exportados podem ser chamados
- Métodos privados são inacessíveis
- É necessário registrar explicitamente os serviços
- Validação de tipos
- Os argumentos são verificados em relação aos tipos do Go
- Tipos inválidos são rejeitados
- Impede ataques de injeção
- Sem eval()
- O frontend não pode executar código Go arbitrário
- Somente métodos predefinidos podem ser chamados
- Sem execução dinâmica de código
- Isolamento de contexto
- Cada janela tem seu próprio contexto
- Os serviços podem verificar o contexto do chamador
- É possível definir permissões por janela
Práticas recomendadas:
- Valide a entrada do usuário no Go (não confie no frontend)
- Use o contexto para autenticação e autorização
- Sanitize os caminhos de arquivos antes das operações com arquivos
- Limite a frequência de operações custosas
Próximos passos
Ciclo de vida da aplicação - Entenda a inicialização, o encerramento e os hooks do ciclo de vida Saiba mais →
Ponte entre Go e frontend - Explore em detalhes como a ponte funciona Saiba mais →
Sistema de build - Entenda como o Wails compila sua aplicação Saiba mais →
Comece a desenvolver - Aplique em um tutorial o que você aprendeu Tutoriais →
Dúvidas sobre a arquitetura? Pergunte no Discord ou consulte a referência da API.