Copenhagen Denmark
THE STATE OF KOTLIN/JS SEBASTIAN AIGNER
@TrueSebi
THE STATE OF KOTLIN/JS SEBASTIAN AIGNER @TrueSebi Copenhagen - - PowerPoint PPT Presentation
THE STATE OF KOTLIN/JS SEBASTIAN AIGNER @TrueSebi Copenhagen Denmark About me Hi, Im Sebastian! Developer Advocate at JetBrains Focus on Kotlin and Fig. 1: me Education twitter.com/TrueSebi Kotlin & the Web
Copenhagen Denmark
@TrueSebi
JetBrains
Education
twitter.com/TrueSebi github.com/SebastianAigner sebastian.aigner@jetbrains.com
Why is Kotlin/JS exciting? Who can benefit the most from K/JS?
familiar with!
Unlock the power of code sharing!
development
– Code Sharing – Model Sharing – Knowledge sharing
now / soon™
Kotlin/JS target
What is currently available and will be available shortly.
K
l i n F r
t e n d P l u g i n kotlin.js Plugin Kotlin/Multiplatform Plugin kotlin2js Plugin Create-React-Kotlin-App IDEA JS
Will be deprecated
Kotlin/Multiplatform Plugin Kotlin Frontend Plugin kotlin.js Plugin kotlin2js Plugin
From kotlin2js / frontend plugin to kotlin.js
– Same features available – Ever-improving documentation
From kotlin.js plugin to multiplatform
– Minimal changes required – Future-proof DSL for JS target(s) already!
Kotlin/Multiplatform kotlin.js Plugin
plugins { id("org.jetbrains.kotlin.js") version "1.3.61" } group = "org.example" version = "1.0-SNAPSHOT" repositories { mavenCentral() } dependencies { implementation(kotlin("stdlib-js")) } kotlin { target { browser { testTask { useKarma { useChromeHeadless() } } } } } plugins { kotlin("multiplatform") version "1.3.61" } group = "org.example" version = "1.0-SNAPSHOT" repositories { mavenCentral() } kotlin { js { browser { testTask { useKarma { useChromeHeadless() } } } } sourceSets { val jsMain by getting { dependencies { implementation(kotlin("stdlib-js")) } } val commonMain by getting { dependencies { implementation(kotlin("stdlib-common")) } } val commonTest by getting { dependencies { implementation(kotlin("test-common")) implementation(kotlin("test-annotations-common")) } } } }
Start your new projects with the kotlin.js plugin
…or do MPP!
package.json
>1M!
Webpack – without the hassle!
No manual environment management necessary
files
– package.json – webpack.config.js
package.json
kotlin { target.nodejs() sourceSets.main { dependencies { implementation(kotlin("stdlib-js")) implementation(npm("uuid", "3.3.3")) implementation(npm("chalk")) } } } { "main": "kotlin/playgroundkts.js", "devDependencies": {}, "dependencies": { "kotlin": "1.3.61", "kotlin-test-js-runner": "1.3.61", "kotlin-test": "1.3.61", "uuid": "3.3.3", "chalk": "*" }, "peerDependencies": {}, "optionalDependencies": {}, "bundledDependencies": [], "name": "playgroundkts", "version": "1.0.0-SNAPSHOT" }
package.json build.gradle.kts
Gradle Task FS watcher Kotlin Compiler Webpack Dev Server Chrome Browser
./gradlew -.continous run
Testing – Test Runners & Browsers
kotlin.target.browser { testTask { useKarma { useIe() useFirefox() useChrome() useChromeHeadless() useOpera() } } }
as fallback
Official Docs!
fun main() { val canvas = document.getElementById("myCanvas") as HTMLCanvasElement val ctx = canvas.getContext("2d") as CanvasRenderingContext2D with(ctx) { repeat(30) { beginPath() fillStyle = listOf("red", "green", "blue").random() rect(randomCoordinate(), randomCoordinate(), 20.0, 20.0) fill() closePath() } } } fun randomCoordinate() = Random.nextDouble(0.0, 200.0)
1 5 8 L i n e s
K
l i n / J S !
standard library
separate release cycles
… a n d f
t h e N
e . j s A P I t
Bring the Kotlin Ecosystem to JS!
kx.serialization Coroutines Ktor Clients . . .
N
e e d f
N P M p u b l i s h e d l i b s ! implementation("io.ktor:ktor-client-core:$ktor_version") implementation("io.ktor:ktor-client-js:$ktor_version") implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:0.13.0") plugins { //. . . id("kotlinx-serialization") version "1.3.60" }
Bring the JS ecosystem to Kotlin!
sourceSets.main { dependencies { implementation(npm("react-minimal-pie-chart")) implementation(npm("react-spinkit")) } }
Dynamic vs static typing
@JsModule("react-spinkit") @JsNonModule external val Spinner: RClass<dynamic> Spinner { attrs.asDynamic().name = spinnerNames.random() attrs.asDynamic().color = colors.random() }
@file:JsModule("react-minimal-pie-chart") @file:JsNonModule import react.RClass import react.RProps external interface PieChartProps: RProps { var data: Array<PiePoint> var lineWidth: Int var paddingAngle: Int var rounded: Boolean var label: Boolean var animate: Boolean var labelStyle: dynamic var labelPosition: Int } @JsName("default") external val PieChart: RClass<PieChartProps> class PiePoint(val title: String, val value: Int, val color: String)
Standardized type declarations
packages
via DefinitelyTyped
Automatic declaration generation
automatically
P
e r i n g B r
s e r & N
e !
implementation(npm("left-pad", "1.3.0")) declare function leftPad( str: string|number, len: number, ch?: string|number ): string; declare namespace leftPad { } export = leftPad; //... all external, all @JsModule("left-pad") fun leftPad(str: String, len: Number, ch: String? = definedExternally): String fun leftPad(str: String, len: Number, ch: Number? = definedExternally): String fun leftPad(str: Number, len: Number, ch: String? = definedExternally): String fun leftPad(str: Number, len: Number, ch: Number? = definedExternally): String fun leftPad(str: String, len: Number): String fun leftPad(str: Number, len: Number): String
println(leftPad("Yay Kotlin!", 50))
warning workspace-aggregator > kotlin-js-demo-1.3.50 > left-pad@1.3.0: use String.prototype.padStart()
E v e n w i t h u n i
t y p e s !
What changes await Kotlin/JS in the near future.
targets
Multi-platform compiler plugins
– Dead code eliminiation – No need to ship a full stdlib anymore!
Some numbers: kotlinx.coroutines w/ IR
Co Code size for example project using coroutines Current Backend IR Backend After Compilation 3.9 MiB 1.1 MiB After JS DCE 713 KiB 430 KiB After Bundle 329 KiB 184 KiB After ZIP 74 KiB 40 KiB IR IR Ba Backend, IR IR DCE, Go Google le Clo losure Comp mpile iler: 116 KiB, , zipped ed 30 KiB
changes
continuous builds
TypeScript, JSDoc
– Static analyzers – JavaScript IDE suggestions
M
e f u n i n h y b r i d a p p s !
@JsExport class TodoItem( val id: Int, val text: String, var completed: Boolean ) { fun complete() { completed = true } }
class TodoItem { constructor( id: number, text: string, completed: boolean ) readonly id: number; readonly text: string; completed: boolean; complete(): void }
@JsExport val todoItems = arrayOf<TodoItem>() @JsExport fun finishAll(items: Array<TodoItem>) { items.forEach { it.completed } }
const todoItems: Array<todoapp.TodoItem> function finishAll( items: Array<todoapp.TodoItem> ): void
– Public declarations available outside module
Action may be required!
(@JsExport)
– Old BE libraries won’t work with IR – IR libraries won’t work with old BE
backend!
– EAP – Release Blog Post
T r y i t s
!
Interesting topics on the mind of the Kotlin/JS team. No promises!
functionality
Challenge: Custom tooling per framework
Getting started, learning more, and giving feedback.
C
e w i n s t u f f !
S
!
Sebastian Aigner @TrueSebi