Kotlin/JS — to kompilator kodu Kotlin do JavaScript, umożliwiający tworzenie aplikacji frontendowych i interfejsów webowych w języku Kotlin. W przeciwieństwie do TypeScript, Kotlin/JS zapewnia ścisłe statyczne typowanie, wsparcie dla korutyn i bezszwową integrację z Kotlin Multiplatform. Od Kotlin 1.8 kompilator używa backendu IR do generowania zoptymalizowanego kodu JavaScript. Według danych JetBrains, 2025, Kotlin/JS obsługuje integrację z ekosystemem NPM oraz TypeScript przez automatyczne generowanie plików .d.ts.
Najważniejsze
Kotlin/JS — to jeden z trzech backendów kompilatora Kotlin (obok JVM i Native), przeznaczony do translacji kodu Kotlin do JavaScript. Opracowany przez JetBrains, Kotlin/JS pozwala pisać aplikacje webowe w języku ze ścisłym statycznym typowaniem, zachowując dostęp do ogromnego ekosystemu bibliotek JavaScript poprzez mechanizm zewnętrznych deklaracji. Od pierwszego stabilnego wydania w Kotlin 1.3 kompilator przeszedł drogę od eksperymentalnego backendu do narzędzia gotowego do produkcji, używanego w projektach przemysłowych.
Głównym przeznaczeniem Kotlin/JS jest tworzenie frontendu z użyciem Kotlin zamiast JavaScript lub TypeScript. Deweloperzy otrzymują wszystkie możliwości języka Kotlin: null safety, funkcje rozszerzające, klasy danych, korutyny i klasy sealed. Wygenerowany kod JavaScript może działać w każdej nowoczesnej przeglądarce lub w środowisku Node.js. Kotlin/JS jest szczególnie poszukiwany w projektach Kotlin Multiplatform, gdzie wspólny moduł (commonMain) jest dostępny zarówno dla aplikacji mobilnych, jak i webowych.
Ekosystem Kotlin/JS obejmuje frameworki do tworzenia interfejsów użytkownika. Compose Multiplatform dla sieci używa Kotlin/JS jako docelowego backendu, co pozwala tworzyć deklaratywne komponenty UI działające w przeglądarce. Alternatywne rozwiązania obejmują opakowania dla React — Kotlin Wrappers, które zapewniają type-safe API dla React, React Router i Redux.
Kompilacja Kotlin/JS przechodzi przez kilka etapów transformacji. Kod źródłowy Kotlin jest najpierw kompilowany do pośredniej reprezentacji (IR), następnie optymalizowany i generowany jest kod JavaScript. Od Kotlin 1.8 stary backend (JsBackend oparty na AST) został całkowicie zastąpiony przez IR-backend, który zapewnia lepszą optymalizację, mniejszy rozmiar kodu wyjściowego i zgodność z TypeScript.
Wcześniej Kotlin/JS używał JsBackend, który działał bezpośrednio na drzewie AST (Abstract Syntax Tree). To podejście miało ograniczenia: złożoność wsparcia optymalizacji platformowych, brak jednolitego IR dla wszystkich backendów i niemożność generowania deklaracji TypeScript. Przejście na IR-backend rozwiązało te problemy, unifikując kompilację wszystkich trzech backendów Kotlin i otwierając drogę do optymalizacji międzybackendowych.
Kotlin/JS obsługuje dwa tryby kompilacji, określające format i optymalizację kodu wyjściowego. Tryb production używa Webpack do kompilacji, minifikacji i tree-shaking. Tryb development wspiera Hot Module Replacement dla szybkiej iteracji w trakcie tworzenia. Wybór trybu konfiguruje się w build.gradle.kts przez konfigurację js.target.
kotlin {
js {
browser {
webpackTask {
outputFileName = "app.js"
}
}
binaries.executable()
}
}
Integracja Kotlin/JS z ekosystemem NPM jest zrealizowana przez specjalny DSL w build.gradle.kts. Deweloper deklaruje zależności npm w konfiguracji kotlin, podając nazwę pakietu i wersję. Kotlin/JS automatycznie pobiera pakiety przez menedżera pakietów npm lub yarn. Aby zapewnić type-safe dostęp do bibliotek JavaScript, używane są deklaracje external, które opisują typy i funkcje biblioteki dla kompilatora Kotlin.
Deklaracje external — to deklaracje Kotlin oznaczone słowem kluczowym external. Informują one kompilator, że implementacja funkcji lub klasy znajduje się w kodzie JavaScript, a nie w Kotlin. JetBrains dostarcza gotowe zestawy opakowań dla popularnych bibliotek w ramach Kotlin Wrappers, w tym React, React Router, Redux, Emotion i MUI. Dla bibliotek, które nie mają gotowych opakowań, deweloper może napisać deklaracje external ręcznie lub użyć generatora wiązań TypeScript Dukat.
kotlin {
js {
browser { }
npm {
dependency("react", "18.3.1")
dependency("react-dom", "18.3.1")
devDependency("webpack", "5.92.0")
}
}
}
// Zewnętrzna deklaracja dla biblioteki JavaScript
@JsModule("date-fns")
external fun formatDistance(
date: Date, baseDate: Date
): String
TypeScript — nieodłączna część nowoczesnego webu, a Kotlin/JS zapewnia z nim zgodność przez generowanie plików .d.ts. Przy ustawieniu js.generateTsDeclarations = true kompilator tworzy deklaracje TypeScript dla wszystkich publicznych funkcji i klas Kotlin. Pozwala to projektom TypeScript importować moduły Kotlin z pełnym wsparciem typów. Generowanie deklaracji TypeScript działa tylko z IR-backendem i jest jednym z kluczowych powodów migracji ze starego backendu.
IR-backend (Intermediate Representation) — to jednolity backend dla wszystkich trzech platform Kotlin: JVM, JS i Native. Używa wspólnej pośredniej reprezentacji, która przechodzi przez kilka etapów optymalizacji przed wygenerowaniem kodu docelowego. Dla Kotlin/JS IR-backend stał się obowiązkowy od Kotlin 1.8.0, zastępując stary backend oparty na AST, który został oznaczony jako deprecated.
Zalety IR-backendu dla Kotlin/JS obejmują ulepszoną optymalizację kodu na poziomie IR, zmniejszenie rozmiaru pakietu dzięki eliminacji martwego kodu i optymalizacjom inline, a także wsparcie dla deklaracji TypeScript. IR-backend zapewnia również poprawną obsługę funkcji inline, dżeneryków reified i funkcji suspend przy translacji do JavaScript, co było problematyczne w starym backendzie.
| Cecha | Stary backend (AST) | IR-backend |
|---|---|---|
| Deklaracje TypeScript | Nieobsługiwane | Generowane automatycznie |
| Eliminacja martwego kodu | Ograniczona | Pełna, na poziomie IR |
| Funkcje inline | Problemy z poprawnością | Poprawna obsługa |
| Dżeneryki reified | Nieobsługiwane | Obsługiwane |
| Rozmiar pakietu | Podstawowy | O 20–30% mniejszy |
Pełnoprawny projekt Kotlin/JS zaczyna się od konfiguracji build.gradle.kts. Wtyczka kotlin multiplatform pozwala skonfigurować Kotlin/JS jako jedną z platform docelowych. Rozważmy przykład konfiguracji dla aplikacji webowej z 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))
}
Po konfiguracji można pisać komponenty React w Kotlin. Kotlin Wrappers zapewniają type-safe API dla React, w tym komponenty funkcyjne, hooki i składnię podobną do JSX przez budownicze DSL. Przykład komponentu Counter demonstruje pracę z useState i obsługą zdarzeń.
@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)
)
}
Kompilacja projektu Kotlin/JS odbywa się przez zadania Gradle. jsDevelopmentRun uruchamia serwer deweloperski Webpack z HMR do tworzenia. jsProductionExecutableCompileSync generuje pakiet produkcyjny z minifikacją i tree-shaking. Końcowy plik HTML podłączający skompilowany JavaScript jest generowany przez wtyczkę webpack i znajduje się w build/dist.
// Uruchom serwer deweloperski z HMR
./gradlew jsDevelopmentRun
// Kompilacja produkcyjna z minifikacją
./gradlew jsProductionExecutableCompileSync
// Wynik w build/dist/productionExecutable/
TypeScript — główny konkurent Kotlin/JS w dziedzinie typowanego JavaScript. Oba języki kompilują się do JavaScript i dodają statyczne typowanie na dynamicznym JS. Jednak Kotlin/JS oferuje szereg zalet: null safety domyślnie, klasy sealed, korutyny i bezszwową integrację z Kotlin Multiplatform. TypeScript z kolei ma większą społeczność, więcej gotowych bibliotek z typami i bardziej dojrzały ekosystem.
Wydajność tworzenia w Kotlin/JS może być wyższa dla zespołów już używających Kotlin w innych częściach projektu, ponieważ nie wymaga przełączania między językami. TypeScript pozostaje bardziej popularnym wyborem dla czystych projektów webowych, w których nie używa się Kotlin Multiplatform. Jednak wraz z rosnącą popularnością Compose Multiplatform dla sieci, Kotlin/JS zyskuje pozycję jako alternatywa dla React i Angular.
| Cecha | Kotlin/JS | TypeScript |
|---|---|---|
| Null safety | Domyślnie | strictNullChecks opcjonalnie |
| Klasy sealed | Obsługiwane | Przez typy unii |
| Korutyny | Natywnie | Przez async/await |
| Integracja KMM | Pełna | Brak |
| Wielkość społeczności | Mała | Ogromna |
| Gotowe typy dla bibliotek | Ograniczone (DefinitelyTyped przez Dukat) | DefinitelyTyped (tysiące bibliotek) |
Wybór między Kotlin/JS a TypeScript zależy od kontekstu projektu. Jeśli zespół już używa Kotlin Multiplatform lub planuje zacząć, Kotlin/JS jest logicznym wyborem dla części frontendowej. Dla izolowanego projektu webowego TypeScript pozostaje bardziej pragmatycznym rozwiązaniem dzięki dostępności gotowych typów dla bibliotek JavaScript i większej liczbie deweloperów na rynku.
Często zadawane pytania
Tak, JetBrains udostępnia Kotlin Wrappers — type-safe opakowania Kotlin dla React, React Router i Redux. Pozwalają one pisać komponenty React w Kotlin z pełnym wsparciem hooków i składni podobnej do JSX.
Po włączeniu generateTsDeclarations = true Kotlin/JS generuje pliki .d.ts dla wszystkich publicznych API. Projekty TypeScript mogą importować moduły Kotlin z pełnym typowaniem jak zwykłe pakiety npm.
Rozmiar pakietu zależy od używanych bibliotek. Minimalna aplikacja Hello World zajmuje około 300 KB z Kotlin stdlib. Z React i Kotlin Wrappers rozmiar wzrasta do 400–600 KB.
Tak, Kotlin/JS można używać do tworzenia funkcji serverless i narzędzi konsolowych pod Node.js. W tym celu w konfiguracji należy wskazać js.nodejs zamiast js.browser.
Kotlin/Wasm — to eksperymentalny backend dla WebAssembly, podczas gdy Kotlin/JS generuje kod JavaScript. Wasm zapewnia wyższą wydajność, ale ma ograniczony dostęp do DOM przeglądarki.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również