J2CL — Лучше поздно, чем никогда
Ещё никому не удалось опоздать на свои похороны.
Валентин Домиль
На прошлой неделе команда из Google наконец-то выложила исходники фреймворка J2CL, о котором говорили с 2015 года. Идея трансляции Java в JavaScript далеко не нова, и все уже давно набили шишек с Google Web Toolkit, однако этот продукт сообщество ждало как ни один другой — о нем говорили и делали выступления, но никто его не видел.
Прошло больше 3х лет с первого анонса и, кажется, что продукт потерял рынок даже не родившись. Сегодня у нас есть Scala.js, Kotlin.js и JSweet, не говоря уже о том, что веб-разработка захвачена TypeScript и для Java не осталось места. За такое время многие, даже самые преданные джависты, утратили веру в «Java для Front-end» и обуздали тот или иной JavaScript фреймворк.
Поскольку релиз всё-таки случился, давайте посмотрим, что получилось, и кому это может пригодиться.
Идея
Фундаментально, эмулировать JVM в браузере — задача сложная. Её долгое время решали разработчики Google Web Toolkit и достигли определенных успехов: построили транслятор, разработали механизмы эмуляции стандартной библиотеки Java, предоставили тулинг для разработки приложений.
Плюсов у такого подхода много: статическая типизация, возможность переиспользовать серверный код в браузере, готовые инструменты в виде Java IDE. Многие подходы, изначально заложенные в GWT мы сейчас видим в TypeScript, Web Pack и других инструментах фронтенд-разработки.
Старичка Google Web Toolkit не любили за его громоздкость и свою абстракцию для построения UI. Идея J2CL проще — позволить транслировать Java в JavaScript с наименьшими возможными расходами, так чтобы можно было легко вызывать Java из JavaScript и наоборот.
И если бы в далеком 2015 году действительно существовал качественный транслятор Java в JS без лишнего мусора, то неизвестно, как развивалась бы веб-разработка дальше.
Предыстория J2CL
В начале 2015 года команда Google GWT приняла трудное, но необходимое решение — разработать новый продукт, позволяющий задействовать Java во фронтенд-разработке.
В основном это было связано с изменением тенденций в веб-разработке и их новыми внутренними клиентами, которые рассматривали Java для веб не как изолированную экосистему, а как неотъемлемую часть большого стека. Это потребовало совершенно нового видения и создания инструментов с нуля, которые должны быть тесно интегрированы с остальной экосистемой.
При помощи GWT практически невозможно было достичь этих целей. И хотя в GWT присутствовали средства для двустороннего взаимодействия с JavaScipt, фреймворк не мог избавиться от большого багажа в виде UI, RPC библиотеки и других прикладных API.
Что это за зверь
Как утверждают разработчики, J2CL дает бесшовную интеграцию Java кода в JavaScript приложениях. Он представляет из себя простой и легковесный транслятор Java в JavaScript с упором на оптимизацию кода при помощи Closure Compiler.
- Можно легко смешивать Java и JavaScript в одном проекте, получая лучшее от каждого из языков.
- Позволяет переиспользовать код между серверным решением, веб-приложением и платформой Android. Доступно большое количество Java библиотек, таких как: Guava, Dagger и AutoValue.
- Современный и удобный. Сборка проектов построена на базе Bazel, поддерживается Live-reload.
- Проверенный. Утверждается, что J2CL используется в продакшене в проектах GSuite: GMail, Docs, Slides и Calendar.
По существу, J2CL транслирует исходный Java код в JavaScript код, не используя при этом байткод Java классов. Это означает, что как и в случае с Google Web Toolkit, для компиляции проекта нужны исходники для всех используемых библиотек. Кроме того, это вызывает вопросы о поддержке языковых возможностей Java в новых релизах. На данный момент, разработчики обещают поддержку всех синтаксических возможностей Java 11.
J2CL не будет поддерживать GWT Widgets, GWT RPC и другие GWT библиотеки — только базовую Java и механизм интеграции с JavaScript — JSInterop.
Т.е. это очень ограниченная версия GWT с полностью новым транспайлером. И, поскольку новый продукт больше не совместим с GWT он называется не GWT, а J2CL. В итоге, планируемый релиз GWT 3 будет представлять собой фреймворк поверх J2CL, где все прикладные библиотеки будут отделены от системного уровня самого транслятора.
Существующие ограничения совместимости с Java описаны на GitHub. В основном, они остались такими же как в GWT — отсутствует поддержка рефлексии, нет сетевого API Java. Но кое-что отличается — семантика массивов и списков не эмулируется, например не выполняется проверка вхождения индекса в границы массивов. Разработчики делают упор не на эмуляции поведения JVM, а на синтаксических средствах языка, чтобы обеспечить минимальные накладные расходы и не генерировать тонны JavaScript для обеспечения полной совместимости.
Хотя J2CL и готов к продакшену, его OSS версия все еще далека от этого. Например, есть проблемы со стартом проектов на Windows и разработчики не обещают стабильного API.
Выбор Bazel в качестве системы сборки для внутреннего продукта Google легко объяснить, но для сообщества в нём нет никаких плюсов, и для использования J2CL сейчас нет другого пути, кроме как изучить эту систему сборки. А пока остаётся только ждать пока сообщество напишет плагины для Maven / Gradle.
Пробуем
Во-первых, чтобы сейчас попробовать J2CL вам понадобится Mac OS или Linux.
Во-вторых, вам нужно установить Bazel — несколько экзотическую систему сборки от Google.
Теперь можно хоть что-то собрать, например, HelloWorld из официального репозитория: https://github.com/google/j2cl/tree/master/samples/helloworld
> bazel build src/main/java/com/google/j2cl/samples/helloworld:helloworld
Если мы заглянем в вывод, то будем приятно удивлены:
> cat bazel-bin/src/main/java/com/google/j2cl/samples/helloworld/helloworld.js
document.write('Hello from Java! and JS!');
Это конечно же ничего не доказывает, но очень радует своей минималистичностью после модулей GWT. Больших примеров приложений пока нет, будем ждать их появления.
Зачем это нужно если есть xxx.js
Ответ на вопрос зачем это нужно найти пока сложно. На первый взгляд, в J2CL заключена очень сильная идея — переиспользовать Java для фронтенда так же, как люди используют TypeScript. С другой стороны, кажется что проект опоздал.
Новые проекты транспайлеров в JS, такие как Kotlin.js и Scala.js реализованы в виде плагинов для компиляторов и им не требуется повторный разбор исходного кода. И в этом плане, J2CL — это шаг назад, поскольку ему нужны исходники, которые он будет разбирать.
Отдельный момент, это сам язык Java. Зачем писать на многословной Java, если можно и сервер, и клиентскую часть написать на лаконичном Kotlin?
Хотя, если сравнивать с другим похожим проектом — JSweet, то J2CL я доверяю больше. Тулинг у JSweet намного более дружелюбный и готовый к использованию, но у JSweet небольшое сообщество и он почти весь написан одним человеком.
Код говорите открытый?
Безусловно радует, что у проекта открытая лицензия Apache 2.0.
К сожалению, открытый код совсем не означает открытый процесс разработки. Самое большое разочарование наступило в сообществе от сложившейся ситуации, проект J2CL анонсирован 3 года назад, но никто не показывает его исходный код, нельзя повлиять на его итоговый API и никак не ускорить процесс разработки, потому что некуда слать патчи.
Будем надеяться, что ситуация наладится и продукт станет жизнеспособным.