Kotlin/JS — это компилятор Kotlin-кода в JavaScript, позволяющий создавать frontend-приложения и веб-интерфейсы на языке Kotlin. В отличие от TypeScript, Kotlin/JS обеспечивает строгую статическую типизацию, поддержку корутин и бесшовную интеграцию с Kotlin Multiplatform. Начиная с Kotlin 1.8, компилятор использует IR-based бэкенд для генерации оптимизированного JavaScript-кода. По данным JetBrains, 2025, Kotlin/JS поддерживает интеграцию с NPM-экосистемой и TypeScript через автоматическую генерацию .d.ts файлов.
Главное
Kotlin/JS — это один из трёх бэкендов компилятора Kotlin (наряду с JVM и Native), предназначенный для трансляции Kotlin-кода в JavaScript. Разработанный JetBrains, Kotlin/JS позволяет писать веб-приложения на языке со строгой статической типизацией, сохраняя доступ к огромной экосистеме JavaScript-библиотек через механизм внешних объявлений. С момента первого стабильного релиза в Kotlin 1.3 компилятор прошёл путь от экспериментального бэкенда до production-ready инструмента, используемого в промышленных проектах.
Основное назначение Kotlin/JS — frontend-разработка с использованием Kotlin вместо JavaScript или TypeScript. Разработчики получают все возможности языка Kotlin: null safety, extension-функции, data-классы, coroutines и sealed-классы. При этом сгенерированный JavaScript-код может выполняться в любом современном браузере или в среде Node.js. Kotlin/JS особенно востребован в проектах Kotlin Multiplatform, где общий модуль (commonMain) доступен как для мобильных, так и для веб-приложений.
Экосистема Kotlin/JS включает фреймворки для создания пользовательских интерфейсов. Compose Multiplatform для веба использует Kotlin/JS как целевой бэкенд, что позволяет создавать декларативные UI-компоненты, работающие в браузере. Альтернативные решения включают обёртки для React — Kotlin Wrappers, которые предоставляют type-safe API для React, React Router и Redux.
Компиляция Kotlin/JS проходит через несколько этапов трансформации. Исходный Kotlin-код сначала компилируется в промежуточное представление (IR), затем оптимизируется и генерируется JavaScript-код. Начиная с Kotlin 1.8, старый бэкенд (JsBackend на основе AST) был полностью заменён на IR-бэкенд, который обеспечивает лучшую оптимизацию, меньший размер выходного кода и совместимость с TypeScript.
Ранее Kotlin/JS использовал JsBackend, который работал непосредственно с AST-деревом (Abstract Syntax Tree). Этот подход имел ограничения: сложность поддержки платформенных оптимизаций, отсутствие единого IR для всех бэкендов и неспособность генерировать TypeScript-декларации. Переход на IR-бэкенд решил эти проблемы, унифицировав компиляцию всех трёх бэкендов Kotlin и открыв путь для кросс-бэкендных оптимизаций.
Kotlin/JS поддерживает два режима сборки, определяющих формат и оптимизацию выходного кода. Режим production использует Webpack для сборки, минификации и tree-shaking. Режим development поддерживает Hot Module Replacement для быстрой итерации разработки. Выбор режима настраивается в build.gradle.kts через конфигурацию js.target.
kotlin {
js {
browser {
webpackTask {
outputFileName = "app.js"
}
}
binaries.executable()
}
}
Интеграция Kotlin/JS с NPM-экосистемой реализована через специальный DSL в build.gradle.kts. Разработчик объявляет npm-зависимости в конфигурации kotlin, указывая имя пакета и версию. Kotlin/JS автоматически подтягивает пакеты через менеджер пакетов npm или yarn. Для обеспечения type-safe доступа к JavaScript-библиотекам используются external-декларации, которые описывают типы и функции библиотеки для Kotlin-компилятора.
External-декларации — это Kotlin-объявления, помеченные ключевым словом external. Они сообщают компилятору, что реализация функции или класса находится в JavaScript-коде, а не в Kotlin. JetBrains предоставляет готовые наборы обёрток для популярных библиотек в составе Kotlin Wrappers, включая React, React Router, Redux, Emotion и MUI. Для библиотек, не имеющих готовых обёрток, разработчик может написать external-декларации вручную или использовать генератор TypeScript-привязок Dukat.
kotlin {
js {
browser { }
npm {
dependency("react", "18.3.1")
dependency("react-dom", "18.3.1")
devDependency("webpack", "5.92.0")
}
}
}
// External declaration for JavaScript library
@JsModule("date-fns")
external fun formatDistance(
date: Date, baseDate: Date
): String
TypeScript — неотъемлемая часть современного веба, и Kotlin/JS обеспечивает совместимость с ним через генерацию файлов .d.ts. При настройке js.generateTsDeclarations = true компилятор создаёт TypeScript-декларации для всех публичных Kotlin-функций и классов. Это позволяет TypeScript-проектам импортировать Kotlin-модули с полной поддержкой типов. Генерация TypeScript-деклараций работает только с IR-бэкендом и является одной из ключевых причин миграции со старого бэкенда.
IR-бэкенд (Intermediate Representation) — это единый бэкенд для всех трёх платформ Kotlin: JVM, JS и Native. Он использует общее промежуточное представление, которое проходит через несколько этапов оптимизации перед генерацией целевого кода. Для Kotlin/JS IR-бэкенд стал обязательным начиная с Kotlin 1.8.0, заменив старый AST-based бэкенд, который был помечен как deprecated.
Преимущества IR-бэкенда для Kotlin/JS включают улучшенную оптимизацию кода на уровне IR, уменьшение размера бандла за счёт dead code elimination и inline-оптимизаций, а также поддержку TypeScript-деклараций. IR-бэкенд также обеспечивает корректную обработку inline-функций, reified-дженериков и suspend-функций при трансляции в JavaScript, что было проблематично в старом бэкенде.
| Характеристика | Старый бэкенд (AST) | IR-бэкенд |
|---|---|---|
| TypeScript-декларации | Не поддерживались | Генерируются автоматически |
| Dead code elimination | Ограниченная | Полная, на уровне IR |
| Inline-функции | Проблемы с корректностью | Корректная обработка |
| Reified дженерики | Не поддерживались | Поддерживаются |
| Размер бандла | Базовый | На 20–30% меньше |
Полноценный Kotlin/JS проект начинается с конфигурации build.gradle.kts. Плагин kotlin multiplatform позволяет настроить Kotlin/JS как одну из целевых платформ. Рассмотрим пример настройки для веб-приложения с React.
plugins {
kotlin("multiplatform") version "2.0.21"
id("org.jetbrains.kotlin-wrappers") version "1.0.0-pre.775"
}
kotlin {
js {
browser { }
binaries.executable()
generateTsDeclarations = true
}
}
dependencies {
implementation(enwraps(react, reactDom))
}
После настройки можно писать React-компоненты на Kotlin. Kotlin Wrappers предоставляют type-safe API для React, включая функциональные компоненты, хуки и JSX-подобный синтаксис через DSL-построители. Пример компонента Counter демонстрирует работу с useState и обработчиками событий.
@OptIn(ExperimentalWrapperApi::class)
val Counter = FC<Props> {
var count = useState(0)
div {
+"Counter value: ${count.component1()}"
button {
onClick = { count.component2()(count.component1() + 1) }
+"Increment"
}
}
}
fun main() {
createRoot(document.getElementById("root")!!).render(
createElement(Counter)
)
}
Сборка Kotlin/JS проекта выполняется через Gradle-задачи. jsDevelopmentRun запускает dev-сервер Webpack с HMR для разработки. jsProductionExecutableCompileSync генерирует production-бандл с минификацией и tree-shaking. Финальный HTML-файл, подключающий скомпилированный JavaScript, генерируется плагином webpack и располагается в build/dist.
// Start dev server with HMR
./gradlew jsDevelopmentRun
// Production build with minification
./gradlew jsProductionExecutableCompileSync
// Output in build/dist/productionExecutable/
TypeScript — основной конкурент Kotlin/JS в области типизированного JavaScript. Оба языка компилируются в JavaScript и добавляют статическую типизацию поверх динамического JS. Однако Kotlin/JS предлагает ряд преимуществ: null safety по умолчанию, sealed-классы, корутины и бесшовную интеграцию с Kotlin Multiplatform. TypeScript, в свою очередь, имеет более широкое сообщество, больше готовых библиотек с типами и более зрелую экосистему.
Производительность разработки на Kotlin/JS может быть выше для команд, уже использующих Kotlin в других частях проекта, так как не требуется переключение между языками. TypeScript остаётся более популярным выбором для чистых веб-проектов, где не используется Kotlin Multiplatform. Однако с ростом популярности Compose Multiplatform для веба Kotlin/JS набирает позиции как альтернатива React и Angular.
| Характеристика | Kotlin/JS | TypeScript |
|---|---|---|
| Null safety | По умолчанию | strictNullChecks опционально |
| Sealed-классы | Поддерживаются | Через union types |
| Корутины | Нативно | Через async/await |
| KMM-интеграция | Полная | Отсутствует |
| Размер сообщества | Малое | Огромное |
| Готовые типы для библиотек | Ограниченные (DefinitelyTyped через Dukat) | DefinitelyTyped (тысячи библиотек) |
Выбор между Kotlin/JS и TypeScript зависит от контекста проекта. Если команда уже использует Kotlin Multiplatform или планирует начать, Kotlin/JS — логичный выбор для frontend-части. Для изолированного веб-проекта TypeScript остаётся более прагматичным решением благодаря доступности готовых типов для JavaScript-библиотек и большему количеству разработчиков на рынке.
Часто задаваемые вопросы
Да, JetBrains предоставляет Kotlin Wrappers — type-safe Kotlin-обёртки для React, React Router и Redux. Они позволяют писать React-компоненты на Kotlin с полной поддержкой хуков и JSX-подобного DSL.
При включении generateTsDeclarations = true Kotlin/JS генерирует .d.ts файлы для всех публичных API. TypeScript-проекты могут импортировать Kotlin-модули с полной типизацией как обычные npm-пакеты.
Размер бандла зависит от используемых библиотек. Минимальное приложение Hello World занимает около 300 КБ включая Kotlin stdlib. С React и Kotlin Wrappers размер увеличивается до 400–600 КБ.
Да, Kotlin/JS можно использовать для разработки serverless-функций и консольных утилит под Node.js. Для этого в конфигурации нужно указать js.nodejs вместо js.browser.
Kotlin/Wasm — экспериментальный бэкенд для WebAssembly, в то время как Kotlin/JS генерирует JavaScript-код. Wasm обеспечивает более высокую производительность, но имеет ограниченный доступ к браузерному DOM.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также