三つ.Java DEVS用のJS : J 2 CL、クロージャ、バズなど.


WebGL/webxr/webgpuや何かを使ってJava上でWebベースのアプリケーションを書いてみたいとしましょう.オプションは何か

GWT


気になる最初のアプローチはGoogleでGWTを使用することです.それが15年前に始まったとき、GWTはすぐに非常に人気が高まり、Vaadin、ext GWT/GXT、SmartGWT、および他の多くのように、それに基づいて多くの驚くべきフレームワークを引き起こしました.しかし、それはその時間が最終的に来ているように見えます:Googleはコミュニティにそれを渡すGWTプロジェクトを残しました.

でなければ


GWTでなければ、JSWITB活動に従ってJWEY(構文マッパへの構文)またはTeavmのような非常に活発で人気のないプロジェクトがいくつかあります.将来的に我々のプロジェクトについて心配しないで、我々は多分安定して、よく維持される何かを選ぶでしょう.

J 2 CL


残された多くのオプションはありませんが、幸運にも私たちは、JWT後継者であるJavaScriptトランジスターを閉鎖するJava 2 Jを見ることができます.Googleによると、J 2 CLは広くGmail、受信トレイ、ドキュメント、スライド、カレンダーなどの多くのプロジェクトで使用されます.一見して、それはまさに我々が必要とするものです、しかし、1つの少しの問題があります.
J 2 CLは1つのタスクに対して責任があります.JavaクラスのセットをJavaScriptファイルのセットに置き換えます.JavaScriptのこのセットを1つの実行可能スクリプトにマージし、その最適化と最小化はGoogleのクロージャコンパイラの責任です.
GoogleはBazel(はい、モノレール、再現可能で安定したビルドなど)が大好きです.我々は通常、プロジェクトのためにMavenやGradleを使用します.幸運にも、我々は試みることができます j2cl-maven-plugin それはVertispanからコリン・オールワースによって開発されます、しかし、現在、Bazel方法を試みましょう.

バジルとJ 2 CL


バゼルとの第一歩は痛みです.何が良い、我々はJ 2 CLプロジェクトによって提供される2つのサンプルを再利用することができます、これらの2デモは私たちを始めるために十分以上です.要するに、私たちの最も重要なバゼル規則はj2cl_library and j2cl_application これは、ファイルのグループを設定し、実行可能なJavaScriptファイルにそれらを転送するために使用することができます.しかし、1つのより多くのステップが必要になるためには:アプリケーションのエントリポイントを定義する必要があります.これは2つの方法で行うことができます:私たちはそれのような手書きのJavaScriptスクリプトを使用して定義することができますannotation processor 私はこの目的のために、あまりにもデモを見て自由に感じた.
:詳細はj2cl_library and j2cl_application , あなたは驚くべきことを見ることができます.
ので、これまでのところ良い.私のお気に入りのIDEは、Googleによる公式のバゼルプラグインを持っているIntellijアイデアですが、あなたがplugin developed by salesforge .

ネイティブAPI


JavaからのブラウザAPIで動作するにはElemental2 , JavaScript APIの抽象化は、クロージャコンパイラに基づくJavaラッパーの集合です.
外部には、例えば、HTML要素やWebGLクラスのようなブラウザーAPIがあります.ところで、Elemental 2ライブラリは、JsInterop generator . Elemental 2はウェブAPIの全体のセットをカバーしません、しかし、私がそうしたように、それは欠落している部分を書くのは難しくありませんmy research project .
ピーター・ドナルドは印象的に働いているproject Akasha これは、最新のWebIDL仕様から生成されるAPIの統一セットを作成することを目的としています.それはほとんど最新の状態に保たれますが、Elemental 2と互換性がありません(事実として、それはビルトイン閉鎖外部と互換性がありません).

JSilop社


それで、我々には最も重要な部分以外はほとんどすべてがあるようです.Javaから利用できるJS.そして、それは少し複雑な部分です.JavaScriptを使用するにはJ2CL JsInterop API , しかし、ちょっとした問題があります.クロージャコンパイラは、(3)のほとんどを認識できなければなりません.jsオブジェクト.以下に2つのオプションがあります.
  • ソースクラスを3つに注釈します.閉鎖タイプ注釈によるJSと若干のリファクタリング(ユニフォームは、痛みです)をしてください.
    利点:最適化フェーズの間、クロージャコンパイラは、ツリーの揺れ、関数のインライン化やその他の最適化や結果のJavaScriptファイルサイズを減らすための他のテクニックを行います.これは、最も簡単で最速のオプションです.
    欠点:3つのような巨大なライブラリに型注釈を追加します.JSは時間がかかり難しいです.私の経験から、それは巨大なリファクタリングを必要とし、維持するのは非常に困難です.概念の証明を作成する私はハードワーク2ヶ月かかりました.
  • 純粋に使うthree.min.js として、Javascriptの注入やスクリプトのタグを介してロードします.
    利点:維持しやすい.
    短所
    トータルコードサイズthree.min.js + あなたのアプリのコード.
    IIJava抽象化を生成し、クロージャコンパイラをハッピーにする必要があります.
    しかし、3のための外部がありません.js
  • 外部


    それで、私は最後のオプションを選びました:純粋な使用three.min.js . いくつかのgooglingの後、私はよくサポートされたD - TSを見つけました.定義されたプロジェクトによるjs.
    さて、3つのような巨大なプロジェクトのためのゼロからの外部を書く、いいね.JSは一人のための圧倒的な仕事です.しかし、少しの問題がありました:D . TSを外部に変える方法?良いニュース:我々は使用することができますTsickle , プロジェクトはd . tsから外部を生成することを目的とした.

    ツァックル


    私にとって悪い知らせは、世代の後、結果として生じる外部が働かなかったということでした.名前空間とタイプの問題を修正するのに数時間かかって、enumは定数に置き換えられなければなりませんでした.J 2 CL GitHubの問題ページによると、チームは、近い将来にそれを改善するために取り組んでいます.

    発電機発電機


    OK、後3.JSの外部はほぼ期待通りに働き始めました@JSType それらの外部に基づいて、デモを終えた.

    デモ


    ここでデモを見てください.
    https://static.treblereel.org/bazel-three4g
    ソースコードはここで公開されています.
    https://github.com/treblereel/bazel_three_demo
    以下に、作業用デモクラスの様子を示します.
    package demo;
    
    import elemental2.dom.DomGlobal;
    import org.treblereel.gwt.elemental2.three.BoxGeometry;
    import org.treblereel.gwt.elemental2.three.Mesh;
    import org.treblereel.gwt.elemental2.three.MeshBasicMaterial;
    import org.treblereel.gwt.elemental2.three.MeshBasicMaterialParameters;
    import org.treblereel.gwt.elemental2.three.PerspectiveCamera;
    import org.treblereel.gwt.elemental2.three.Scene;
    import org.treblereel.gwt.elemental2.three.Texture;
    import org.treblereel.gwt.elemental2.three.TextureLoader;
    import org.treblereel.gwt.elemental2.three.WebGLRenderer;
    import org.treblereel.gwt.elemental2.three.WebGLRendererParameters;
    
    public class Demo {
    
        private PerspectiveCamera camera;
        private Scene scene;
        private Mesh mesh;
        private WebGLRenderer renderer;
    
        Demo() {
            camera = new PerspectiveCamera( 70, DomGlobal.window.innerWidth / DomGlobal.window.innerHeight, 1, 1000 );
            camera.position.z = 400;
            scene = new Scene();
            Texture texture = new TextureLoader().load("https://threejs.org/examples/textures/crate.gif" );
            MeshBasicMaterialParameters meshBasicMaterialParameters = MeshBasicMaterialParameters.create();
            meshBasicMaterialParameters.setMap(texture);
    
            BoxGeometry geometry = new BoxGeometry(200, 200, 200 );
            MeshBasicMaterial material = new MeshBasicMaterial(meshBasicMaterialParameters);
    
            mesh = new Mesh( geometry, material );
    
            scene.add( mesh );
    
            WebGLRendererParameters webGLRendererParameters = WebGLRendererParameters.create();
            webGLRendererParameters.setAntialias(true);
    
            renderer = new WebGLRenderer(webGLRendererParameters);
            renderer.setPixelRatio( DomGlobal.window.devicePixelRatio );
            renderer.setSize( DomGlobal.window.innerWidth, DomGlobal.window.innerHeight );
            DomGlobal.document.body.appendChild( renderer.domElement );
    
            DomGlobal.window.addEventListener("resize", evt -> onWindowResize(), false);
    
            animate();
        }
    
        private void  onWindowResize() {
    
            camera.aspect = DomGlobal.window.innerWidth / DomGlobal.window.innerHeight;
            camera.updateProjectionMatrix();
    
            renderer.setSize( DomGlobal.window.innerWidth, DomGlobal.window.innerHeight );
        }
    
        private void animate() {
            DomGlobal.requestAnimationFrame(timestamp -> animate());
            mesh.rotation.x += 0.005;
            mesh.rotation.y += 0.01;
            renderer.render( scene, camera );
        }
    }
    

    結論

  • J 2 CLでバゼルはこのようなタスクのために素晴らしい作品、バゼルは非常に高速です!
  • Java 3を維持するのは難しいことではない.JSラッパーは、我々だけの外部更新を維持する必要があります.
  • 巨大なマイナスはテストがまだソース化されていないということです、しかし、J 2 CL Mavenプラグインはそれのまわりで動きます.
  • デバッグ用のソースマップは動作しませんJ2CL and Closure GitHub issues page ). おそらくデバッグ中にソースマップをサポートするVertiSpanのクロージャコンパイラフォークを使用することができます.
  • GoogleがJ 2 CLを普及させようとしているように見えません.私は、彼らが現在の状態でOKであると思います.私は彼らが彼らのレガシーアプリケーションをサポートするためにそれを使用すると仮定することができます、私は間違っていることを願っています.
  • 三つ.JSはES 6に移行しています.使用可能ですES6 classes with J2CL しかし、3の場合ではない.JSの例のクラスは、DEVSは、前ES 6生態系との後方互換性を維持し続けることを願っています.
  • ヒント:いくつかの時間前に私は移植Quake2 by id Software to J2CL J 2 cl Mavenプラグインを使用してクォーツバックエンドを使用するので、見てみることができます、それは岩!
    P . S .それは私の非常に最初の記事以来ですので、私は何を修正または改善することができます聞いて満足しているよ.
    P . P . S .主な質問:我々は本当にすべてそれを必要としますか?yesの場合は、スタンドアロンライブラリとしてMavenに公開できます.