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

Avatar for Lupo Montero

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