diff --git a/website/blog/2023-01-17-v3-roadmap.mdx b/website/blog/2023-01-17-v3-roadmap.mdx new file mode 100644 index 000000000..acd9a2603 --- /dev/null +++ b/website/blog/2023-01-17-v3-roadmap.mdx @@ -0,0 +1,225 @@ +--- +slug: the-road-to-wails-v3 +title: The Road to Wails v3 +authors: [leaanthony] +tags: [wails, v3] +--- + +```mdx-code-block +
+ +
+
+``` + +# Where are we now? + +It's been incredible to see the popularity of Wails rising since the v2 release. I'm constantly +amazed by the creativity of the community and the wonderful things that are being built with it. +With more popularity, comes more eyes on the project. And with that, more feature requests and +bug reports. + +Over time, I've been able to identify some of the most pressing issues facing the project. +I've also been able to identify some of the things that are holding the project back. + +This post is a summary of my thoughts on the future of Wails and what a v3 may look like. + +## Current issues + +The first thing I want to address is what I see as some of the current issues that +are holding the project back. I've identified the following as the most important: + +- The API +- Bindings generation +- The Build System + +### The API + +The API to build a Wails application currently consists of 2 parts: + +- The Application API +- The Runtime API + +#### The Application API + +The Application API famously has only 1 function: `Run()` which takes a heap of +options which govern how the application will work. Whilst this is very simple to use, +it is also very limiting. It is a "declarative" approach which hides a lot of the +underlying complexity. For instance, there is no handle to the main window, so you can't +interact with it directly. For that, you need to use the Runtime API. This is a problem +when you start to want to do more complex things like create multiple windows. + +#### The Runtime API + +The Runtime API provides a lot of utility functions for the developer. This includes: + +- Window management +- Dialogs +- Menus +- Events +- Logs + +There are a number of things I am not happy with the Runtime API. The first is that it +requires a "context" to be passed around. This is both frustrating and confusing for +new developers who pass in a context and then get a runtime error. + +The biggest issue with the Runtime API is that it was designed for applications that only +use a single window. Over time, the demand for multiple windows has grown and the API is +not well suited to this. + +### Thoughts on the v3 API + +Wouldn't it be great if we could do something like this? + +```go +func main() { + app := wails.NewApplication(options.App{}) + myWindow := app.NewWindow(options.Window{}) + myWindow.SetTitle("My Window") + myWindow.On(events.Window.Close, func() { + app.Quit() + }) + app.Run() +} +``` + + +This programmatic approach is far more intuitive and allows the developer to interact +with the application elements directly. All current runtime methods for windows would +simply be methods on the window object. For the other runtime methods, we could move +them to the application object like so: + +```go +app := wails.NewApplication(options.App{}) +app.NewInfoDialog(options.InfoDialog{}) +app.Log.Info("Hello World") +``` + +This is a much more powerful API which will allow for more complex applications to be built. +It also allows for the creation of multiple windows: + +```go +func main() { + app := wails.NewApplication(options.App{}) + myWindow := app.NewWindow(options.Window{}) + myWindow.SetTitle("My Window") + myWindow.On(events.Window.Close, func() { + app.Quit() + }) + myWindow2 := app.NewWindow(options.Window{}) + myWindow2.SetTitle("My Window 2") + myWindow2.On(events.Window.Close, func() { + app.Quit() + }) + app.Run() +} +``` + +### Bindings generation + +One of the key features of Wails is generating bindings for your Go methods so they may be +called from Javascript. The current method for doing this is a bit of a hack. It involves +building the application with a special flag and then running the resultant binary which +uses reflection to determine what has been bound. This leads to a bit of a chicken and egg +situation: You can't build the application without the bindings and you can't generate the +bindings without building the application. There are many ways around this but the best one +would be not to use this approach at all. + +There was a number of attempts at writing a static analyser for Wails projects but they +didn't get very far. In more recent times, it has become slightly easier to do this with +more material available on the subject. + +Compared to reflection, the AST approach is much faster however it is significantly more +complicated. To start with, we may need to impose certain constraints on how to specify +bindings in the code. The goal is to support the most common use cases and then expand +it later on. + +### The Build System + +Like the declarative approach to the API, the build system was created to hide the +complexities of building a desktop application. When you run `wails build`, it does a +lot of things behind the scenes: +- Builds the backend binary for bindings and generates the bindings +- Installs the frontend dependencies +- Builds the frontend assets +- Determines if the application icon is present and if so, embeds it +- Builds the final binary +- If the build is for `darwin/universal` it builds 2 binaries, one for `darwin/amd64` and one for `darwin/arm64` and then creates a fat binary using `lipo` +- If compression is required, it compresses the binary with UPX +- Determines if this binary is to be packaged and if so: + - Ensures the icon and application manifest are compiled into the binary (Windows) + - Builds out the application bundle, generates the icon bundle and copies it, the binary and Info.plist to the application bundle (Mac) +- If an NSIS installer is required, it builds it + +This entire process, whilst very powerful, is also very opaque. It is very difficult to +customise it and it is very difficult to debug. + +To address this in v3, I would like to move to a build system that exists outside of Wails. +After using [Task](https://taskfile.dev/) for a while, I am a big fan of it. It is a great +tool for configuring build systems and should be reasonably familiar to anyone who has used +Makefiles. + +The build system would be configured using a `Taskfile.yml` file which would be generated +by default with any of the supported templates. This would have all of the steps required +to do all the current tasks, such as building or packaging the application, allowing for +easy customisation. + +There will be no external requirement for this tooling as it would form part of the Wails +CLI. This means that you can still use `wails build` and it will do all the things it does +today. However, if you want to customise the build process, you can do so by editing the +`Taskfile.yml` file. It also means you can easily understand the build steps and use your +own build system if you wish. + +The missing piece in the build puzzle is the atomic operations in the build process, such +as icon generation, compression and packaging. To require a bunch of external tooling would +not be a great experience for the developer. To address this, the Wails CLI will provide +all these capabilities as part of the CLI. This means that the builds still work as expected, +with no extra external tooling, however you can replace any step of the build with any tool +you like. + +This will be a much more transparent build system which will allow for easier customisation +and address a lot of the issues that have been raised around it. + +## The Payoff + +These positive changes will be a huge benefit to the project: +- The new API will be much more intuitive and will allow for more complex applications + to be built. +- Using static analysis for bindings generation will be much faster and reduce a lot + of the complexity around the current process. +- Using an established, external build system will make the build process completely + transparent, allowing for powerful customisation. + +Benefits to the project maintainers are: + +- The new API will be much easier to maintain and adapt to new features and platforms. +- The new build system will be much easier to maintain and extend. I hope this will lead to a new ecosystem of community driven build pipelines. +- Better separation of concerns within the project. This will make it easier to add new features and platforms. + +## The Plan + +A lot of the experimentation for this has already been done and it's looking good. +There is no current timeline for this work but I'm hoping by the end of Q1 2023, there +will be an alpha release for Mac to allow the community to test, experiment with and +provide feedback. + +## Summary + +- The v2 API is declarative, hides a lot from the developer and not suitable for features such as multiple windows. A new API will be created which will be simpler, intuitive and more powerful. +- The build system is opaque and difficult to customise so we will move to an external build system which will open it all up. +- The bindings generation is slow and complex so we will move to static analysis which will remove a lot of the complexity the current method has. + +There has been a lot of work put into the guts of v2 and it's solid. +It's now time to address the layer on top of it and make it a much better experience for the developer. + +I hope you are as excited about this as I am. I'm looking forward to hearing your thoughts and feedback. + +Regards, + +‐ Lea + +PS: If you or your company find Wails useful, please consider [sponsoring the project](https://github.com/sponsors/leaanthony). Thanks! +PPS: Yes, that's a genuine screenshot of a multi-window application built with Wails. It's not a mockup. It's real. It's awesome. It's coming soon. \ No newline at end of file diff --git a/website/static/img/blog/multiwindow.webp b/website/static/img/blog/multiwindow.webp new file mode 100644 index 000000000..746a1d7f2 Binary files /dev/null and b/website/static/img/blog/multiwindow.webp differ