Перейти к содержимому

WebImage: из JVM в WebAssembly

Компилируйте Java или Kotlin в модуль WebAssembly с загрузчиком на JavaScript с помощью артефакта WebImage в Elide: требования, бэкенды, хосты и параметры компилятора.

На этой странице

Артефакт WebImage компилирует байт-код JVM в загрузчик на JavaScript и модуль WASM. Как запустить готовый бинарный файл WASM или WASI, описано в разделе WebAssembly.

Требования

  • Binaryen 119 или новее, с wasm-as в PATH во время сборки.
  • Код, соответствующий требованиям Native Image: метаданные достижимости для рефлексии, ресурсов и прокси; никаких нативных зависимостей.
  • Хост с обработкой исключений WASM (и WASM GC для wasm-gc): Node.js 25+ или современный браузер.

Развёрнутому бандлу не нужны ни Elide, ни Binaryen.

Сборка полного проекта

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 собирает app-jar, затем компилирует его в web. name — базовое имя без .js и .wasm; optimization = "b" — режим быстрой сборки. Результат записывается в .dev/artifacts/native-image/:

ФайлНазначение
hello.jsЗагрузчик на JavaScript и точка входа.
hello.js.wasmМодуль WASM, который загружает hello.js.
hello.js.watТекстовая форма WASM для просмотра.
hello.js.mapКарта исходного кода для загрузчика, при sourceMap = true.

Развёртывайте hello.js и hello.js.wasm вместе. Kotlin и другие языки JVM работают так же, если упакованы в JAR. Попадание в кеш восстанавливает весь бандл; отключение sourceMap удаляет старый .js.map.

Выбор бэкенда и хоста

СвойствоЗначениеСмысл
backend"wasm-gc" (по умолчанию)Использует сборщик мусора WASM хоста.
backend"wasm-lm"Использует сборщик мусора в линейной памяти; загрузчик всё равно нужен, это не бинарный файл WASI.
runtime"generic" (по умолчанию)Загрузчик поддерживает браузеры и Node.
runtime"browser"Загрузчик, специализированный для браузеров.
runtime"node"Загрузчик, специализированный для API, совместимых с Node.
autoRuntrue (по умолчанию)Запускает программу, когда загрузчик загружен; false оставляет запуск встраивающей странице.
sourceMapfalse (по умолчанию)true создаёт hello.js.map.

Точка входа обязательна даже при autoRun = false. Ни одно значение runtime не нацелено на Cloudflare Workers, Fastly Compute или WASI. Общие поля (from, entrypoint, moduleName, options) описаны в разделе Native Image. WebImage не может быть входом артефакта образа контейнера.

Руководства по целям: Browser WASM и Edge WASM.

Запуск на серверном хосте

С runtime = "generic" или "node":

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

Запуск в браузере

С runtime = "browser" или "generic" и autoRun = true поместите этот index.html в .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

Откройте http://localhost:8000/; вывод появится в консоли браузера. URL file:// не работают.

Параметры компилятора

Блок options артефакта принимает параметры компилятора Native Image; какие из них действуют, зависит от бэкенда. Два случая относятся только к WebImage:

  • options.driverMode = "external" использует native-image из GRAALVM_HOME или JAVA_HOME; эта установка должна поддерживать бэкенды WebAssembly.
  • -H:EntryPointsConfig=config/entrypoints.json в options.flags задаёт точки входа; путь указывается относительно корня проекта, а изменение файла запускает пересборку.

Компиляция без манифеста проекта

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

Бандлы записываются в текущий каталог. Артефакт NativeImage с --tool:wasm-gc или --tool:wasm-lm в options.flags по-прежнему собирается. Чтобы перевести его на новый вид, замените класс на WebImage, уберите флаг и type, если он есть, и задайте backend.

Устранение неполадок

СимптомРешение
wasm-as не найденУстановите Binaryen и добавьте его в PATH сборки.
Внешний драйвер отклоняет бэкенд WebAssemblyУкажите в GRAALVM_HOME или JAVA_HOME установку, чей native-image его поддерживает, или используйте driverMode = "embedded".
Конфликтующие низкоуровневые параметрыУберите флаги бэкенда, среды выполнения, запуска и карты исходного кода; используйте типизированные свойства. Не переопределяйте Backend и свойство лаунчера.
Хост отклоняет инструкции WASMИспользуйте хост с обработкой исключений и, для wasm-gc, с WASM GC.
Браузер не может загрузить модульРаздавайте загрузчик и модуль вместе по HTTP; проверьте запрашиваемый URL.
elide run hello.js.wasm сообщает об отсутствующих импортахЗапустите вместо этого hello.js; модулю нужен его загрузчик.

Была ли эта страница полезной?