Fermer

février 11, 2020

Une introduction de Rust à WebAssembly


Voyons comment Wasm + Rust libère un potentiel vraiment excitant pour l'avenir du développement web frontal. Ce n'est pas un remplacement pour JavaScript – il l'améliore et le complète.

Conditions préalables:

Cet article suppose ce qui suit:

  • Un peu de connaissances sur la rouille et la chaîne d'outils standard, y compris le rouillage, la rouille et le fret [19659005] Bases de HTML, CSS et JavaScript

Qu'est-ce que WebAssembly?

Selon la documentation officielle WebAssembly (abrégé Wasm) est un format d'instructions binaires pour une machine virtuelle basée sur la pile. Wasm est conçu comme une cible portable pour la compilation de langages de haut niveau comme C / C ++ / Rust, permettant le déploiement sur le Web pour les applications client et serveur.

Décomposons cela en une grammaire plus simple. Essentiellement, tout cela signifie que Wasm est:

  • Une cible de compilation: C'est une façon de prendre du code écrit dans une autre langue (autre que JavaScript bien sûr) et de l'exécuter sur un navigateur Web.
  • Une amélioration (pas un remplacement) de JavaScript: Des parties essentielles / de calcul critique de votre base de code peuvent être implémentées dans Wasm et importées comme un module JavaScript standard.
  • Un nouveau langage: Le code Wasm définit un AST (arbre de syntaxe abstraite) représenté dans un format binaire. Si vous le décidez, vous pouvez le créer et le déboguer au format texte, il est absolument lisible.
  • Une amélioration du rendu du navigateur: Parce que Wasm est au format binaire, qui est plus proche du code de niveau machine, les navigateurs peuvent rendre Wasm plus rapidement et atteindre une vitesse de type natif par rapport au texte JavaScript standard que nous avons aujourd'hui. Il est important de noter que les opportunités d'optimisation au moment de la compilation sont essentielles pour que ce soit le cas.

Pourquoi Wasm?

Comme de nombreux développeurs seront d'accord, il est beaucoup plus difficile d'atteindre des étapes importantes lorsque vous codez directement dans le langage d'assemblage. et JavaScript est un langage assez génial pour écrire la plupart du code requis par tous les logiciels dont nous pouvons rêver. Alors, pourquoi avons-nous besoin de cet assemblage Web pour commencer?

  • WebAssemby apporte de la diversité au Web et la diversité est une bonne chose. Cela signifie que vous pouvez écrire dans la langue de votre choix et qu'elle s'exécute dans le navigateur – imaginez les possibilités.
  • Il est rapide, car il est codé dans un format binaire efficace en termes de taille et de temps de chargement, s'exécutant à la vitesse native en tirant parti des capacités matérielles communes disponibles sur une large gamme de plates-formes. Mettez Rust dans le mélange, et vous avez des tailles de paquets incroyablement petites et par conséquent plus de vitesse.
  • Les bases de code existantes n'ont pas besoin d'être jetées. Vous pouvez commencer par porter vos fonctions JavaScript les plus sensibles aux performances vers Wasm pour obtenir des avantages immédiats. Vous pouvez même vous arrêter là, si vous en décidez ainsi.

Mise en route

Configuration Rust + Wasm

Maintenant que nous sommes au courant de ce qu'est Wasm, la prochaine consiste à configurer votre machine pour le développement Wasm avec Rust. Nous allons voir comment configurer la chaîne d'outils pour compiler des programmes Rust dans WebAssembly et les intégrer dans JavaScript. Après quoi, nous allons créer une application très basique qui demande aux utilisateurs d'entrer deux chiffres qu'ils souhaitent ajouter.

Assurez-vous que la chaîne d'outils Rust standard est installée. Vous pouvez trouver l'installation ici .

Pour continuer, assurez-vous que vous disposez de Rust 1.30 ou plus récent. Utilisez la commande ci-dessous pour vérifier votre version Rust.

 rustc -V 

ou

 rustc --version 

Remarque: La commande ci-dessus dépend de votre version.

Suivant nous installons wasm-pack qui est un guichet unique pour la construction, les tests et la publication de WebAssembly généré par Rust. À des fins de démonstration, j'utiliserai une machine Unix (distributions Mac et Linux). Si vous êtes sur une machine Windows, vous pouvez télécharger un programme d'installation pour wasm-pack ici .

Exécutez la commande ci-dessous dans votre terminal et suivez l'invite pour l'installer sur votre machine. [19659023] curl https://rustwasm.github.io/wasm-pack/installer/init.sh -s Sf | sh

Vous devriez avoir cette sortie:

Ensuite, nous installons cargo-generate ce qui permet de démarrer rapidement avec un nouveau projet Rust en tirant parti d'un préexistant référentiel git comme modèle. Installez avec cette commande:

 cargo install cargo-generate  

Remarque: Si cela échoue, une raison typique est que pkg-config n'est pas installé sur votre machine. Vous pouvez résoudre ce problème en exécutant la commande suivante pour les machines Linux. Utilisez brew si vous êtes sur un Mac.

 sudo apt install pkg-config 

La prochaine étape est npm. Il s'agit d'un gestionnaire de packages JavaScript. Nous l'utiliserons pour installer et exécuter un bundle JavaScript et un serveur de développement. Suivez les instructions de e s e pour installer npm . Si vous avez déjà installé npm, assurez-vous qu'il est à jour avec cette commande.

 npm install npm @ latest -g 

Bonjour tout le monde!

Nous verrons comment construire notre premier programme Rust et WebAssembly : une page Web qui alerte "Bonjour tout le monde!"

Tout d'abord, nous clonons un modèle de projet qui est préconfiguré avec les mêmes paramètres par défaut, afin que vous puissiez rapidement créer, intégrer et empaqueter votre code pour le Web.

Clonez le modèle avec cette commande:

 cargo generate --git https://github.com/rustwasm/wasm-pack-tem plate  

Cela devrait vous demander le nom du nouveau projet. Nous utiliserons le calcul de la rouille.

 rouille-calcul 

Répartition de la structure du projet

Entrez dans le nouveau répertoire du projet

 cd rouille-calcul 

Selon le moment où vous lisez ceci, son contenu devrait ressembler à ceci: [19659008]

Examinons en détail certains de ces fichiers.

 rust-Calculate / Cargo.toml 

Le fichier Cargo.toml spécifie les dépendances et les métadonnées pour cargo le gestionnaire de paquets et l'outil de construction de Rust. Celui-ci est préconfiguré avec une dépendance wasm-bindgen quelques dépendances optionnelles et le type de caisse correctement initialisé pour générer les bibliothèques .wasm .

 rust-Calculate / src Le fichier  src / lib.rs  est la racine de la caisse Rust que nous compilons pour WebAssembly. Il utilise  wasm-bindgen  pour s'interfacer avec JavaScript. Il importe la fonction JavaScript  window.alert  et exporte la fonction  salue  Rust, qui alerte un message de bienvenue. 

 mod utils;
utilisez wasm_bindgen :: prelude :: *;
// Lorsque la fonction `wee_alloc` est activée, utilisez` wee_alloc` comme global
// allocateur.
# [cfg(feature = "wee_alloc")]
# [global_allocator]
ALLOC statique: wee_alloc :: WeeAlloc = wee_alloc :: WeeAlloc :: INIT;
# [wasm_bindgen]
extern {
    alerte fn (s: & str);
}
# [wasm_bindgen]
pub fn salue () {
    alert ("Bonjour, calculez la rouille!");
}
 rouille-calculer / src / utils.rs 

Le module src / utils.rs fournit des utilitaires courants pour faciliter le travail avec Rust compilé vers WebAssembly.

Construire le projet

wasm-pack est utilisé pour orchestrer les étapes de construction suivantes:

  • Assurez-vous que nous avons Rust 1,30 ou une version plus récente et la cible wasm32-unknown-unknown installée via rustup .
  • Compilez nos sources de rouille dans un assemblage Web .wasm binaire via cargo .
  • Utilisez wasm-bindgen pour générer l'API JavaScript pour en utilisant notre WebAssembly généré par Rust.

Pour faire tout cela, exécutez cette commande dans le répertoire du projet:

 build wasm-pack 

Lorsque la construction est terminée, nous pouvons trouver ses artefacts dans le répertoire pkg et il doit avoir le contenu suivant:

Le fichier README.md est copié à partir du projet principal, mais les autres sont complètement nouveaux.

 rouille-calcul / pkg / rust_calculate_bg .wasm 

Le fichier .wasm est le binaire WebAssembly généré par le compilateur Rust à partir de nos sources Rust. Il contient les versions compilées au wasm de toutes nos fonctions et données Rust. Par exemple, il a une fonction "d'accueil" exportée.

 rust-Calculate / pkg / rust_calculate.js 

Le fichier .js est généré par wasm-bindgen et contient de la colle JavaScript pour importer des fonctions DOM et JavaScript dans Rust et exposer une belle API aux fonctions WebAssembly à JavaScript. Par exemple, il existe une fonction JavaScript saluer qui encapsule la fonction saluer exportée à partir du module WebAssembly. Pour l'instant, cette colle ne fait pas grand-chose, mais lorsque nous commençons à transmettre des valeurs plus intéressantes entre Wasm et JavaScript, cela aidera à guider ces valeurs à travers la frontière.

 importez * comme wasm de './rust_calculate_bg. était M'
/ **
* /
fonction d'exportation salue () {
    wasm.greet ();
}
laissez cachedTextDecoder = new TextDecoder ('utf-8', {ignoreBOM: true, fatal: true});
laissez cachegetUint8Memory = null;
fonction getUint8Memory () {
    if (cachegetUint8Memory === null || cachegetUint8Memory.buffer! == wasm.memory.buffer) {
        cachegetUint8Memory = nouveau Uint8Array (wasm.memory.buffer);
    }
    return cachegetUint8Memory;
}
function getStringFromWasm (ptr, len) {
    return cachedTextDecoder.decode (getUint8Memory (). subarray (ptr, ptr + len));
}
export const __wbg_alert_264313fba916676f = fonction (arg0, arg1) {
    alert (getStringFromWasm (arg0, arg1));
};
 rouille-calcul / pkg / rust_calculate.ts 

Le fichier .d.ts contient des déclarations de type TypeScript pour la colle JavaScript. Si vous utilisez TypeScript, vous pouvez faire vérifier le type de vos appels dans les fonctions WebAssembly, et votre IDE peut fournir des compléments automatiques et des suggestions! Si vous n'utilisez pas TypeScript, vous pouvez ignorer ce fichier en toute sécurité.

 / * tslint: disable * /
/ **
* /
fonction d'exportation salue (): void;
 rouille-calculer / pkg / package.json 

Le package.json (https://docs.npmjs.com/files/package.json) fichier " contient des métadonnées sur le généré JavaScript et package WebAssembly. Ceci est utilisé par les bundleurs npm et JavaScript pour déterminer les dépendances entre les packages, les noms de package, les versions et un tas d'autres choses. Il nous aide à intégrer les outils JavaScript et nous permet de publier notre package sur npm.

 {
  "nom": "calcul de rouille",
  "collaborateurs": [
    "Obinna Ekwuno "
  ],
  "version": "0.1.0",
  "fichiers": [
    "rust_calculate_bg.wasm",
    "rust_calculate.js",
    "rust_calculate.d.ts"
  ],
  "module": "rust_calculate.js",
  "types": "rust_calculate.d.ts",
  "sideEffects": "false"
}

Mise en page Web

Pour prendre notre package de calcul de rouille et l'utiliser dans une page Web, nous utilisons le create-wasm-app modèle de projet JavaScript.

Exécutez ce commande à l'intérieur du répertoire du projet de calcul de la rouille:

 npm init wasm-app www 

La commande crée un nouveau répertoire de calcul de la rouille / www, le contenu est:

Encore une fois, nous allons regardez de plus près certains de ces fichiers.

 rust-calcul / www / package.json 

Ce package.json est préconfiguré avec webpack et dépendances webpack-dev-server ainsi qu'une dépendance sur hello-wasm-pack qui est une version du package initial wasm-pack-template qui a été publié sur npm.

 rust-Calculate / www / weback.config.js 

Ce fichier configure webpack et son serveur de développement local. Il est préconfiguré et vous ne devriez pas avoir à le modifier du tout pour que le webpack et son serveur de développement local fonctionnent.

 rust-Calculate / www / index.html 

Ceci est le fichier HTML racine pour le page Web. Il ne fait pas grand-chose d'autre que de charger bootstrap.js qui est une enveloppe très fine autour de index.js .



  
    
     Bonjour wasm-pack! 
  
  
    
       

 rouille-calcul / www / index.js 

Le index.js est le principal point d'entrée pour le JavaScript de notre page Web. Il importe le paquet hello-wasm-pack npm, qui contient le WebAssembly compilé par défaut wasm-pack-template et la colle JavaScript, puis il appelle hello-wasm- pack salue la fonction

 import * as wasm de "hello-wasm-pack";
wasm.greet ();

Installation des dépendances

Tout d'abord, assurez-vous que le serveur de développement local et ses dépendances sont installés en exécutant npm install dans le sous-répertoire rust-Calculate / www :

 npm install 

Cette commande ne doit être exécutée qu'une seule fois et installera le webpack bundler JavaScript et son serveur de développement.

Remarque: webpack n'est pas requis pour travailler avec Rust et WebAssembly, il est juste le bundler et le serveur de développement que nous avons choisis ici pour plus de commodité. Parcel et Rollup doivent également prendre en charge l'importation de WebAssembly en tant que modules ECMAScript. Vous pouvez également utiliser Rust et WebAssembly sans bundler si vous préférez!

Utilisation de notre package local de calcul de rouille dans www

Plutôt que d'utiliser le hello-wasm-pack paquet de npm, nous voulons utiliser notre paquet local de calcul de la rouille. Cela nous permettra de développer progressivement notre application de démonstration simple.

Ouvrez rust-Calculate / www / package.json et éditez les "dépendances" pour inclure un "rouille-calculer": "fichier: ../ pkg" entrée

 {
  // ...
  "dépendances": {
    "rouille-calculer": "fichier: ../ pkg", // Ajoutez cette ligne!
    // ...
  }
}

Ensuite, modifiez rouille-calcul / www / index.js pour importer rouille-calcul à la place du hello-wasm-pack paquet:

 import * as wasm from "calculer la rouille";
wasm.greet (); 

Puisque nous avons déclaré une nouvelle dépendance, nous devons l'installer:

 npm install 

Félicitations. Notre page Web est maintenant prête à être servie localement!

Servir localement

Ensuite, ouvrez un nouveau terminal pour le serveur de développement. L'exécution du serveur dans un nouveau terminal nous permet de le laisser fonctionner en arrière-plan et ne nous empêche pas d'exécuter d'autres commandes entre-temps. Dans le nouveau terminal, exécutez cette commande à partir du répertoire wasm-game-of-life / www:

 npm run start 

Naviguez dans votre navigateur Web vers http: // localhost: 8080 / et vous devriez être accueilli avec un message d'alerte:

 Premier programme Hello World dans Rust + Wasm

Chaque fois que vous apportez des modifications et que vous souhaitez qu'elles soient reflétées sur http: // localhost: 8080 /, il suffit de relancer le Commande wasm-pack build dans le répertoire rust-Calculate.

Fin de notre application de démonstration

Ensuite, nous modifions le fichier index.html pour refléter une nouvelle interface utilisateur simple pour l'application de démonstration que nous voulons créer. Le fichier contient des styles CSS simples et du balisage.



  
    
     Calcul de rouille 
  
    
    

CALCUL DE LA ROUILLE

    
       

Le serveur Webpack se recharge automatiquement et votre page devrait ressembler à ceci:

Ensuite, nous créons une fonction de rouille pour effectuer notre ajout. Ouvrez le fichier lib.rs situé dans rust-Calculate / src / lib.rs. Modifiez la fonction d'accueil en:

 pub fn add (x: i32, y: i32) -> i32 {
    soit z = x + y;
    return z;
}

La fonction est assez simple. Il prend deux nombres et renvoie leur somme.

Nous réexécutons maintenant notre commande build pour regrouper notre nouveau code de rouille dans Wasm. La construction écrase automatiquement la précédente dans le répertoire pkg, laissez-la telle quelle. Exécutez cette commande dans le répertoire rust-Calculate:

 build wasm-pack

Une fois que c'est fait, jetez un œil au fichier rust_calculate.js et vous devriez voir notre nouvelle fonction d'ajout:

 fonction d'exportation add (x, y) {
    const ret = wasm.add (x, y);
    return ret;
}

Maintenant, nous pouvons maintenant l'utiliser dans notre fichier index.js trouvé dans rust-calcul / www / index.js.

Mettez à jour le code index.js pour:

 import * comme wasm de "rouille-calculer" ";
document.querySelector ('# addBtn'). addEventListener ('click', () => {
   let x = document.querySelector ('# firstValue'). value;
   laissez y = document.querySelector ('# secondValue'). value;
   si (! x &&! y) {
    alerte ("veuillez saisir des valeurs")
    revenir
   }
   soit z = wasm.add (x, y)
   document.querySelector ('# answerDisplay'). innerHTML = z
})

Le code est assez simple.

Cela importe notre binaire Wasm généré à partir du répertoire pkg.

 import * as wasm from "rust-Calculate"; 

Ensuite, un écouteur d'événements de clic est attaché au bouton.

 document.querySelector (' #addBtn '). addEventListener (' click ', () => 

Nous obtenons ensuite les valeurs des champs de saisie.

 let x = document.querySelector (' # firstValue '). value;
let y = document.querySelector ('# secondValue'). value; 

Ensuite, nous vérifions que les champs ne sont pas vides avant de le passer à notre fonction add.

 if (! x &&! y) {
    alerte ("veuillez saisir des valeurs")
    revenir
   } 

Maintenant, nous passons nos valeurs dans values ​​à la fonction add, à laquelle nous accédons avec wasm.

 let z = wasm.add (x, y) 

Enfin, nous mettons à jour notre interface utilisateur avec le résultat du calcul.

 document.querySelector ('# answerDisplay'). InnerHTML = z 

Pour en savoir plus sur la façon de construire avec Wasm + Rust, voici une ressource incroyable . Il vous guide à travers les notions de base jusqu'aux concepts avancés comme le débogage, les optimisations, etc.

Conclusion

Dans cet article, nous avons examiné comment Wasm + Rust libère un potentiel vraiment excitant pour l'avenir du développement Web frontal. Il ne remplace pas JavaScript - il l'améliore et le complète. Alors que vous avancez pour explorer cette nouvelle frontière, que la force soit avec vous. Codage heureux.





Source link