• Création d’un nouveau site Hugo
  • Création d’un projet Rust
  • Appeler Rust depuis Javascript
  • Intégration de WebAssembly dans le site
  • Conclusion
  • Accueil
  • Articles
  • Notes
  • Livres
  • Auteur
🇺🇸 en 🇨🇳 zh 🇮🇳 ml

Nathaniel Thomas

Construire et déployer du Rust sur un site Hugo

22 avril 2024

Nous allons passer en revue un exemple minimal qui vous permettra d’exécuter du code Rust côté client d’un site Hugo. Nous allons compiler le code Rust en WebAssembly (wasm), ce qui nous donnera des performances quasi-natives dans le navigateur !

Création d’un nouveau site Hugo

Commençons par initialiser le site de démarrage rapide de Hugo :

hugo new site quickstart_wasm
cd quickstart_wasm
git init
git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke.git themes/ananke
echo "theme = 'ananke'" >> hugo.toml
hugo server

Vous devriez voir quelque chose comme :

# Logs ...
Built in 28 ms
Environment: "development"
Serving pages from disk
Running in Fast Render Mode. For full rebuilds on change: hugo server --disableFastRender
Web Server is available at http://localhost:55802/ (bind address 127.0.0.1)

Si vous ouvrez l’URL localhost, vous devriez voir quelque chose comme ceci :

Site Hugo vide
Un site Hugo vide

Création d’un projet Rust

Nous allons utiliser Rust comme langage source pour notre wasm, principalement parce que ses macros rendent extrêmement facile la création de liaisons. Pour plus de commodité, initialisons la bibliothèque dans le répertoire assets de notre site Hugo.

# Dans le dossier du site Hugo
cd assets
mkdir rust_app && cd rust_app
cargo init --lib

Ouvrez Cargo.toml et ajoutez ce qui suit :

# Ajoutez ceci en bas
[lib]
crate-type = ["cdylib", "rlib"]

Maintenant, nous devons ajouter wasm-bindgen comme dépendance, ce qui nous donnera une solution en une ligne pour créer des liaisons.

cargo add wasm-bindgen

Dans src/lib.rs, écrivons une fonction critique en termes de performance que nous devons appeler depuis notre application web.

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn sieve_of_eratosthenes(n: usize) -> Vec<i32> {
    let mut primes = Vec::new();
    let mut is_prime = vec![true; n + 1];
    is_prime[0] = false;
    is_prime[1] = false;

    for i in 2..=n {
        if is_prime[i] {
            primes.push(i as i32);

            let mut j = 2 * i;
            while j <= n {
                is_prime[j] = false;
                j += i;
            }
        }
    }

    primes
}

Nous allons compiler ceci avec :

wasm-pack build --target web

Vous devriez voir la sortie compilée dans pkg.

ls pkg
package.json  rust_app.d.ts  rust_app.js  rust_app_bg.wasm  rust_app_bg.wasm.d.ts

Appeler Rust depuis Javascript

Maintenant, dans le dossier rust_app, créons une application web qui utilisera notre crible de nombres premiers.

# dans assets/rust_app
mkdir www && cd www
touch index.js

Mettez ce qui suit dans le fichier index.js :

import init, * as wasm from '../pkg/rust_app';

init(wasm_path).then(_ => {
    function computePrimes()
    {
        var inputNumber = parseInt(
            document.getElementById('inputNumber').value,
        );
        if (!isNaN(inputNumber) && inputNumber >= 1) {
            var primes = wasm.sieve_of_eratosthenes(inputNumber);
            document.getElementById('output').innerText = primes.join(', ');
        } else {
            document.getElementById('output').innerText =
                'Please enter a valid integer.';
        }
    }
    let button = document.getElementById('computeButton');
    button.addEventListener('click', () => {
        computePrimes();
    });
});

Intégration de WebAssembly dans le site

Maintenant, nous voulons que le résultat de la fonction wasm apparaisse sur le site. Créons donc un shortcode que nous pouvons insérer dans un article avec une petite application web.

Dans ~/quickstart_wasm/layouts/shortcodes/wasm_app.html :

<!doctype html>
<html lang="en">
  <head>
    <title>Prime Number Finder</title>
  </head>
  <body>
    <input type="number" id="inputNumber" placeholder="Enter an integer..." />
    <button id="computeButton">Compute</button>
    <div id="output"></div>

    <!-- rust_app DOIT être dans /assets pour être détecté ! -->
    {{ $wasm_path := resources.Get "rust_app/pkg/rust_app_bg.wasm" }}

    <script>
      wasm_path = "{{ $wasm_path.Permalink }}";
    </script>

    {{ $index_js := resources.Get "rust_app/www/index.js" | js.Build }}

    <script type="module" src="{{ $index_js.Permalink }}"></script>
  </body>
</html>

La clé ici est la partie où nous définissons la variable globale wasm_path dans notre environnement JS. Cela fait deux choses :

  1. Indique à Hugo de rendre ce chemin accessible via des requêtes fetch
  2. Donne au script JS le bytecode wasm à exécuter

Nous devrions maintenant pouvoir utiliser le générateur de nombres premiers depuis la page d’accueil !

Générateur de nombres premiers
hugo server – Nombres premiers générés depuis Rust

Conclusion

Il n’y avait pas beaucoup de ressources en ligne sur wasm + Hugo, alors j’ai décidé de créer le premier tutoriel. Si vous avez une méthode alternative/meilleure pour déployer wasm, faites-le-moi savoir dans les commentaires.


←
Passer à Obsidian
Estimation du Maximum de Vraisemblance
→

back to top