Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Kotlin/JS

 Kotlin/JS

Have you ever developed something with JavaScript? Did you like it? Did you miss Kotlin's features? Since the release of Kotlin 1.1, you don’t have to anymore! Kotlin now is also able to compile to pure JavaScript and run without a JVM.

by Jossi Wolf
presented on February 21, 2018 @car2go

C67d4b2a0b74214c56b23969177e743c?s=128

Kotlin User Group Hamburg

February 21, 2018
Tweet

Transcript

  1. / @jossiwolf

  2. Jossi Wolf Android Developer High School Student @jossiwolf

  3. AGENDA - INTRODUCTION - WHY KOTLIN? - GETTING STARTED -

    DIFFERENCES - USING NODEJS - CREATING A WEBSITE - CONCLUSION @jossiwolf
  4. / @jossiwolf

  5. WHY KOTLIN? THE CASE AGAINST JAVASCRIPT @jossiwolf

  6. STATICALLY TYPED DYNAMICALLY TYPED var hello = "Hello" hello =

    5 ❌ let hello = "Hello" hello = 5 ✅ @jossiwolf
  7. DEVELOPER HAPPINESS IS IMPORTANT! @jossiwolf

  8. INTEROPERABILITY @jossiwolf

  9. SCALABILITY @jossiwolf

  10. CODE REUSE @jossiwolf

  11. DIFFERENCES @jossiwolf

  12. PACKAGE NAMES IN FILES ARE OPTIONAL @jossiwolf

  13. NO JAVA APIs @jossiwolf

  14. GETTING STARTED @jossiwolf

  15. @jossiwolf

  16. @jossiwolf

  17. 2. Wait for Gradle build to finish (⏳) @jossiwolf

  18. @jossiwolf

  19. buildscript { ext.kotlin_version = '1.2.10' repositories { mavenCentral() } dependencies

    { classpath "$kotlin_gradle_plugin:$kotlin_version" } } apply plugin: 'kotlin-js' repositories { mavenCentral() } dependencies { compile "$kotlin_stdlib_js:$kotlin_version" } @jossiwolf
  20. compileKotlin2Js.kotlinOptions { sourceMap = true //Generate a source-map for debug

    } @jossiwolf
  21. compileKotlin2Js.kotlinOptions { sourceMap = true //Generate a source-map for debug

    sourceMapEmbedSources = "always" //And embed the source } @jossiwolf
  22. compileKotlin2Js.kotlinOptions { sourceMap = true //Generate a source-map for debug

    sourceMapEmbedSources = "always" //And embed the source moduleKind = "plain" //The module loader to be used } @jossiwolf
  23. compileKotlin2Js.kotlinOptions { sourceMap = true //Generate a source-map for debug

    sourceMapEmbedSources = "always" //And embed the source moduleKind = "plain" //The module loader to be used outputFile = "web/index.js" //Output file that we use } @jossiwolf
  24. USING NODE.JS @jossiwolf

  25. compileKotlin2Js.kotlinOptions { moduleKind = "commonjs" } @jossiwolf

  26. fun main(args: Array<String>) { console.log("Hello from Kotlin!") } @jossiwolf

  27. $ gradle build @jossiwolf

  28. $ gradle build $ node node/index.js @jossiwolf

  29. $ gradle build $ node node/index.js > Hello from Kotlin!

    @jossiwolf
  30. dynamic //„Disables“ type-safety @jossiwolf

  31. dynamic //„Disables“ type-safety val hello: dynamic = "Hello" hello.whatever() hello.itDoesntMatter

    @jossiwolf
  32. external //This is defined externally @jossiwolf

  33. external fun require(module: String): dynamic @jossiwolf

  34. INTERACTING WITH THE DOM @jossiwolf

  35. task assembleWeb(type: Sync) { configurations.compile.each { File file -> from(zipTree(file.absolutePath),

    { includeEmptyDirs = false include { fileTreeElement -> def path = fileTreeElement.path path.endsWith(".js") && (path.startsWith("META-INF/resources/") || !path.startsWith("META-INF/")) } }) } from compileKotlin2Js.destinationDir into "${projectDir}/web" dependsOn classes } assemble.dependsOn assembleWeb @jossiwolf
  36. document#getElementById @jossiwolf

  37. document#getElementById document#getElementsByClassName @jossiwolf

  38. document#getElementById document#getElementsByClassName // All the normally available @jossiwolf

  39. div { } @jossiwolf

  40. div { h1 { +"This is some text from Kotlin!"

    } } @jossiwolf
  41. document.body?.append { div { h1 { +"This is some text

    from Kotlin!" } } } @jossiwolf
  42. <!DOCTYPE html> <html lang="en"> <head> <title>Kotlin & JS <3</title> </head>

    <body> </body> <!-- The Kotlin libraries --> <script src="web/kotlin.js"></script> <script src="web/kotlinx-html-js.js"></script> <!-- Make sure this is at the bottom --> <script src="web/index.js"></script> </html> @jossiwolf
  43. @jossiwolf

  44. @jossiwolf

  45. <div class="mdc-card"> <section class="mdc-card__primary"> <h1 class="mdc-card__title mdc-card__title--large">Title goes here</h1> <h2

    class="mdc-card__subtitle">Subtitle here</h2> </section> <section class="mdc-card__supporting-text"> Some text goes here </section> <section class="mdc-card__actions"> <button class="mdc-button mdc-button--compact mdc-card__action"> Action 1 </button> <button class="mdc-button mdc-button--compact mdc-card__action"> Action 2 </button> </section> </div> @jossiwolf
  46. DSL (DOMAIN SPECIFIC LANGUAGE) „BUILDERS ON STEROIDS“ @jossiwolf

  47. verticalLayout { val name = editText() button("Say Hello") { onClick

    { toast("Hello, ${name.text}!") } } } @jossiwolf
  48. div("mdc-card") { section("mdc-card__primary") { h1("mdc-card__title) { +"This is the title"

    } h2("mdc-card__subtitle") { +"Subtitle" } } section("mdc-card__supporting-text") { +"This is the card's text" } } @jossiwolf
  49. fun DIV.card(title: String, subtitle: String, text: String) { div("mdc-card") {

    section("mdc-card__primary") { h1("mdc-card__title") { +title } h2("mdc-card__subtitle") { +subtitle } } section("mdc-card__supporting-text") { +text } } } @jossiwolf
  50. fun DIV.card(title: String, subtitle: String, text: String) { div("mdc-card") {

    section("mdc-card__primary") { h1("mdc-card__title") { +title } h2("mdc-card__subtitle") { +subtitle } } section("mdc-card__supporting-text") { +text } } } @jossiwolf
  51. document.create.div { card("Card Title", "Card Subtitle", "Card Text") } @jossiwolf

  52. @jossiwolf

  53. card { title = "Card Title" subtitle = "Card Subtitle"

    text = "Hello Kotlin Meetup!„ } @jossiwolf
  54. card { title = "Card Title" subtitle = "Card Subtitle"

    text = "Hello Kotlin Meetup!" action { text = "Action!" } elevation = 6 } @jossiwolf
  55. HIGHER-ORDER FUNCTIONS @jossiwolf

  56. fun higherOrderFunction(block: (String) -> String): String { return block("Hello from

    up here") } @jossiwolf
  57. fun higherOrderFunction(block: (String) -> String): String { return block("Hello from

    up here") } The function takes a string as parameter @jossiwolf
  58. fun higherOrderFunction(block: (String) -> String): String { return block("Hello from

    up here") } The function takes a string as parameter @jossiwolf
  59. fun higherOrderFunction(block: (String) -> String): String { return block("Hello from

    up here") } The function takes a string as parameter Its return type is also String @jossiwolf
  60. fun higherOrderFunction(block: (String) -> String): String { return block("Hello from

    up here") } println(higherOrderFunction { it }) //Prints „Hello from up here“ The function takes a String as parameter Its return type is Also String @jossiwolf
  61. fun higherOrderFunction(block: (String) -> String): String { return block("Hello from

    up here") } println(higherOrderFunction { return@higherOrderFunction it }) //Prints „Hello from up here“ The function takes a String as parameter Its return type is Also String @jossiwolf
  62. RECEIVERS @jossiwolf

  63. card { title = "Card Title" subtitle = "Card Subtitle"

    text = "Hello Kotlin Meetup!" } @jossiwolf
  64. class MaterialCardOptions { lateinit var title: String lateinit var subtitle:

    String lateinit var text: String } @jossiwolf
  65. fun card(block: MaterialCardOptions.() -> Unit) { val options = MaterialCardOptions().apply(block)

    println(JSON.stringify(options)) } @jossiwolf
  66. fun card(block: MaterialCardOptions.() -> Unit) { val options = MaterialCardOptions().apply(block)

    println(JSON.stringify(options)) } @jossiwolf
  67. card { title = "Hello" subtitle = "Subtitle" } @jossiwolf

  68. card { title = "Hello" subtitle = "Subtitle" } {

    "title_xesk5l$_0": "Hello", "subtitle_x7q17f$_0": "Subtitle", "actions": [] } @jossiwolf
  69. document.body?.append { div { } } @jossiwolf

  70. fun DIV.card(block: MaterialCardOptions.() -> Unit) { val options = MaterialCardOptions().apply(block)

    div("mdc-card") { section("mdc-card__primary") { h1 { classes = setOf("mdc-card__title") +options.title } h2("mdc-card__subtitle") { +options.subtitle } } section("mdc-card__supporting-text") { +options.text } } } @jossiwolf
  71. document.body?.append { div { card { title = "Shiba Inu"

    subtitle = "Japanese Dog Breed" text = "Shiba Inu, also known as Doge, is a Japanese dog breed." } } } @jossiwolf
  72. SHOULD I USE IT? (IN PRODUCTION) @jossiwolf

  73. NOT REALLY. @jossiwolf

  74. medium.com/@jossiwolf twitter.com/jossiwolf github.com/jossiwolf speakerdeck.com/jossiwolf