Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Web Assembly, Rust y el futuro de JavaScript

Web Assembly, Rust y el futuro de JavaScript

LimaJS 15 Dic 2018

Lupo Montero

December 15, 2018
Tweet

More Decks by Lupo Montero

Other Decks in Programming

Transcript

  1. Disclaimer Imágenes, inspiración y algunas ideas a continuación, han sido

    tomadas de varios recursos abiertos; en particular el blog https://hacks.mozilla.org/ y los posts y presentaciones de Lin Clark (@linclark).
  2. Qué es WebAssembly? “WebAssembly (abbreviated Wasm) is a binary instruction

    format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.” Fuente: https://webassembly.org/
  3. Qué es Rust? “Rust es un lenguaje de programación de

    sistemas extremadamente rápido, previene fallas de segmentación y garantiza la seguridad de los hilos de ejecución.” Fuente: https://www.rust-lang.org/es-ES/
  4. • Performance • Minimal runtime • Memory safety without GC

    • No data races • High-level abstractions • Awesome build system / dev experience (rustup, cargo, ...) • Más amigable para desarrolladorxs web? • Reemplazo de C y C++? Por qué Rust?
  5. Rust vs ... Fuente: “A Case for Oxidation” - Sergio

    Benítez https://youtu.be/cDFSrVhnZKo?t=262
  6. Rust toolchain y wasm como target • # configura toolchain

    nightly por defecto rustup default nightly • # añade wasm como target rustup target add wasm32-unknown-unknown \ --toolchain nightly Fuente: https://rustwasm.github.io/wasm-bindgen/whirlwind-tour/basic-usage.html
  7. Cargo • cargo new • cargo init • cargo run

    • cargo build • cargo test • cargo install • cargo publish • ...
  8. Rust => Wasm (101) • # creamos un proyecto indicando

    que va a ser una librería cargo new --lib limajs • Modificamos el tipo de “crate” en Cargo.toml: [lib] crate-type = ["cdylib"]
  9. Compilemos nuestro programa # Esto debería crear un archivo wasm:

    # target/wasm32-unknown-unknown/debug/limajs.wasm cargo build --target wasm32-unknown-unknown
  10. Invocando una función de Rust desde JavaScript fetch('target/wasm32-unknown-unknown/debug/limajs.wasm') .then(resp =>

    resp.arrayBuffer()) .then(buffer => WebAssembly.instantiate(buffer)) .then(wasm => console.log(wasm.instance.exports.sum(2, 3)));
  11. Optimizando el archivo wasm con wasm-gc cargo install wasm-gc #

    post-procesamos con wasm-gc... wasm-gc \ target/wasm32-unknown-unknown/debug/limajs.wasm \ limajs.gc.wasm
  12. Usando wasm optimizado con wasm-gc fetch('limajs.gc.wasm') .then(resp => resp.arrayBuffer()) .then(result

    => WebAssembly.instantiate(result)) .then(wasm => console.log(wasm.instance.exports.sum(2, 3)));
  13. Pasando funciones de JavaScript a Rust Promise<ResultObject> WebAssembly.instantiateStreaming(source, options); const

    options = { env: { printToDOM: msg => document.body.appendChild(document.createTextNode(msg)), }, };
  14. Usando funciones de JavaScript en Rust extern { fn printToDOM(x:

    i32); } #[no_mangle] pub fn run() { unsafe { printToDOM(42); } }
  15. Y si necesitamos pasar más que números entre Rust y

    JavaScript? extern { fn printToDOM(x: String); } #[no_mangle] pub fn run() { unsafe { printToDOM(String::from("OMG")); } }
  16. src/lib.rs extern crate wasm_bindgen; use wasm_bindgen::prelude::*; #[wasm_bindgen(module = "../printToDOM")] extern

    { fn printToDOM(x: String); } #[wasm_bindgen] pub fn run() { printToDOM(String::from("OMG")); } #[wasm_bindgen] pub fn sum(a: i32, b: i32) -> i32 { a + b }
  17. Build y generación de bindings de JavaScript cargo build --target

    wasm32-unknown-unknown mkdir build wasm-bindgen \ target/wasm32-unknown-unknown/debug/limajs.wasm \ --out-dir ./build
  18. Configuración de Webpack const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = {

    entry: './index.js', plugins: [ new HtmlWebpackPlugin({ title: 'Getting started with WASM' }), ], };
  19. Usando nuestro módulo desde JavaScript // index.js import('./build/limajs') .then(wasm =>

    wasm.run()) .catch(console.error); https://webpack.js.org/api/module-methods/#import-
  20. Arrancando nuestra aplicación... npx webpack-dev-server --mode development ... "scripts": {

    "start": "webpack-dev-server --mode development" }, ... yarn start