Adding a web page

To consume the JavaScript target of our shared Kotlin code, we will create a new Gradle module called :webapp and then create a simple HTML page that will consume the compiled JavaScript code. Perform the following steps for this:

  1. To start, create a new Gradle module, :webapp, with the following structure:
root/webapp
build.gradle
src/main/kotlin
src/index.html
  1. Within webapp/build.gradle, we will use the kotlin2js plugin to configure how our :webapp module should be built:
apply plugin: 'kotlin2js'

dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-js"
implementation project(':core')
}

compileKotlin2Js.kotlinOptions.sourceMap = true
compileKotlin2Js.kotlinOptions.outputFile = "${projectDir}/output/js/app.js"
compileKotlin2Js.kotlinOptions.suppressWarnings = true
compileKotlin2Js.kotlinOptions.verbose = true

Notice that we've added a dependency to :core that will allow us to reference our shared Kotlin types with this module. We've configured several properties of the kotlin2js plugin, the most important one being outputFile. This outputFile path is where the JavaScript output for our :webapp directory will be saved.

  1. Before we can start writing new Kotlin code and build our web page, we need to add a new Gradle task to our :webapp module. This task will be responsible for expanding the build artifacts of our JavaScript built target from :core. This is required because we need to be able to include the JavaScript implementations of the Kotlin standard library along with whatever Kotlin code we write/deploy within our :webapp module. To add this task, we can make the following updates to webapp/build.gradle:
// webapp/build.gradle
...
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}/output"

dependsOn classes
}

assemble.dependsOn assembleWeb
This code is part of the official documentation for setting up the kotlin.js portion of a Kotlin multiplatform project.
  1. Now, we're ready to start building our web page. First, we'll define a new file, webapp/src/main/kotlin/main.kt, and define the following Kotlin function:
fun main() {
val outputMessage = "Hello Kotlin ${Platform.name}"
println(outputMessage)
}

This function will access Platform.name and print that out to the console.

  1. Next, to compile the required build artifacts for :webapp, run the assemble and assembleWeb Gradle tasks. This should generate two important build artifacts:
    • webapp/output/kotlin.js
    • webapp/output/js/app.js
  1. Now, we can consume those build artifacts from index.html. We will load them as scripts so that when the web page is loaded, Platform.name is printed out to the console, as follows:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS Multiplatform</title>
</head>
<body bgcolor="#E6E6FA">
<script type="text/javascript" src="../output/kotlin.js"></script>
<script type="text/javascript" src="../output/js/app.js"></script>
</body>
</html>
  1. Once index.html is updated, you should be able to open the page in your browser from IntelliJ, as we did previously in this book, and see the console output using the developer tools.

With our HTML page consuming our compiled JavaScript, we now have three different projects in place that are making using of our shared Kotlin code.

In the next section, we'll further explore how to go about writing shared Kotlin code that can be consumed by various build targets.