building progressive web apps in kotlin erik hellman...building progressive web apps in kotlin erik...

81
Copenhagen Denmark BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman

Upload: others

Post on 26-Apr-2021

4 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

CopenhagenDenmark

BUILDING PROGRESSIVE WEB APPS IN KOTLINErik Hellman

@ErikHellman

Page 2: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Actual Cross Platform!

Page 3: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts
Page 4: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts
Page 5: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts
Page 6: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts
Page 7: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Types - They’re pretty great!

Page 8: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

lib.dom.d.ts

Type definitions for JavaScript DOM APIs

Page 9: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts
Page 10: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

import { LitElement, html, property, customElement } from 'lit-element';

@customElement('simple-greeting')export class SimpleGreeting extends LitElement { @property() name = 'World';

render() { return html`<p>Hello, ${this.name}!*/p>`; }}

Page 11: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

class SimpleGreeting : LitElement() { private var name: String = "World"

override fun render(): dynamic { return "<p>Hello, $name!*/p>" }

companion object { val properties = json("name" to String*:class) }}

Page 12: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

JavaScript can be weird...function javaScriptIsWeird(wantNumber) { if (wantNumber) { return 42 } else { return "Here is some text" }}

Page 13: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

TypeScript can also be weird! :)function typeScriptExample(wantNumber: boolean): number | string { if (wantNumber) { return 42 } else { return "Here is some text" }}

Page 14: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

“It’s complicated…”

Page 15: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Kotlin/JS

Page 16: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Kotlin/JS - build.gradle.ktsplugins { id("org.jetbrains.kotlin.js") version "1.3.61" }

group = "se.hellsoft"version = "1.0-SNAPSHOT"

repositories { mavenCentral() jcenter()}

kotlin { target { nodejs() browser() }

sourceSets["main"].dependencies { implementation(kotlin("stdlib-js")) }}

Page 17: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Kotlin/JS - Main.ktimport kotlin.browser.window

val document = window.document

fun main() { val button = document.querySelector("#button") *: return button.addEventListener("click", { console.log("Clicked on button!}") })}

Page 18: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Kotlin/JS - main.jsif (typeof kotlin **= 'undefined') { throw new Error("Error loading module 'test'. Its dependency 'kotlin' was not found. Please, check whether 'kotlin' is loaded prior to 'test'.");}var test = function (_, Kotlin) { 'use strict'; var Unit = Kotlin.kotlin.Unit; var document; function main$lambda(it) { console.log('Clicked on button!}'); return Unit; } function main() { var tmp$; tmp$ = document.querySelector('#button'); if (tmp$ *= null) { return; } var button = tmp$; button.addEventListener('click', main$lambda); } Object.defineProperty(_, 'document', { get: function () { return document; } }); _.main = main; document = window.document; main(); Kotlin.defineModule('test', _); return _;}(typeof test **= 'undefined' ? {} : test, kotlin);

Page 19: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Kotlin/JS - main.jsvar main = function (_, Kotlin) { **. function main$lambda(it) { console.log('Clicked on button!}'); return Unit; } function main() { var tmp$; tmp$ = document.querySelector('#button'); if (tmp$ *= null) { return; } var button = tmp$; button.addEventListener('click', main$lambda); } **. main(); **.}(typeof main **= 'undefined' ? {} : main, kotlin);

Page 20: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Progressive Web Apps

Page 21: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Reliable - Fast - Engaginghttps://developers.google.com/web/progressive-web-apps

Page 22: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

manifest.json

Web App Manifest Service Worker

Web UI

Page 23: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Web App Manifest - manifest.json{ "short_name": "Maps", "name": "Google Maps", "icons": [ { "src": "/images/icons-192.png", "type": "image/png", "sizes": "192x192" }, { "src": "/images/icons-512.png", "type": "image/png", "sizes": "512x512" } ], "start_url": "/maps/?source=pwa", "background_color": "#3367D6", "display": "standalone", "scope": "/maps/", "theme_color": "#3367D6"}

Page 24: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts
Page 25: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts
Page 26: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Service Workerindex.html

main.js

service-worker.js

Page 27: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Service Worker - index.html<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Kotlin/JS PWA Demo*/title>*/head><body><div id="appContent">*/div>*/body><script src="main.js">*/script>*/html>

Page 28: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Service Worker - main.jsif ('serviceWorker' in navigator) { navigator.serviceWorker .register('/service-worker.js') .then(() *> { console.log('Service Worker registered!') }) .catch(error *> { console.error('Service Worker registration failed!', error) });}

Page 29: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Service Worker - service-worker.jsself.addEventListener('install', event *> { console.log('Service Worker installed!')});

self.addEventListener('activate', event *> { console.log('Service Worker is now active!')});

self.addEventListener('fetch', event *> { const url = new URL(event.request.url);

if (url.origin **= location.origin *& url.pathname **= '/dog.svg') { event.respondWith(caches.match('/cat.svg')); }});

Page 30: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Service Worker

Page 31: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Kotlin/JS - Service Workers

Page 32: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Kotlin/JS - Main.ktimport kotlin.browser.window

fun main() { window.addEventListener("load", { window.navigator.serviceWorker .register("/service-worker.js") .then { console.log("Service worker registered!") } .catch { console.error("Service Worker registration failed: $it") } })}

Page 33: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Kotlin/JS Output

Input

Output

Page 34: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Kotlin/JS - Main.ktimport kotlin.browser.window

fun main() { window.addEventListener("load", { window.navigator.serviceWorker .register("/service-worker.js") .then { console.log("Service worker registered!") } .catch { console.error("Service Worker registration failed: $it") } })}

How can we create this file?

Page 35: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

First solution - 2 Gradle modules!

2 copies of Kotlin/JS stdlib!!!

Page 36: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Second solution - use the same script!

Page 37: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Kotlin/JS - Main.ktimport kotlin.browser.window

fun main() { window.addEventListener("load", { window.navigator.serviceWorker .register("/kotlin-js-pwa.js") .then { console.log("Service worker registered!") } .catch { console.error("Service Worker registration failed: $it") } })}

Same script as we’re currently running in!

Page 38: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

external val self: ServiceWorkerGlobalScope

fun main() { try { window.addEventListener("load", { window.navigator.serviceWorker.register("/kotlin-js-pwa.js") }) } catch (t: Throwable) { self.addEventListener("install", { event -> console.log("Service Worker installed!") }) self.addEventListener("activate", { event -> console.log("Service Worker is now active!") }) }}

Kotlin/JS - Main.kt Throws ReferenceError in a Service Worker!

Page 39: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

external val self: ServiceWorkerGlobalScope

fun main() { try { window.addEventListener("load", { window.navigator.serviceWorker.register("/kotlin-js-pwa.js") }) } catch (t: Throwable) { self.addEventListener("install", { event -> console.log("Service Worker installed!") }) self.addEventListener("activate", { event -> console.log("Service Worker is now active!") }) }}

Kotlin/JS - Main.kt Reference to Service Worker scope

Page 40: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Implementing the Service Worker

Page 41: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Kotlin/JS - Installing Service Workerconst val CACHE_NAME = "my-site-cache-v1"val urlsToCache = arrayOf( "/", "/styles/main.css", "/images/dog.svg", "/images/cat.cvg")external val self: ServiceWorkerGlobalScope

fun installServiceWorker() { self.addEventListener("install", { event -> event as InstallEvent event.waitUntil( self.caches.open(CACHE_NAME) .then { it.addAll(urlsToCache) } ) }}

Reference to Service Worker scope

Page 42: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Kotlin/JS - Implementing offline cacheself.addEventListener("fetch", { event -> event as FetchEvent self.caches.match(event.request) .then { it as Response? return@then it *: self.fetch(event.request) }})

Page 43: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Calling your HTTP API with Kotlin/JS

Page 44: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Kotlinx.serialization + ktor clientplugins { id("org.jetbrains.kotlin.js") version "1.3.61" id("org.jetbrains.kotlin.plugin.serialization") version "1.3.61"}

sourceSets["main"].dependencies { implementation(kotlin("stdlib-js"))

implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-js:1.3.2") implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:0.14.0")

implementation("io.ktor:ktor-client-json-js:1.2.6") implementation("io.ktor:ktor-client-js:1.2.6")}

Page 45: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Kitten API response{ "count": 1, "kittens": [ { "name": "Lucy", "age": 3, "gender": "male", "color": "gray", "race": "siberian", "photoUri": "https:*/kitten.io/images/lucy.png" } ]}

Page 46: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Kotlin data classes@Serializabledata class KittensResponse( val count: Int, val kittens: List<Kitten>)

@Serializabledata class Kitten( val name: String, val age: Int, val gender: Gender, val color: Color, val race: Race, val photoUri: String)

Page 47: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

kotlinx.serializationfun testSerialization(kittensResponse: KittensResponse): KittensResponse { val serializer = KittensResponse.serializer() val json = Json(JsonConfiguration.Stable)

val jsonData = json.stringify(serializer, kittensResponse) println(jsonData)

return json.parse(serializer, jsonData)}

Page 48: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Ktor client + kotlinx.serializationclass KittenApi { private val client = HttpClient(Js) { install(JsonFeature) }

suspend fun fetchKittens(): KittensResponse { val url = "http:*/localhost:8080/kittens" return client.get<KittensResponse>(url) }}

Page 49: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Kotlin/JS & Coroutines

Page 50: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

JavaScript - async/awaitasync function registerServiceWorker() { try { await navigator.serviceWorker .register('/service-worker.js') console.log('Service worker registered!') } catch (e) { console.error(`Error registering service worker: ${e}`) }}

Page 51: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Kotlin/JS - Coroutinessuspend fun registerServiceWorker() { try { window.navigator.serviceWorker .register("/service-worker.js").await() console.log("Service Worker registered!") } catch (e: Exception) { console.error("Failed to register service worker: $e") }}

Page 52: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Promises.ktpublic suspend fun <T> Promise<T>.await(): T = suspendCancellableCoroutine { cont: CancellableContinuation<T> -> [email protected]( onFulfilled = { cont.resume(it) }, onRejected = { cont.resumeWithException(it) })}

Page 53: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Kotlin/JS UI

Page 54: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

kotlinx.htmlimplementation("org.jetbrains.kotlinx:kotlinx-html-js:0.6.12")

Page 55: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

kotlinx.htmlfun main() { val appRoot = document.querySelector("#app") *: return appRoot.append { h1 { +"Hello, World!" } p { +"Unary plus operator appends String to tag." img(alt = "Photo of the cutest cat", src = "/cookie.jpg") } }}

Page 56: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts
Page 57: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

kotlinx.htmlfun main() { val kittens = listOf("Lucy", "Cookie", "Mittens", "Daisy", "Smokey")

val appRoot = document.querySelector("#app") *: return appRoot.append { ul { for ((index, kitten) in kittens.withIndex()) { li { val color = if (index % 2 *= 0) "red" else "blue" classes = setOf(color) */ Set the CSS class onClickFunction = { } */ Click listener +kitten */ Add text to LI element } } } }}

Page 58: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Reactimplementation(npm("@jetbrains/kotlin-react", "16.9.0-pre.83"))implementation(npm("@jetbrains/kotlin-react-dom", "16.9.0-pre.83"))

Page 59: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Reactfun RBuilder.hello(name: String) { h1 { +"Hello, $name!" }}

fun RBuilder.app() { hello("Erik")}

fun main() { val element = document.querySelector("#app") *: return render(element) { app() }}

Page 60: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Create React Kotlin Apphttps://github.com/JetBrains/create-react-kotlin-app

Page 61: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

$ npm install -g create-react-kotlin-app$ npx create-react-kotlin-app kotlin-create-react-demo

Create a React/Kotlin app

Page 62: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

NPM packages

Page 63: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts
Page 64: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

kotlin { target { nodejs() browser() }

sourceSets["main"].dependencies { implementation(kotlin("stdlib-js")) implementation(npm("jszip","3.2.2")) }}

NPM dependencies in Gradle?!?

Page 65: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Declare the API in Kotlinexternal class ZipObject { fun async(type: String): Promise<Any?>}

external class JSZip { fun file(name: String): Promise<ZipObject> fun loadAsync(data: ArrayBuffer): Promise<JSZip>}

Page 66: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Use the JavaScript library in Kotlinfun main() { val zip = JSZip() window.fetch("/kitten-photos.zip") .then { it.arrayBuffer() } .then { zip.loadAsync(it) } .then { it.file("lucy.jpg") } .then { it.async("blob") as Promise<Blob> } .then { val objectUrl = URL.createObjectURL(it) val img = document.querySelector("#kittenImage") img as HTMLImageElement img.src = objectUrl }}

Page 67: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

...using coroutinessuspend fun loadImageFromZip(url:String) { val zip = JSZip() val response = window.fetch(url).await() val zipBuffer = response.arrayBuffer().await() val zipObject = zip.loadAsync(zipBuffer).await() val zipData = zipObject.file("lucy.jpg").await() val imageBlob = zipData.async("blob").await() as Blob

val objectUrl = URL.createObjectURL(imageBlob) val img = document.querySelector("#kittenImage") img as HTMLImageElement img.src = objectUrl}

Page 68: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

dynamic

Page 69: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Impossible to convert to Kotlin?function typeScriptExample(wantNumber: boolean): number | string { if (wantNumber) { return 42 } else { return "Here is some text" }}

Page 70: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

dynamic to the rescue!fun testExternal() { val result: dynamic = typeScriptExample(false) val text = result as String console.log("Result is a string of length ${text.length}") result.can().call().anything.without().compile.error()}

Page 71: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Dukat

Experimental!!!

Page 72: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

gradle.propertieskotlin.js.experimental.generateKotlinExternals=true

Page 73: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Generate externals task$ ./gradlew generateExternals

Page 74: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

left-pad/index.d.ts*/ Type definitions for left-pad 1.2.0*/ Project: https:*/github.com/stevemao/left-pad*/ Definitions by: Zlatko Andonovski, Andrew Yang, Chandler Fang and Zac Xu

declare function leftPad(str: string|number, len: number, ch*: string|number): string;

declare namespace leftPad { }

export = leftPad;

Page 75: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Generated externals: index.module_left-pad.kt@JsModule("left-pad")external fun leftPad(str: String, len: Number, ch: String? = definedExternally ** null */): String

@JsModule("left-pad")external fun leftPad(str: String, len: Number, ch: Number? = definedExternally ** null */): String

@JsModule("left-pad")external fun leftPad(str: Number, len: Number, ch: String? = definedExternally ** null */): String

@JsModule("left-pad")external fun leftPad(str: Number, len: Number, ch: Number? = definedExternally ** null */): String

@JsModule("left-pad")external fun leftPad(str: String, len: Number): String

@JsModule("left-pad")external fun leftPad(str: Number, len: Number): String

Page 76: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Is Kotlin/JS ready for production use?

Page 77: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

“It depends…”

Page 78: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

Conclusions● JavaScript output can be very big

● Kotlin wrappers needed

● Undocumented build system

● Missing code splitting (for Service Workers etc.)

● Looks promising!

Page 79: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

The state of Kotlin/JS - 13:00 Today!

Page 80: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts
Page 81: BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman...BUILDING PROGRESSIVE WEB APPS IN KOTLIN Erik Hellman @ErikHellman Actual Cross Platform! Types - They’re pretty great! lib.dom.d.ts

#KotlinConf

THANK YOUAND REMEMBER TO VOTE

Erik Hellman @ErikHellman