انتقل إلى المحتوى

WebImage: من JVM إلى WebAssembly

صرّف Java أو Kotlin إلى وحدة WebAssembly مع محمِّل JavaScript باستخدام مُخرَج WebImage في Elide: المتطلبات المسبقة، والواجهات الخلفية، والمضيفات، وخيارات المُصرّف.

في هذه الصفحة

يصرّف المُخرَج WebImage شيفرة JVM البايتية (bytecode) إلى محمِّل JavaScript ووحدة WASM. لتشغيل ملف WASM أو WASI ثنائي موجود، راجع WebAssembly.

المتطلبات المسبقة

  • Binaryen بالإصدار 119 أو أحدث، مع وجود wasm-as على PATH وقت البناء.
  • شيفرة تستوفي متطلبات Native Image: بيانات وصفية لقابلية الوصول تخص الانعكاس والموارد والكائنات الوكيلة (proxies)؛ ودون تبعيات أصلية.
  • مضيف يدعم معالجة الاستثناءات في 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"محمِّل مخصص للواجهات المتوافقة مع 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/؛ تظهر المخرجات في وحدة تحكم المتصفح. ولا تعمل عناوين 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؛ وتحقق من العنوان المطلوب.
elide run hello.js.wasm يبلّغ عن عمليات استيراد مفقودةشغّل hello.js بدلًا منه؛ فالوحدة تحتاج إلى محمِّلها.

هل كانت هذه الصفحة مفيدة؟