Desenvolvimento de Aplicações
Não existem regras rígidas e rápidas para o desenvolvimento das aplicações com o "Wails”, mas existem algumas orientações básicas.
Configurar Aplicação
O padrão usado pelos templates padrão é que main.go
é usado para configurar e executar a aplicação, enquanto app.go
é usado para definir a lógica da aplicação.
O arquivo app.go
definirá uma struct que tem 2 métodos que funcionam como hooks na aplicação principal:
type App struct {
ctx context.Context
}
func NewApp() *App {
return &App{}
}
func (a *App) startup(ctx context.Context) {
a.ctx = ctx
}
func (a *App) shutdown(ctx context.Context) {
}
O método
startup
é chamado assim que as Wails alocam os recursos de que precisa e é um bom lugar para a criação de recursos configurando ouvintes de eventos e qualquer outra coisa que o aplicativo precise na inicialização. É dado a ele umcontext.Context
que é geralmente salvo em um campo struct. Este contexto é necessário para chamar o runtime. Se este método retornar um erro, o aplicativo será encerrado. No modo de desenvolvimento, o erro será exibido no console.O método de
shutdown
será chamado pelo Wails logo no final do processo de encerramento. Este é um bom lugar para limpar memória e executar qualquer tarefa encerrada.
O arquivo main.go
geralmente consiste de uma única chamada para wails.Run()
, que aceita a configuração da aplicação. O padrão usado pelos templates é o antes da chamada para wails.Run()
, uma instância do struct definido no aplicativo app. o
é criado e salvo em uma variável chamada app
. Essa configuração é onde adicionamos os nossos callbacks:
func main() {
app := NewApp()
err := wails.Run(&options.App{
Title: "My App",
Width: 800,
Height: 600,
OnStartup: app.startup,
OnShutdown: app.shutdown,
})
if err != nil {
log.Fatal(err)
}
}
Mais informações sobre os hooks do ciclo de vida da aplicação podem ser encontradas aqui.
Métodos de vínculo
É provável que você queira chamar métodos Go do frontend. Isso normalmente é feito adicionando métodos públicos ao a struct já definida no app.go
:
type App struct {
ctx context.Context
}
func NewApp() *App {
return &App{}
}
func (a *App) startup(ctx context.Context) {
a.ctx = ctx
}
func (a *App) shutdown(ctx context.Context) {
}
func (a *App) Greet(name string) string {
return fmt.Sprintf("Hello %s!", name)
}
Na configuração principal do aplicativo, a tecla Bind
é onde podemos dizer aos Wails o que queremos vincular:
func main() {
app := NewApp()
err := wails.Run(&options.App{
Title: "My App",
Width: 800,
Height: 600,
OnStartup: app.startup,
OnShutdown: app.shutdown,
Bind: []interface{}{
app,
},
})
if err != nil {
log.Fatal(err)
}
}
Isso vinculará todos os métodos públicos em nosso App
de construção (isso nunca vinculará os métodos de inicialização e desligação).
Lidando com contexto quando vincular várias structs
Se você quiser vincular métodos para várias structs , mas deseja que cada structs mantenha uma referência ao contexto para que você possa usar as funções de tempo de execução, um bom padrão é passar o contexto do método OnStartup
para suas instâncias de construção :
func main() {
app := NewApp()
otherStruct := NewOtherStruct()
err := wails.Run(&options.App{
Title: "My App",
Width: 800,
Height: 600,
OnStartup: func(ctx context.Context){
app.SetContext(ctx)
otherStruct.SetContext(ctx)
},
OnShutdown: app.shutdown,
Bind: []interface{}{
app,
otherStruct
},
})
if err != nil {
log.Fatal(err)
}
}
Mais informações sobre isso podem ser encontradas aqui.
Menu da aplicação
O Wails suporta adicionar um menu à sua aplicação. Isso é feito passando uma struct de menu para a configuração da aplicação. É comum o uso de um método que retorna um Menu, e ainda mais comum que seja um método na struct App
usada para hooks de ciclo de vida.
func main() {
app := NewApp()
err := wails.Run(&options.App{
Title: "My App",
Width: 800,
Height: 600,
OnStartup: app.startup,
OnShutdown: app.shutdown,
Menu: app.menu(),
Bind: []interface{}{
app,
},
})
if err != nil {
log.Fatal(err)
}
}
Assets
A grande coisa do jeito que o Wails v2 lida com assets é que não o faz! A única coisa que você precisa fazer no Wails é um embed.FS
. A forma como se chega a isso depende inteiramente de você. Você pode usar arquivos html/css/js como o modelo vanilla. Você pode ter um sistema de compilação complicado, isso não importa.
Quando wails build
é executado, ele vai verificar o arquivo do projeto wails.json
na raiz do projeto. Há duas chaves no arquivo do projeto que são lidas:
- "frontend:install"
- "frontend:build"
O primeiro, se dado, será executado no diretório frontend
para instalar os módulos do Node. O segundo, se dado, será executado no diretório frontend
para realizar o build do projeto frontend.
Se essas duas chaves não são dadas, então as Wails não faz absolutamente nada com a frontend. É apenas esperando o embed.FS
.
AssetsHandler
Um aplicativo Wails v2 pode opcionalmente definir um http.Handler
nas opções options.App
, que permite o gancho do AssetServer criar arquivos em tempo real ou processe solicitações POST/PUT. Solicitações GET sempre são tratadas primeiramente pelos assets
FS. Se o FS não encontrar o arquivo solicitado, a solicitação será encaminhada para http.Handler
para servir. Qualquer requisição que não seja o GET será diretamente processada pelo AssetsHandler
se especificado. Também é usar apenas o AssetsHandler
por especificação é nil
como a opção Assets
.
Servidor de Desenvolvedor nativo
Executar wails dev
iniciará o servidor de desenvolvimento que também iniciará um observador de arquivos no seu diretório de projeto. Por padrão, se qualquer arquivo for alterado, verifica-se se era um arquivo da aplicação (padrão: .go
, configurável com -e
flag). Se foi, então ele irá reconstruir sua aplicação e reiniciá-la. Se o arquivo alterado estiver nos assets, emitirá uma recarga após um curto período de tempo.
O servidor de desenvolvimento utiliza uma técnica chamada "debwaring" que significa que não recarrega imediatamente, como pode haver vários arquivos alterados em um curto período de tempo. Quando um gatilho ocorre, ele espera por uma quantidade de tempo definida antes de emitir um recarregamento. Se outro gatilho acontecer, ele será redefinido para esperar novamente. Por padrão, esse valor é de 100ms
. Se este valor não funcionar para o seu projeto, ele pode ser configurado usando a flag -debounce
. Se usado, este valor será salvo na configuração do seu projeto e se tornará o padrão.
Servidor de Desenvolvedor Externo
Alguns frameworks vêm com seu próprio servidor ao vivo, no entanto, eles não serão capazes de tirar proveito das ligações Go/Wails. Neste cenário, é melhor executar um script de observador que reconstrui o projeto no diretório build, que Wails estará assistindo. Por exemplo, veja o modelo padrão do svelte que usa rollup. Para create-react-app, é possível usar este script para alcançar um resultado similar.
Go Module
Os modelos padrão do Wails geram um arquivo go.mod
que contém o nome do módulo "changeme". Você deve alterar isto para algo mais apropriado após a geração do projeto.