Tauri is a cross-platform framework that converts JavaScript or TypeScript code into a native application for virtually any operating system. While similar to Electron or React Native, Tauri can handle a wide range of front-end technologies. It is combined with the front-end to derive a native application for the required operating system.
Architecturally, Tauri runs the front-end application code alongside a Tauri process that builds the native application in parallel. As a result, you can develop the native app alongside the web app, and you can embed Rust calls into the native app to access the capabilities of the operating system. This is a hybrid process and gives Tauri much of her power; the development process remains exactly the same no matter which stack you use. Tauri simply decorates the existing process.
Tauri with SvelteKit
The process for developing a Tauri-enabled web application is to create or introduce the Rust plumbing along with the application code, and then run Tauri in web application development mode. It then runs the Tauri connector (the IPC, or Inter-Process Communication), starts the native app, and watches as the changes are reflected in the web app there. When you’re ready to deliver your application to production, you can create a release package for specific platform targets.
We will see the process to run Tauri against a SvelteKit application. Each stack has its own requirements, but the general steps are consistent.
First, we need to have Rust installed. Tauri uses Rust for its performance, cross-platform, and security features. rustc --version
it should return a response on your command line. To configure Rust, you can follow the configuration steps in the Tauri docs. remember to run rustup update
and verify the installation with rustc --version
.
Once Rust is available, you can assemble a new Tauri skin with npm create tauri-app
which requires you to have npm
installed. The Tauri quickstart describes other ways to install the Tauri framework for your application, such as using a shell script or Rust cargo. we will need npm
anyway for SvelteKit, so we’ll use it.
For our present purpose, once we have run npm create tauri-app
we can follow the indications, giving the project a name (mine is iw-tauri
). Next, you’ll specify a package manager (Yarn for this example), then the framework you’re using (SvelteKit). Once this is done, you can cd
in the new iw-tauri
directory and type yarn install
to install the packages, then yarn run dev
to start the development server.
Now if you visit localhost:1420 you will see the application with a screen like the one shown in Figure 1.
Figure 1. The SvelteKit front-end for a Tauri application.
Currently the screen only shows the SvelteKit app. To see Tauri’s magic in action, write npm run tauri dev
. That will launch both the SvelteKit app and the Tauri front-end as its twin Tauri Rust does. Tauri will generate a native window that reflects the same user interface as the web interface.
Note that the first time you do this, Tauri will install its dependencies, which will take a moment. Thereafter, the start will be fast.
As you write code and make changes, the native UI will automatically reflect them, as long as you’re using a development setup (such as SvelteKit) that automatically updates the development build.
How to create a Tauri app
Tauri works by running a native Rust app that watches the web app and reflects code changes there. In the previous section, we used npm create tauri-app
, which is a shortcut for the manual process of creating a Tauri application. The process consists of these steps:
- Create a front-end project using a framework like SvelteKit.
- Configure the front-end project to work with Tauri.
- Run the Tauri app.
- Set the Tauri app to view the front app.
In a manual process, we would also need to set framework-specific parameters in the front-end configuration step. In the case of SvelteKit, for example, we would have to make sure that the static adapter was used.
You can find the specific Tauri code in the /src-tauri
directory, which contains the tauri.conf.json
file to configure Tauri itself. You can look at the file create tauri-app
has been generated so we can get an idea of how it works and find more details here. Listing 1 contains a small portion of the Tauri configuration code.
Listing 1. A snippet of the Tauri configuration
{
"build": {
"beforeDevCommand": "yarn dev",
"beforeBuildCommand": "yarn build",
"devPath": "http://localhost:1420",
"distDir": "../build",
"withGlobalTauri": false
},
In Listing 1, you can see that the configuration tells Tauri what to do before running a build, which is basically: use yarn dev
to start the web app in development mode, then tell it where the app is running (localhost on port 1420).
For a video guide on developing native web-powered apps with Tauri, check out Tauri, a Rust-powered Electron alternative. Also see the Tauri guides for more information on how to manually set up a Tauri project.
Native calls from JavaScript
Tauri allows you to bind JavaScript calls to native functionality in Rust. The basic idea is to expose a Rust function as a Tauri command (in the src-tauri/src/main.rs
file), then Tauri makes it available as a JavaScript function that you can run in your web application. Here’s a quick look at the Tauri documentation:
Listing 2. Using a native JavaScript command
// In src-tauri/src/main.rs
#[tauri::command]
fn my_custom_command() {
println!("I was invoked from JS!");
}
// register the command:
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![my_custom_command])
.run(tauri::generate_context!())
.expect("failed to run app");
}
// In your JavaScript
import { invoke } from '@tauri-apps/api/tauri'
const invoke = window.__TAURI__.invoke
invoke('my_custom_command');
Listing 2 shows the basic outlines of using a native JavaScript command. There’s a lot more to the capability, but overall, it’s a good means of linking a web application to the operating system.
Tauri under the hood: Rust and WebViews
You should now have a general idea of how Tauri is presented together with the web application. The great thing about Tauri is the communication between the two components, which in Tauri is known as inter-process communication. Essentially, the two apps are isolated sandboxes that exchange messages. There are two types of messages: events and commands. Events are bi-directional, with a specific format that the Tauri JavaScript or TypeScript client uses to interact with the Tauri server.
The command protocol overlaps the event protocol. The command protocol is always initiated by the client-side application and works like a request and response interaction. It’s something like a remotely negotiated external function interface, via JSON-RPC (so the data should always be JSON serializable). It is not a true external function interface in the sense that all calls to the operating system are mediated by the remote procedure call, thus mitigating many of the security risks.
Tauri uses both Rust and WebViews to generate the native user interface. WebViews provide Tauri with a standardized and well-understood foundation from which to build the rest of its functionality. WebViews are native to the operating system, allowing for better performance than a secondary layer like Chromium.
Tauri uses a multi-threaded model for responsive user interface management. Essentially, Tauri spawns processes as needed to handle incoming commands and events from the client application. The Tauri main process creates threads with the specific permissions required. Each process has a lifetime dedicated solely to the job at hand.
Here is more information on how WebViews work. You can also check out the Tauri project on GitHub for Tauri’s Rust-based custom WebView engine. To get an idea of how much goes on behind the scenes with Tauri, take a deep dive into Tauri’s architecture.
Conclusion
Tauri is a framework similar to Electron and React Native. Each has its pros and cons, but the rapid adoption of Tauri by developers indicates that it’s doing a few things right. The decision to use native WebViews and Rust pays dividends in performance. Tauri is certainly a strong contender for new projects as well as existing web applications that need to be able to generate a native application.
Copyright © 2023 IDG Communications, Inc.
Be First to Comment