Hello! If you have been following our articles, you may remember reading that Krater was being developed with Rust using Tauri. However, this is no longer the case because a few months ago we made the decision to migrate the entire project to Wails (Golang). In this article, we will discuss our experience and why we made such a risky decision to migrate an entire application from one language to another.
What is Krater?
Krater is a cross-platform application for debugging Laravel applications locally. The MoonGuard team is made up of developers who are passionate about the world of Laravel, and we have been working on creating solutions for those who develop and work with Laravel.
Krater was born out of our need as developers to have a customized tool that would provide a better debugging experience (locally) for Laravel applications or PHP projects. In the initial stage of Krater, we focused on defining, conceptualizing, and designing its features. This was the moment when we set the goal for Krater to be a product and a useful tool for anyone developing with Laravel.
We recommend reading this article if you want to learn even more about how and why we created a product like Krate
Our objectives in Krater are:
- Data persistence: we wanted the data to persist between programming sessions and even store data from multiple projects.
- Performance: we wanted Krater to be really fast and avoid memory crashes when processing data.
- Disk usage: Krater should be lightweight and occupy little disk space. Currently, it weighs around 18 MB.
- Memory usage: we don't want Krater to hang after receiving a large data from Laravel or when displaying multiple records on the window.
Tech and Framework Analysis
We wanted to create a cross-platform desktop application, so we focused on researching which technology was most suitable for development. At that time, we considered Electron, Wails, Flutter, Tauri, Neutralino, and many others. However, we ultimately concentrated on a solution based on web technologies (At MoonGuard, we have a preference for this approach).
In the team, we have experience working with Electron, but we knew beforehand that it would not provide us with the convenience we were looking for in developing Krater. We recognized that with Electron, we would not be able to achieve the performance, disk usage, and memory objectives for Krater. Therefore, Electron was ruled out from the beginning.
We visited this Github repository where we found an objective comparison between multiple frameworks. Here, we were able to compare the size of compilations, RAM usage of each technology, and compilation times across different test projects.
With Tauri, we observed that the size of the compilations was small but the compilation time was significantly higher than other technologies. This was the benchmark of the "01-empty-app" demo project:
Note: the demo test is using version 1.4 of Tauri.
The Elanis/web-to-desktop-framework-comparison repository was very useful for us to compare different technologies. If you are looking for a technology to create cross-platform apps using web technologies, it can be a good resource to consider.
From the available options, we chose Wails and Tauri for the following reasons:
- Based on web technologies.
- Frontend agnostic (allowing us to use React, Vue, Svelte, etc.).
- They meet the performance, persistence, and efficiency objectives for Krater.
After conducting this research, the next step was to validate the concept of Krater by creating two Proof of Concepts (POCs), one with Wails and another with Tauri.
After experimenting with both tests, we considered both technologies valid, and the decision came down to Tauri due to its better support, maintenance, and contribution on Github.
None of us had experience with Rust, and it was also our first encounter with Tauri. As a team, we took on the challenge of learning Rust and Tauri to develop the application.
Krater with Rust
Development with Krater was slow in the first few months, but by the third month, we started to have a better rhythm and understanding of the language to implement features. We improved our pace over time until we reached a crossroads.
The team agreed that we had a pleasant experience with Tauri, but we also acknowledged that some of us had discomfort and issues when working with Rust. Some of the aspects that posed challenges at that time were:
Understanding ownership transfer and management can be one of the most confusing and complex aspects of Rust. It is crucial to consider the program's execution flow and manage mutable and immutable variables in memory to avoid getting lost in the code. Mastering this, along with working with threads, was one of the most time-consuming tasks for the team.
Rust is a language with strong type safety, which acts as a shield against data in an unknown format and ensures code safety with the compiler. This strict feature can sometimes be uncomfortable when proposing a solution in code. We often heard the advice to start writing the code in a simple and flat manner and then structure it in a better way. This aspect occasionally limited our development and consumed time, making us question whether Krater as an application needed this level of security-restriction.
In this project, we used SQLite as our database, and finding a good ORM was a monumental task. We tried a wide range of crates, but none of them satisfied us. The most stable option at that time was Diesel; however, it did not fit our needs, and we also believe that the documentation could be better.
Rust and Tauri are relatively new projects that are currently gaining popularity, and finding good documentation, knowledge resources, or real-world examples can be challenging. In fact, one of the tutorials we offer on our blog cannot be found from any other source. This aspect will likely change over time because both Rust and Tauri have many contributors and passionate developers in their ecosystems.
We like to build software accompanied by unit tests because they are the life jacket that ensures the integrity of our projects. This was one of the most challenging tasks in terms of effort and time in the project. Several team members attempted it multiple times without success. I remember that we wanted to create mocks to test certain behaviors in our code, but we couldn't find good documentation or a guide on how to do it. It was extremely complicated.
Don't get us wrong, Tauri is an impressive and powerful toolkit for building applications, and Rust is a great programming language for creating fast and efficient software.
We had completed about 65% of the features in Krater, but the whole team was struggling to complete the remaining features (those that required Rust code). After facing this obstacle for weeks, we considered giving Wails with Golang a chance. The test was approved by the entire team because we were able to migrate almost all of our progress in just one weekend.
Krater with Golang
We understand that rewriting your entire application from scratch in another language is not an agile and pleasant decision, but we found that Golang easily adapted to the whole team. Surprisingly, coming from Laravel/PHP and writing code in Golang/Wails felt very natural to us.
Each of us has been able to understand this language more easily and in less time than working with Rust for months. Let's review the problems we mentioned before and how we resolved them:
Golang and Rust handle memory differently. Golang uses automated garbage collection to limit issues related to memory leaks. Its management is done at runtime, which can introduce certain additional costs. However, Golang offers Goroutines, which allow functions to run as threads, making concurrency easier.
Golang and Rust both offer type safety, both are statically typed, but Golang uses a garbage collector to manage memory (as mentioned earlier). Golang's type system is simpler compared to Rust's.
For this project, we found GORM, which is a really good ORM library. We used it to define tables, run migrations, delete records, and perform many other operations. It has comprehensive documentation with many examples.
Golang predates Rust by several years, which translates into the size and maturity of its community, as well as the breadth and depth of library documentation and resources. Along the way, we found that the documentation for Wails was also helpful, as well as some books as learning materials for the team.
Writing unit tests in Golang was simpler and easier to do. Golang provides built-in support for unit testing with the
testing package. We were also able to validate and create mock behavior for some of our objects in the code.
Krater is available!
After all these months of development, we managed to develop Krater 100% and reach its first stable version. We are very happy with working with both frameworks and the experience we have gained throughout this year in developing this product.
Before concluding the article, we want to share with each of our followers that they can try Krater for free with a 15-day trial!
This article was not written with the intention of seeking discussion or debate about frameworks or development languages. We wanted to share our experience working with many tools, frameworks, and languages. Our best advice to those who are on the path of creating their own products is to use tools that make them feel comfortable while working.
We want to thank the Tauri team for supporting the promotion of several of our Rust and Tauri articles on our blog on X (previously Twitter).
You can find us in our Discord community, where we will be sharing sneak peeks of upcoming features as well as development discussions. We look forward to seeing you there!
For the latest updates, breaking news, and important announcements, be sure to follow us on Twitter/X at @moonguard_dev. Stay connected and stay informed about all things MoonGuard.