koute / stdweb

A standard library for the client-side Web
Apache License 2.0
3.44k stars 177 forks source link
asmjs emscripten gui javascript rust web webasm webassembly

Build Status Join the chat at https://gitter.im/stdweb-rs/stdweb

A standard library for the client-side Web

Documentation

The goal of this crate is to provide Rust bindings to the Web APIs and to allow a high degree of interoperability between Rust and JavaScript.

Donate

Become a patron

Patrons

This software was brought to you thanks to these wonderful people:

Thank you!

Examples

You can directly embed JavaScript code into Rust:

let message = "Hello, 世界!";
let result = js! {
    alert( @{message} );
    return 2 + 2 * 2;
};

println!( "2 + 2 * 2 = {:?}", result );

Closures are also supported:

let print_hello = |name: String| {
    println!( "Hello, {}!", name );
};

js! {
    var print_hello = @{print_hello};
    print_hello( "Bob" );
    print_hello.drop(); // Necessary to clean up the closure on Rust's side.
}

You can also pass arbitrary structures thanks to serde:

#[derive(Serialize)]
struct Person {
    name: String,
    age: i32
}

js_serializable!( Person );

js! {
    var person = @{person};
    console.log( person.name + " is " + person.age + " years old." );
};

This crate also exposes a number of Web APIs, for example:

let button = document().query_selector( "#hide-button" ).unwrap().unwrap();
button.add_event_listener( move |_: ClickEvent| {
    for anchor in document().query_selector_all( "#main a" ) {
        js!( @{anchor}.style = "display: none;"; );
    }
});

Exposing Rust functions to JavaScript is supported too:

#[js_export]
fn hash( string: String ) -> String {
    let mut hasher = Sha1::new();
    hasher.update( string.as_bytes() );
    hasher.digest().to_string()
}

Then you can do this from Node.js:

var hasher = require( "hasher.js" ); // Where `hasher.js` is generated from Rust code.
console.log( hasher.hash( "Hello world!" ) );

Or you can take the same .js file and use it in a web browser:

<script src="https://github.com/koute/stdweb/raw/master/hasher.js"></script>
<script>
    Rust.hasher.then( function( hasher ) {
        console.log( hasher.hash( "Hello world!" ) );
    });
</script>

If you're using Parcel you can also use our experimental Parcel plugin; first do this in your existing Parcel project:

$ npm install --save parcel-plugin-cargo-web

And then simply:

import hasher from "./hasher/Cargo.toml";
console.log( hasher.hash( "Hello world!" ) );

Design goals

Getting started

Take a look at some of the examples:

The API documentation is also available for you to look at.

Running the examples

  1. Install cargo-web:

    $ cargo install -f cargo-web

  2. Go into examples/todomvc and start the example using one of these commands:

    • Compile to WebAssembly using Rust's native WebAssembly backend:

      $ cargo web start --target=wasm32-unknown-unknown

    • Compile to asm.js using Emscripten:

      $ cargo web start --target=asmjs-unknown-emscripten

    • Compile to WebAssembly using Emscripten:

      $ cargo web start --target=wasm32-unknown-emscripten

  3. Visit http://localhost:8000 with your browser.

For the *-emscripten targets cargo-web is not necessary, however the native wasm32-unknown-unknown which doesn't need Emscripten requires cargo-web to work!

Changelog

License

Licensed under either of

at your option.

Snippets of documentation which come from Mozilla Developer Network are covered under the CC-BY-SA, version 2.5 or later.

Contributing

See CONTRIBUTING.md