mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-02 18:29:53 +08:00
189 lines
6.2 KiB
Plaintext
189 lines
6.2 KiB
Plaintext
|
|
# Application Development
|
|
|
|
There are no hard and fast rules for developing applications with Wails, but there are some basic guidelines.
|
|
|
|
## Application Setup
|
|
|
|
The pattern used by the default templates are that `main.go` is used for configuring and running the application, whilst
|
|
`app.go` is used for defining the application logic.
|
|
|
|
The `app.go` file will define a struct that has 2 methods which act as hooks into the main application:
|
|
|
|
```go title="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) {
|
|
}
|
|
```
|
|
|
|
- The startup method is called as soon as Wails allocates the resources it needs and is a good place for creating resources,
|
|
setting up event listeners and anything else the application needs at startup.
|
|
It is given a `context.Context` which is usually saved in a struct field. This context is needed for calling the
|
|
[runtime](/docs/reference/runtime/intro). If this method returns an error, the application will terminate.
|
|
In dev mode, the error will be output to the console.
|
|
|
|
- The shutdown method will be called by Wails right at the end of the shutdown process. This is a good place to deallocate
|
|
memory and perform any shutdown tasks.
|
|
|
|
The `main.go` file generally consists of a single call to `wails.Run()`, which accepts the application configuration.
|
|
The pattern used by the templates is that before the call to `wails.Run()`, an instance of the struct we defined in
|
|
`app.go` is created and saved in a variable called `app`. This configuration is where we add our callbacks:
|
|
|
|
```go {3,9,10} title="main.go"
|
|
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)
|
|
}
|
|
}
|
|
|
|
```
|
|
|
|
More information on application lifecycle hooks can be found [here](/docs/howdoesitwork#application-lifecycle-callbacks).
|
|
|
|
## Binding Methods
|
|
|
|
It is likely that you will want to call Go methods from the frontend. This is normally done by adding public methods to
|
|
the already defined struct in `app.go`:
|
|
|
|
```go {16-18} title="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.Printf("Hello %s!", name)
|
|
}
|
|
```
|
|
|
|
In the main application configuration, the `Bind` key is where we can tell Wails what we want to bind:
|
|
|
|
```go {11-13} title="main.go"
|
|
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)
|
|
}
|
|
}
|
|
|
|
```
|
|
|
|
This will bind all public methods in our `App` struct (it will never bind the startup and shutdown methods).
|
|
|
|
More information on Binding can be found [here](/docs/howdoesitwork#method-binding).
|
|
|
|
## Application Menu
|
|
|
|
Wails supports adding a menu to your application. This is done by passing a [Menu](/docs/reference/menus#menu) struct
|
|
to application config. It's common to use a method that returns a Menu, and even more common for that to be a method on
|
|
the `App` struct used for the lifecycle hooks.
|
|
|
|
```go {11} title="main.go"
|
|
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
|
|
|
|
The great thing about the way Wails v2 handles assets is that it doesn't! The only thing you need to give Wails is an
|
|
`embed.FS`. How you get to that is entirely up to you. You can use vanilla html/css/js files like the vanilla template.
|
|
You could have some complicated build system, it doesn't matter.
|
|
|
|
When `wails build` is run, it will check the `wails.json` project file at the project root. There are 2 keys in the
|
|
project file that are read:
|
|
|
|
- "frontend:install"
|
|
- "frontend:build"
|
|
|
|
The first, if given, will be executed in the `frontend` directory to install the node modules.
|
|
The second, if given, will be executed in the `frontend` directory to build the frontend project.
|
|
|
|
If these 2 keys aren't given, then Wails does absolutely nothing with the frontend. It is only expecting that `embed.FS`.
|
|
|
|
## Built in Dev Server
|
|
|
|
Running `wails dev` will start the built in dev server which will start a file watcher in your project directory. By
|
|
default, if any file changes, wails checks if it was an application file (default: `.go`, configurable with `-e` flag).
|
|
If it was, then it will rebuild your application and relaunch it. If the changed file was in the `assetdir` directory,
|
|
it will issue a reload after a short amount of time.
|
|
|
|
The dev server uses a technique called "debouncing" which means it doesn't reload straight away,
|
|
as there may be multiple files changed in a short amount of time. When a trigger occurs, it waits for a set amount of time
|
|
before issuing a reload. If another trigger happens, it resets to the wait time again. By default this value is `100ms`.
|
|
If this value doesn't work for your project, it can be configured using the `-debounce` flag. If used, this value will
|
|
be saved to your project config and become the default.
|
|
|
|
## External Dev Server
|
|
|
|
Some frameworks come with their own live-reloading server, however they will not be able to take advantage of the Wails
|
|
Go bindings. In this scenario, it is best to run a watcher script that rebuilds the project into the build directory, which
|
|
Wails will be watching. For an example, see the default svelte template that uses [rollup](https://rollupjs.org/guide/en/).
|
|
For [create-react-app](https://create-react-app.dev/), it's possible to use
|
|
[this script](https://gist.github.com/int128/e0cdec598c5b3db728ff35758abdbafd) to achieve a similar result.
|
|
|
|
## Go Module
|
|
|
|
The default Wails templates generate a `go.mod` file that contains the module name "changeme". You should change this
|
|
to something more appropriate after project generation.
|