Aller au contenu

WebImage : de la JVM à WebAssembly

Compilez du Java ou du Kotlin en module WebAssembly avec un chargeur JavaScript grâce à l'artefact WebImage d'Elide : prérequis, backends, hôtes et options du compilateur.

Sur cette page

Un artefact WebImage compile du bytecode JVM en un chargeur JavaScript accompagné d’un module WASM. Pour exécuter un binaire WASM ou WASI existant, voir WebAssembly.

Prérequis

  • Binaryen 119 ou ultérieur, avec wasm-as dans le PATH au moment du build.
  • Du code conforme aux exigences de Native Image : métadonnées d’accessibilité pour la réflexion, les ressources et les proxys ; aucune dépendance native.
  • Un hôte qui gère les exceptions WASM (et WASM GC pour wasm-gc) : Node.js 25+ ou un navigateur récent.

Le bundle déployé n’a besoin ni d’Elide ni de Binaryen.

Construire un projet complet

hello-wasm/
  elide.pkl
  src/main/java/Hello.java
public class Hello {
  public static void main(String[] args) {
    System.out.println("Hello from WebImage");
  }
}
amends "elide:project.pkl"
import "elide:Jvm.pkl" as jvm
import "elide:NativeImage.pkl" as nativeImage

name = "hello-wasm"

artifacts {
  ["app-jar"] = new jvm.Jar {
    sources { "main" }
  }
  ["web"] = new nativeImage.WebImage {
    from { "app-jar" }
    name = "hello"
    entrypoint = "Hello"
    backend = "wasm-gc"
    runtime = "generic"
    autoRun = true
    sourceMap = false
    options {
      optimization = "b"
    }
  }
}
elide build

Elide construit app-jar, puis le compile en web. name est le nom de base sans .js ni .wasm ; optimization = "b" est le mode de build rapide. La sortie va dans .dev/artifacts/native-image/ :

FichierRôle
hello.jsChargeur JavaScript et point d’entrée.
hello.js.wasmModule WASM, chargé par hello.js.
hello.js.watForme texte du WASM, pour inspection.
hello.js.mapSource map du chargeur, si sourceMap = true.

Déployez hello.js et hello.js.wasm ensemble. Kotlin et les autres langages JVM fonctionnent de la même façon une fois empaquetés dans un JAR. Une restauration depuis le cache rétablit le bundle entier ; désactiver sourceMap supprime l’ancien .js.map.

Choisir un backend et un hôte

PropriétéValeurSignification
backend"wasm-gc" (par défaut)Utilise le ramasse-miettes WASM de l’hôte.
backend"wasm-lm"Utilise un ramasse-miettes en mémoire linéaire ; nécessite toujours le chargeur, ce n’est pas un binaire WASI.
runtime"generic" (par défaut)Le chargeur prend en charge les navigateurs et Node.
runtime"browser"Chargeur spécialisé pour les navigateurs.
runtime"node"Chargeur spécialisé pour les API compatibles Node.
autoRuntrue (par défaut)Démarre le programme au chargement du chargeur ; false laisse le démarrage à la page qui l’intègre.
sourceMapfalse (par défaut)true produit hello.js.map.

Un point d’entrée est requis même avec autoRun = false. Aucun runtime ne cible Cloudflare Workers, Fastly Compute ou WASI. Les champs communs (from, entrypoint, moduleName, options) sont décrits dans Native Image. Un WebImage ne peut pas servir d’entrée à un artefact conteneur.

Guides par cible : Browser WASM et Edge WASM.

Exécuter sur un hôte backend

Avec runtime = "generic" ou "node" :

node .dev/artifacts/native-image/hello.js
Hello from WebImage

Exécuter dans un navigateur

Avec runtime = "browser" ou "generic" et autoRun = true, placez ce index.html dans .dev/artifacts/native-image/ :

<!doctype html>
<html lang="en">
  <meta charset="utf-8" />
  <title>Hello WebImage</title>
  <body>
    <p>Open the browser console to see the application output.</p>
    <script src="./hello.js"></script>
  </body>
</html>
elide dev --no-tui --port 8000 .dev/artifacts/native-image

Ouvrez http://localhost:8000/ ; la sortie s’affiche dans la console du navigateur. Les URL file:// ne fonctionnent pas.

Options du compilateur

Le bloc options de l’artefact accepte les options du compilateur Native Image ; celles qui s’appliquent dépendent du backend. Deux cas propres à WebImage :

  • options.driverMode = "external" utilise native-image depuis GRAALVM_HOME ou JAVA_HOME ; cette installation doit prendre en charge les backends WebAssembly.
  • -H:EntryPointsConfig=config/entrypoints.json dans options.flags définit les points d’entrée ; le chemin est relatif à la racine du projet, et modifier le fichier déclenche un nouveau build.

Compiler sans manifeste de projet

elide javac -- -d classes src/main/java/Hello.java
elide native-image -- --tool:wasm-gc -Ob -cp classes -o hello Hello
elide native-image -- --tool:wasm-lm -Ob -cp classes -o hello-lm Hello

Les bundles sont écrits dans le répertoire courant. Un artefact NativeImage avec --tool:wasm-gc ou --tool:wasm-lm dans options.flags se construit toujours. Pour le migrer, remplacez la classe par WebImage, retirez l’option et tout type, puis définissez backend.

Dépannage

SymptômeSolution
wasm-as introuvableInstallez Binaryen et ajoutez-le au PATH du build.
Le pilote externe refuse le backend WebAssemblyFaites pointer GRAALVM_HOME ou JAVA_HOME vers une installation dont native-image le prend en charge, ou utilisez driverMode = "embedded".
Options brutes en conflitRetirez les options de backend, d’environnement d’exécution, de démarrage et de source map ; utilisez les propriétés typées. Ne remplacez ni Backend ni la propriété du lanceur.
L’hôte refuse des instructions WASMUtilisez un hôte qui gère les exceptions et, pour wasm-gc, WASM GC.
Le navigateur ne charge pas le moduleServez le chargeur et le module ensemble via HTTP ; vérifiez l’URL demandée.
elide run hello.js.wasm signale des imports manquantsExécutez plutôt hello.js ; le module a besoin de son chargeur.

Cette page vous a-t-elle aidé ?