#desktop-applications #web-gui #cross-platform-gui #gui-applications

web-view

Rust bindings for webview, a tiny cross-platform library to render web-based GUIs for desktop applications

24 releases

Uses old Rust 2015

0.7.3 Feb 23, 2021
0.7.2 Dec 9, 2020
0.7.1 Nov 13, 2020
0.6.3 Jun 4, 2020
0.1.3 Feb 1, 2018

#244 in Rendering

Download history 382/week @ 2024-07-20 523/week @ 2024-07-27 328/week @ 2024-08-03 397/week @ 2024-08-10 262/week @ 2024-08-17 324/week @ 2024-08-24 294/week @ 2024-08-31 342/week @ 2024-09-07 258/week @ 2024-09-14 307/week @ 2024-09-21 422/week @ 2024-09-28 138/week @ 2024-10-05 169/week @ 2024-10-12 224/week @ 2024-10-19 230/week @ 2024-10-26 241/week @ 2024-11-02

879 downloads per month
Used in 16 crates (15 directly)

MIT license

410KB
3.5K SLoC

C 1.5K SLoC // 0.0% comments Rust 1K SLoC // 0.0% comments C++ 516 SLoC // 0.0% comments

web-view   .github/workflows/ci.yml Latest Version

Important: requires Rust 1.30 stable or newer.

This library provides a Rust binding to the original implementation of webview, a tiny cross-platform library to render web-based GUIs as desktop applications.

screenshot

Two-way binding between your Rust and JavaScript code is made simple via the external JS object and webview.eval Rust function. We have full working examples, but the core is as follows:

// ... Simplified for the sake of brevity.
web_view::builder()    
    .invoke_handler(|webview, arg| {
        match arg {
            "test_one" => {
                // Do something in Rust!
            }
            "test_two" => {
                // Invoke a JavaScript function!
                webview.eval(&format!("myFunction({}, {})", 123, 456))
            }
            _ => unimplemented!(),
        };
    })
// Executes our "invoke_handler" - passing the value "test_one" as the second parameter.
external.invoke('test_one');

// Executes our "invoke_handler", which in turn calls "myFunction" below.
external.invoke('test_two');

function myFunction(paramOne, paramTwo) {
    console.log(paramOne);
    console.log(paramTwo);
}

In addition, by relying on the default rendering engine of the host Operating System, you should be met with a significantly leaner binary to distribute compared to alternatives such as Electron which have to bundle Chromium with each distribution.

You should also see comparatively less memory usage, and this section will be updated with benchmarks to highlight this in due course.

Finally, the supported platforms and the engines you can expect to render your application content are as follows:

Operating System Browser Engine Used
Windows MSHTML or EdgeHTML
Linux Gtk-webkit2
OSX Cocoa/WebKit

Note: by default the MSHTML (IE) rendering engine is used to display the application on Windows. If you want to make use of EdgeHTML (Edge) then you'll need to enable it with a feature switch (see the installation and configuration section).

Prerequisites

If you're planning on targeting Linux you must ensure that Webkit2gtk is already installed and available for discovery via the pkg-config command.

If you skip this step you will see a similarly formatted error message as below informing you of what's missing:

Compiling webview-sys v0.3.3
error: failed to run custom build command for `webview-sys v0.3.3`
Caused by:
process didn't exit successfully: `/home/username/rust-projects/my-project/target/debug/build/webview-sys-9020ddaf41e4df7d/build-script-build` (exit code: 101)
--- stderr
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Command { command: "\"pkg-config\" \"--libs\" \"--cflags\" \"webkit2gtk-4.0\" \"webkit2gtk-4.0 >= 2.8\"", cause: Os { code: 2, kind: NotFound, message: "No such file or directory" } }', src/libcore/result.rs:1165:5

Installation and Configuration

Let's start off with the basic Rust application. Run cargo new my-project in a shell of your choice and change into the my-project directory.

As this library can be found as a crate on the Rust Community Registry all you have to do to add this as a dependency is update your Cargo.toml file to have the following under its dependencies section:

[dependencies]
web-view = { version = "0.7" }

If you want to make use of Edge on Windows environments, you will need to have Windows 10 SDK installed through Visual Studio Installer and you'll need to use the following syntax instead:

[dependencies]
web-view = { version = "0.7", features = ["edge"] }

Now let's write some Rust code that makes use of the library. Open up the main.rs file in an editor of your choice:

vim src/main.rs

And replace the contents with the following:

use web_view::*;

fn main() {
    let html_content = "<html><body><h1>Hello, World!</h1></body></html>";
	
    web_view::builder()
        .title("My Project")
        .content(Content::Html(html_content))
        .size(320, 480)
        .resizable(false)
        .debug(true)
        .user_data(())
        .invoke_handler(|_webview, _arg| Ok(()))
        .run()
        .unwrap();
}

You should now be able to run cargo build and see something similar to the output below:

$ cargo build
Updating crates.io index
Compiling pkg-config v0.3.17
Compiling cc v1.0.47
Compiling boxfnonce v0.1.1
Compiling urlencoding v1.0.0
Compiling webview-sys v0.3.3
Compiling web-view v0.5.4
Compiling my-project v0.1.0 (C:\Users\Username\source\rust-projects\my-project)
Finished dev [unoptimized + debuginfo] target(s) in 8.36s

Assuming you get a successful build all you have to do now is run it with: cargo run. Hopefully you'll see the same as below:

screenshot

For more usage info please check out the examples and the original README.

Known Issues and Limitations

  • Edge feature switch not working on Windows 10 if run as Administrator. This was the root cause of the issue raised in #96 and is the result of a bug in Microsoft.Toolkit.Win32 which is tracked here.

  • Edge sandbox restrictions. If you decide to make use of an embedded Web Server to return your content you will need to run the following command to bypass the restriction that prevents communication with localhost:

    $ # Requires administrative privileges.
    $ CheckNetIsolation.exe LoopbackExempt -a -n="Microsoft.Win32WebViewHost_cw5n1h2txyewy"
    

    This is usually used with Windows IoT Core, when allowing TCP/IP connections between two processes. You can read some more about this in the Microsoft Documentation here.

  • IE rendering content in a legacy, compatibility format. By default, content rendered inside a Web Browser Control will be done so in compatibility mode (specifically IE7). To get round this on Windows systems where Edge is not available you can force the use of the highest version of IE installed via a Registry tweak.

Suggestions

  • If you like type safety, write your frontend in Elm or PureScript*, or use a Rust frontend framework that compiles to asm.js, like yew.
  • Use parcel to bundle & minify your frontend code.
  • Use inline-assets to inline all your assets (css, js, html) into one index.html file and embed it in your Rust app using include_str!().
  • If your app runs on windows, add an icon to your Rust executable to make it look more professional™
  • Use custom npm scripts or just or cargo-make to automate the build steps.
  • Make your app state persistent between sessions using localStorage in the frontend or rustbreak in the backend.
  • Btw, instead of injecting app resources via the js api, you can also serve them from a local http server (e.g. bound to an ephemeral port).
  • Happy coding :)

* The free PureScript By Example book contains several practical projects for PureScript beginners.

Contribution opportunities

  • Create an issue for any question you have
  • Docs
  • Feedback on this library's API and code
  • Test it on non-windows platforms, report any issues you find
  • Showcase your app
  • Add an example that uses Elm or Rust compiled to asm.js
  • Add a PureScript example that does two-way communication with the backend
  • Contribute to the original webview library: E.g. add HDPI support on Windows
  • Make it possible to create the webview window as a child window of a given parent window. This would allow webview to be used for the GUIs of VST audio plugins in Rust.

Ideas for apps

  • Rust IDE (by porting xi-electron to web-view)
  • Data visualization / plotting lib for Rust, to make Rust more useful for data science
  • Crypto coin wallet
  • IRC client, or client for other chat protocols
  • Midi song editor, VJ controller
  • Rust project template wizard: Generate new Rust projects from templates with user-friendly steps
  • GUI for pijul
  • Implement Gooey alternative with web-view and clap-rs

Showcase

Feel free to open a PR if you want your project to be listed here!

  • Juggernaut - The unstoppable programmers editor
  • FrakeGPS - Simulate a simple GPS device
  • Compactor - Windows 10 filesystem compression utility
  • neutrino - A GUI frontend in Rust based on web-view
  • SOUNDSENSE-RS - Sound-engine tool for Dwarf Fortress
  • Tauri - Bringing security into webstack GUIs, with strong support for your favorite JS frameworks
  • WV Linewise - Add your own interactive HTML/CSS/JS in the middle of your UNIX pipelines
  • Bloop - A light weight aesthetic scratchpad for developers.

Contributions and feedback welcome :)


Dependencies

~0.3–1.4MB
~28K SLoC