Voltar ao blog

Deixa o Electron, usa o Wails: aplicações desktop em Go em 2026

O Wails é a alternativa ao Electron para apps desktop em Go. Uma app vazia tem 8 a 11 MB, contra 295 a 384 MB. Vê onde ganha cada um.

Deixa o Electron, usa o Wails: aplicações desktop em Go em 2026

Se estás a construir uma ferramenta interna, um cliente de base de dados, um visualizador de logs ou qualquer aplicação desktop de pequena ou média dimensão, usa o Wails em vez do Electron. O Wails junta um backend em Go ao webview que o sistema operativo já traz, por isso uma aplicação vazia fica com cerca de 8 a 11 MB em vez de 295 a 384 MB (benchmark Elanis, 2026). Manténs o teu frontend web e trocas o Node pelo Go. O IPC escrito à mão dá lugar a bindings gerados, e não há Chromium embutido porque é o sistema operativo que fornece o webview. Ainda assim, o Wails não ganha todos os benchmarks, e há aplicações em que o Electron continua a ser a melhor escolha.

Resumo rápido

  • O tamanho é a vitória clara. Num benchmark de aplicações vazias feito em CI, as builds do Wails eram 30 a 40 vezes mais pequenas do que as do Electron no Windows, no macOS e no Linux (benchmark Elanis, 2026).
  • Na memória e no arranque, a vitória não é total. No mesmo benchmark, o Wails usou menos memória no macOS e no Linux, mas mais no Windows, e o Electron arrancou mais depressa nos três sistemas operativos.
  • As maiores vantagens são estruturais. Distribuis um único binário Go, escreves o backend com a biblioteca padrão e com goroutines do Go, chamas esse backend através de bindings gerados e tipados, e não corres Node na página.
  • Deixas de andar atrás das versões major do Electron. O Electron lança uma nova versão major a cada 8 semanas e só suporta as três mais recentes (Electron, 2026). Com o Wails, o webview é atualizado fora da tua aplicação: pelo atualizador do Evergreen WebView2 no Windows (Microsoft Learn, 2026), pelas atualizações do macOS e pelos pacotes da tua distribuição Linux.
  • O Electron continua a ser a escolha certa quando precisas de uma renderização Chromium idêntica em todo o lado, dependes de módulos nativos do Node ou já tens uma grande base de código em Electron.

O que é que o Electron traz em cada aplicação?

Cada aplicação Electron traz o seu próprio navegador e o seu próprio runtime de JavaScript. A documentação do Electron diz: «Ao embutir o Chromium e o Node.js no seu binário, o Electron permite-te manter uma única base de código JavaScript» para várias plataformas (documentação do Electron, 2026). Esse compromisso fazia sentido quando a alternativa eram três bases de código nativas. Mas também significa que cada aplicação que instalas traz uma cópia completa do Chromium.

O modelo de processos também vem do Chromium. Há um processo principal que corre Node.js, mais «um processo de renderização separado para cada BrowserWindow aberta (e para cada web embed)» (modelo de processos do Electron, 2026). A lógica do backend vive no processo principal, a interface vive nos processos de renderização, e ligas as duas partes com mensagens IPC que escreves à mão.

Depois há o calendário de lançamentos. «A cadência do Electron entre lançamentos de versões major é de 8 semanas», e só as três versões major estáveis mais recentes são suportadas (calendário do Electron, 2026). O Electron 44.0.0 passou a estável a 25 de agosto de 2026, com o Chromium M152 e o Node v24.18.1. O Electron 45 está previsto para 20 de outubro de 2026 (lançamentos do Electron, 2026). Para fazer chegar as correções de segurança do Chromium aos teus utilizadores, tens de continuar a publicar novas builds a esse ritmo.

Como funciona o Wails?

O Wails descreve-se como «uma alternativa leve e rápida ao Electron para Go» (documentação do Wails, 2026). Em vez de embutir um navegador, «reutiliza o motor de renderização nativo da plataforma». O README diz: «Usa motores de renderização nativos, sem navegador embutido!» (Wails no GitHub, 2026). O motor depende do sistema operativo:

  • No Windows, a interface é renderizada com o Microsoft WebView2.
  • No macOS, é renderizada com o WebKit.
  • No Linux, é renderizada com o WebKitGTK.

Uma aplicação Wails é «uma aplicação Go normal, com um frontend webkit» (Como funciona o Wails, 2026). O teu frontend (React, Svelte, Vue ou HTML simples) fica embutido no binário Go com //go:embed, por isso a aplicação inteira é distribuída como um único executável.

A ponte entre as duas metades é a opção Bind, que «especifica que métodos de structs expor ao frontend». Quando corres wails dev, o Wails lê esses métodos e gera wrappers em JavaScript e declarações em TypeScript. O frontend chama os métodos Go como se fossem funções assíncronas. Para enviar dados no sentido inverso, o Go emite eventos de runtime e o JavaScript fica à escuta.

O Wails v2 é a linha estável, e a v2.14.0 saiu a 10 de agosto de 2026 (lançamentos do Wails, 2026). O projeto tem licença MIT e cerca de 36,3 mil estrelas no GitHub. Entre as aplicações feitas com ele estão o Tiny RDM, uma interface gráfica para Redis com cerca de 13 mil estrelas (Tiny RDM, 2026), e o cliente gRPC Wombat (montra do Wails, 2026).

Wails vs Electron: quão mais pequena e leve fica a aplicação?

Muito mais pequena, mas nem sempre mais leve. Os melhores números públicos vêm da comparação de frameworks web-to-desktop da Elanis, que compila uma aplicação vazia em cada framework, em modo release, no CI do GitHub, e mede o tamanho, a memória e o arranque. Foi atualizada a 4 de setembro de 2026 (benchmark Elanis, 2026).

Gráfico de barras com o tamanho da build de uma aplicação vazia em Wails vs Electron por sistema operativo: Electron com cerca de 295 a 384 MB, Wails com cerca de 8 a 11 MB, Tauri com cerca de 3 a 5 MB

MétricaSistema operativoElectronWailsTauri
Tamanho da buildWindows x64~384 MB~11 MB~3 MB
Tamanho da buildmacOS arm64~319 MB~8 MB~5 MB
Tamanho da buildLinux x64~295 MB~9 MB~4 MB
MemóriaWindows x64~278 MB~323 MB~317 MB
MemóriamacOS arm64~369 MB~100 MB~95 MB
MemóriaLinux x64~586 MB~360 MB~94 MB
ArranqueWindows x64~206 ms~559 ms~711 ms
ArranquemacOS arm64~640 ms~1.740 ms~2.044 ms
ArranqueLinux x64~204 ms~263 ms~30.325 ms

Fonte: Elanis web-to-desktop-framework-comparison, atualizado a 2026-09-04. Aplicação vazia, build de release, CI do GitHub. Compara frameworks apenas dentro do mesmo sistema operativo. O README não indica as versões dos frameworks.

No tamanho, o Wails ganha sem discussão. Uma aplicação Wails vazia é cerca de 35 vezes mais pequena do que a do Electron no Windows, 40 vezes mais pequena no macOS e 33 vezes mais pequena no Linux. Numa ligação lenta de hotel, 11 MB descarregam-se em segundos e 384 MB demoram minutos. E a diferença acumula-se quando cada ferramenta num portátil traz o seu próprio Chromium.

A memória depende do sistema operativo. No macOS, o Wails usou cerca de 3,7 vezes menos memória do que o Electron. No Linux, usou cerca de 1,6 vezes menos. No Windows, usou mais: cerca de 323 MB contra os 278 MB do Electron. O benchmark não explica esta diferença, mas o WebView2 usa o motor do Microsoft Edge, que é baseado em Chromium, e corre os seus próprios processos de navegador. Por isso, no Windows é provável que continues a pagar um motor Chromium em memória, mesmo sem o distribuíres.

O Electron arrancou mais depressa em todos os sistemas neste benchmark. No Windows, abriu em cerca de 206 ms, contra os 559 ms do Wails. No macOS, a diferença foi de 640 ms contra 1.740 ms. No Linux, os dois ficaram próximos, com 204 ms contra 263 ms. Uma aplicação vazia num runner de CI dá apenas uma indicação aproximada e não corresponde ao que os teus utilizadores vão ver. Ainda assim, os dados não sustentam a ideia de que o Wails arranca sempre mais depressa.

Mais uma ressalva sobre o Windows. As aplicações Wails precisam do Microsoft WebView2 Runtime. Vem incluído no Windows 11, e a Microsoft diz que «a grande maioria dos dispositivos Windows 10 já tem o WebView2 Runtime instalado» (Microsoft Learn, 2026). Embutir o bootstrapper cobre os restantes casos e acrescenta cerca de 150 KB (guia do Wails para Windows, 2026). Mas se precisares de um motor com versão fixa, a Microsoft avisa que «os binários da Fixed Version têm mais de 250 MB e aumentam o pacote da tua aplicação nesse valor». Isso anula a maior parte da vantagem de tamanho no Windows.

Como é o código em Wails?

Imagina um pequeno visualizador de logs feito para a tua equipa: escolhe um ficheiro de log, mostra as últimas 200 linhas e depois vai mostrando as novas linhas à medida que são escritas. Também faz ping ao endpoint de health de um serviço. Tudo corre em Go, e o frontend limita-se a renderizar.

O lado Go é uma struct simples com métodos exportados. O TailLog lê um ficheiro com os e bufio. O CheckHealth chama um endpoint HTTP com um timeout usando net/http, que o curso de HTTP aborda. O código abaixo compila com o Wails v2.14.0:

example.gogo
// app.go
package main

import (
	"bufio"
	"context"
	"fmt"
	"net/http"
	"os"
	"sync"
	"time"
)

const tailLines = 200

type App struct {
	ctx        context.Context
	mu         sync.Mutex
	stopFollow context.CancelFunc
}

func NewApp() *App { return &App{} }

// startup is called by Wails once the app is running. Keep the context:
// runtime calls like EventsEmit need it.
func (a *App) startup(ctx context.Context) {
	a.ctx = ctx
}

// TailLog returns the last 200 lines of the log file at path.
func (a *App) TailLog(path string) ([]string, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, fmt.Errorf("open log: %w", err)
	}
	defer f.Close()

	lines := make([]string, 0, tailLines)
	sc := bufio.NewScanner(f)
	sc.Buffer(make([]byte, 0, 64*1024), 1024*1024) // allow long JSON log lines
	for sc.Scan() {
		if len(lines) == tailLines {
			lines = lines[1:]
		}
		lines = append(lines, sc.Text())
	}
	if err := sc.Err(); err != nil {
		return nil, fmt.Errorf("read log: %w", err)
	}
	return lines, nil
}

// CheckHealth calls a service's health endpoint and returns the status code.
func (a *App) CheckHealth(url string) (int, error) {
	ctx, cancel := context.WithTimeout(a.ctx, 3*time.Second)
	defer cancel()

	req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
	if err != nil {
		return 0, fmt.Errorf("build request: %w", err)
	}
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return 0, fmt.Errorf("health check %s: %w", url, err)
	}
	defer resp.Body.Close()
	return resp.StatusCode, nil
}

O main embute o frontend compilado e passa a struct ao Bind. O Wails v2 está em github.com/wailsapp/wails/v2:

example.gogo
// main.go
package main

import (
	"embed"
	"log"

	"github.com/wailsapp/wails/v2"
	"github.com/wailsapp/wails/v2/pkg/options"
	"github.com/wailsapp/wails/v2/pkg/options/assetserver"
)

//go:embed all:frontend/dist
var assets embed.FS

func main() {
	app := NewApp()

	err := wails.Run(&options.App{
		Title:  "Log Viewer",
		Width:  1100,
		Height: 720,
		AssetServer: &assetserver.Options{
			Assets: assets,
		},
		OnStartup: app.startup,
		Bind:      []interface{}{app},
	})
	if err != nil {
		log.Fatal(err)
	}
}

Corre wails dev e o Wails gera frontend/wailsjs/go/main/App.js e App.d.ts. As declarações ficam assim:

example.tsts
export function TailLog(arg1: string): Promise<Array<string>>;
export function CheckHealth(arg1: string): Promise<number>;

Cada método ligado devolve uma Promise. Se o método Go devolver um error diferente de nil, a Promise é rejeitada com esse erro. Assim, o frontend usa simplesmente await e try/catch:

example.tsts
import { TailLog, CheckHealth } from "../wailsjs/go/main/App";

async function openLog(path: string) {
  try {
    const lines = await TailLog(path);
    renderLines(lines);
  } catch (err) {
    showError(`Could not read ${path}: ${err}`);
  }
}

async function refreshStatus(url: string) {
  try {
    const status = await CheckHealth(url);
    setStatus(status === 200 ? "healthy" : `HTTP ${status}`);
  } catch (err) {
    setStatus(`down: ${err}`);
  }
}

Não tens de manter nomes de canais sincronizados nem de verificar formatos de mensagem à mão. Se mudares a assinatura de um método Go, a declaração regenerada muda com ela, e uma build do frontend com verificação de tipos assinala as chamadas desatualizadas.

Enviar novas linhas em streaming com eventos de runtime

É ao acompanhar um ficheiro em tempo real que a concorrência do Go dá jeito. O FollowLog salta para o fim do ficheiro e depois uma goroutine verifica periodicamente se há linhas novas e envia cada uma para o frontend com runtime.EventsEmit. Abrir outro ficheiro cancela o seguidor anterior:

example.gogo
// follow.go
package main

import (
	"bufio"
	"context"
	"fmt"
	"io"
	"os"
	"strings"
	"time"

	"github.com/wailsapp/wails/v2/pkg/runtime"
)

// FollowLog streams lines appended to path as "log:line" events.
func (a *App) FollowLog(path string) error {
	f, err := os.Open(path)
	if err != nil {
		return fmt.Errorf("open log: %w", err)
	}
	if _, err := f.Seek(0, io.SeekEnd); err != nil {
		f.Close()
		return fmt.Errorf("seek log: %w", err)
	}

	a.mu.Lock()
	if a.stopFollow != nil {
		a.stopFollow()
	}
	ctx, cancel := context.WithCancel(a.ctx)
	a.stopFollow = cancel
	a.mu.Unlock()

	go a.follow(ctx, f)
	return nil
}

func (a *App) follow(ctx context.Context, f *os.File) {
	defer f.Close()

	r := bufio.NewReader(f)
	var partial strings.Builder
	ticker := time.NewTicker(500 * time.Millisecond)
	defer ticker.Stop()

	for {
		select {
		case <-ctx.Done():
			return
		case <-ticker.C:
			for {
				chunk, err := r.ReadString('\n')
				partial.WriteString(chunk)
				if err != nil {
					break // no complete line yet, try again on the next tick
				}
				line := strings.TrimRight(partial.String(), "\r\n")
				runtime.EventsEmit(a.ctx, "log:line", line)
				partial.Reset()
			}
		}
	}
}

No frontend, subscreve uma vez com EventsOn:

example.tsts
import { FollowLog } from "../wailsjs/go/main/App";
import { EventsOn } from "../wailsjs/runtime/runtime";

EventsOn("log:line", (line: string) => appendLine(line));

await FollowLog("/var/log/payments-api/app.log");

No Electron, escreverias a mesma funcionalidade com fs no processo principal, um ipcMain.handle para a leitura, um webContents.send para cada linha nova e um script de preload que expõe ambos através do contextBridge. No Wails, é uma struct Go e um nome de evento. Esta versão não trata a rotação de logs. Um seguidor pronto para produção voltaria a abrir o ficheiro quando o tamanho diminuísse.

O Wails v3 muda um pouco o formato. Registas serviços em application.Options.Services com application.NewService(&LogService{}), e o frontend importa o código gerado de uma pasta bindings em vez de wailsjs (bindings do Wails v3, 2026). O frontend continua a chamar métodos de um tipo Go.

Em que difere o modelo de segurança?

A segurança do Electron depende de uma checklist, e o Wails parte de uma superfície mais pequena. O próprio guia de segurança do Electron pede-te que mantenhas a integração com Node desligada para conteúdo remoto (a predefinição desde a 5.0.0), mantenhas o isolamento de contexto ligado (predefinição desde a 12.0.0), mantenhas o sandboxing de processos ligado (predefinição desde a 20.0.0), valides o remetente de cada mensagem IPC, definas uma Content Security Policy e só exponhas APIs à página através do contextBridge (segurança do Electron, 2026).

Hoje essas predefinições são boas, mas cada uma é uma flag que o teu código pode desligar. E como cada aplicação traz o Chromium embutido, um bug do navegador fica na aplicação instalada até publicares uma atualização assente num Electron corrigido.

O Wails elimina vários desses pontos de raiz. Não há Node.js na página, por isso não há nodeIntegration para configurar mal. A página recebe os métodos Go que ligaste mais a API de runtime do Wails, e nada mais do anfitrião. Não consegue ler ficheiros nem lançar processos, a não ser que um dos teus métodos o faça. Como o webview pertence ao sistema operativo, as correções de segurança chegam através do runtime Evergreen WebView2, que se atualiza sozinho no Windows, das atualizações do macOS ou dos pacotes da tua distribuição Linux, e não através do teu pipeline de lançamentos. Se fixares um runtime Fixed Version no Windows, as correções voltam a ser responsabilidade tua.

Algum risco mantém-se. Cada método ligado é uma API, e a página que o chama pode renderizar conteúdo que não controlas. No visualizador de logs acima, o TailLog aceita qualquer caminho. Se a tua aplicação alguma vez mostrar HTML não confiável, isso passa a ser uma primitiva de leitura de ficheiros. Valida os argumentos em Go da mesma forma que validarias a entrada de um handler HTTP: restringe os caminhos a diretórios permitidos e os URLs a hosts conhecidos. Uma CSP também continua a importar, porque a página pode fazer pedidos de rede como qualquer página num navegador.

Sobre a questão relacionada do que uma dependência Node pode fazer no momento da instalação, lê O Go é mais seguro do que o Node.js na cadeia de fornecimento?.

Onde é que o Wails te sai caro?

O Wails troca um navegador embutido por três webviews diferentes, e isso tem custos. A Microsoft nota que, com o Evergreen WebView2 Runtime, deves preparar testes de compatibilidade futura, porque o motor é atualizado por baixo da tua aplicação (Microsoft Learn, 2026). No macOS estás a usar o WebKit, o motor do Safari, por isso testa lá qualquer CSS ou API web que só tenhas verificado no Chrome.

O Linux é a plataforma mais difícil. O guia do Wails para Linux enumera problemas conhecidos: o evento ended de vídeo não dispara por causa de um bug do WebKitGTK, podes ver "GStreamer element autoaudiosink not found", e «o WebKit instala handlers de sinais que interferem com o mecanismo de recuperação de panics do Go» (guia do Wails para Linux, 2026). Há também uma divisão de ABI. O Debian 11, o Ubuntu 20.04 e o RHEL 8 a 9 precisam do WebKitGTK 4.0 legado, por isso tens de escolher entre as build tags webkit2_41 e webkit2_40 (suporte a distribuições do Wails, 2026). Uma issue da v3 de fevereiro de 2026 reporta uma janela em branco no X11 com Nvidia, contornada com WEBKIT_DISABLE_DMABUF_RENDERER=1 (issue n.º 4985 do Wails, 2026).

Outros custos a ter em conta:

  • A v2 só tem uma janela. O guia de migração da v3 diz que a v2 «suportava apenas uma janela por aplicação», enquanto a v3 «introduz suporte nativo a múltiplas janelas como funcionalidade central» (guia da v2 para a v3 do Wails, 2026).
  • A v3 ainda está em beta. A mais recente é a v3.0.0-beta.25, de 22 de setembro de 2026. As notas de lançamento dizem que «a API é estável, mas podes ainda encontrar problemas antes do lançamento final da 3.0» (lançamentos do Wails, 2026). O guia de migração acrescenta que «a v2 continua a ser a versão estável atual».
  • O ecossistema é mais pequeno. Há menos plugins, e quando te deparas com um bug estranho é menos provável que alguém já tenha escrito a solução.
  • A documentação de migração é escassa. A página «from Electron» na documentação da v3 é, por agora, só um marcador de posição.

E o Tauri?

O Tauri é o outro grande framework baseado em webview. Descreve-se como «um framework para construir binários pequenos e rápidos para todas as principais plataformas desktop e móveis», usa «o web view que já está disponível no sistema de cada utilizador» e tem um backend em Rust (Tauri, 2026). O Tauri 2.0 passou a estável a 2 de outubro de 2024 (blog do Tauri, 2024).

No benchmark Elanis, o Tauri produziu as builds mais pequenas (cerca de 3 a 5 MB) e usou menos memória no Linux. Também teve o arranque mais lento em todos os sistemas operativos, incluindo cerca de 30 segundos no runner de CI em Linux. O Tauri e o Wails partilham os mesmos compromissos do webview, por isso a escolha resume-se sobretudo à linguagem do backend. Se a tua equipa escreve Rust, usa o Tauri. Se a tua equipa escreve Go, usa o Wails.

Como migrar uma aplicação Electron para o Wails?

Mantém o frontend e substitui o processo principal. O Wails ainda não tem um guia oficial de migração a partir do Electron, por isso planeia o trabalho fazendo corresponder cada peça do Electron ao seu equivalente em Go:

ElectronWails (Go)
ipcMain.handle + ipcRenderer.invoke via preloadMétodo exportado numa struct ligada, chamado a partir dos bindings gerados
fsos, io, bufio, path/filepath
child_processos/exec
fetch / axios no processo principalnet/http com um timeout de context
webContents.send + ipcRenderer.onruntime.EventsEmit + EventsOn
electron-builderwails build, com -nsis para um instalador Windows

Uma ordem prática:

  1. Move o frontend tal como está. Aponta o Wails para o output da tua build Vite ou webpack atual. A maioria dos componentes não precisa de mudar. Só mudam os pontos de chamada que falam com a API de preload, e o passo 2 trata deles.
  2. Porta um canal IPC de cada vez. Cada ipcMain.handle passa a ser um método Go. Apaga a entrada correspondente no preload e muda o ponto de chamada para o import gerado.
  3. Substitui as mensagens push por eventos. Tudo o que é enviado com webContents.send passa a runtime.EventsEmit.
  4. Refaz o empacotamento. O wails build compila «um binário pronto para produção», e flags como -nsis, -webview2 e -platform cobrem instaladores, a estratégia de WebView2 e compilação para outras plataformas (CLI do Wails, 2026). O guia de assinatura cobre a notarização no macOS e o SignTool no Windows, incluindo GitHub Actions.
  5. Testa nos três webviews. Este passo é trabalho novo em comparação com o Electron, por isso reserva tempo para ele.

O Go que escreves no passo 2 é sobretudo código da biblioteca padrão. Se os, net/http e encoding/json são novidade para ti, o curso de HTTP e o curso de formatos de dados cobrem as partes que um backend desktop usa.

Onde entra o LevelUpGo

O visualizador de logs acima assenta nos fundamentos do Go: funções, múltiplos valores de retorno, tratamento de erros e a biblioteca padrão. O curso Go Basics no LevelUpGo ensina-os com um editor a sério ao lado de cada lição, e o teu código tem de passar nos testes antes de avançares. O trabalho com goroutines e context no FollowLog é abordado em Concurrency Fundamentals. Quando quiseres praticar mais, o Training Ground tem exercícios independentes.

Se ainda estás a decidir se o Go vale o teu tempo, começa por Vale a pena aprender Go em 2026?. Para ver onde o Go já corre em produção, lê Onde é usado o Go?, e para o lado do servidor, Melhor linguagem de programação para backend.

Perguntas frequentes

O Wails é melhor do que o Electron?

Para a maioria das aplicações desktop pequenas e médias, sim. No benchmark Elanis, uma aplicação Wails vazia era 30 a 40 vezes mais pequena do que uma aplicação Electron (benchmark Elanis, 2026), e ficas com um backend em Go com bindings tipados. O Electron continua a ser melhor quando precisas de uma renderização Chromium idêntica ou de módulos nativos do Node.

O Wails usa menos memória do que o Electron?

Depende do sistema operativo. No mesmo benchmark, o Wails usou cerca de 100 MB contra os 369 MB do Electron no macOS, e 360 MB contra 586 MB no Linux. No Windows usou mais, cerca de 323 MB contra 278 MB, provavelmente porque o WebView2 usa o motor do Microsoft Edge, baseado em Chromium, e corre os seus próprios processos de navegador.

O Wails está pronto para produção?

O Wails v2 é a versão estável, e a v2.14.0 saiu a 10 de agosto de 2026 (lançamentos do Wails, 2026). Aplicações como o Tiny RDM correm sobre ele. O Wails v3 está em beta. A documentação diz que já há aplicações em produção com ele, mas aconselha a testar a fundo antes do deployment.

As aplicações Wails funcionam no Windows 10?

Sim, desde que o WebView2 Runtime esteja instalado. A Microsoft diz que a grande maioria dos dispositivos Windows 10 já o tem (Microsoft Learn, 2026). Para os restantes, o Wails pode embutir um bootstrapper ou descarregar o runtime durante a instalação, usando a flag de build -webview2.

Posso manter o meu frontend React ao passar para o Wails?

Sim. O Wails serve qualquer frontend web compilado a partir de ficheiros embutidos no binário Go, por isso React, Vue, Svelte e HTML simples funcionam todos. O que muda é a forma como o frontend fala com o backend. As chamadas IPC passam a ser imports de funções geradas, e as mensagens push passam a ser eventos de runtime.

Fontes

Escreve Go como um engenheiro sénior

Lições interativas no navegador. As primeiras são grátis.

Experimenta uma lição grátisOu cria uma conta gratuita