Kotlin JS Development
Introduction
Kotlin/JS is a powerful technology that allows developers to write Kotlin code that transpiles to JavaScript. As part of the Kotlin Multiplatform ecosystem, it enables developers to share code between different platforms while still leveraging platform-specific capabilities. With Kotlin/JS, you can build web applications, utilize JavaScript libraries, and even share code with Android, iOS, or backend applications.
In this guide, we'll explore the fundamentals of Kotlin/JS development, from setting up your environment to creating interactive web applications and integrating with JavaScript libraries.
Setting Up Your Environment
Before diving into Kotlin/JS development, you'll need to set up your development environment.
Prerequisites
- JDK 8 or later
- IntelliJ IDEA (recommended) or any IDE with Kotlin support
- Gradle or Maven build system
Creating a New Kotlin/JS Project
The easiest way to create a new Kotlin/JS project is through IntelliJ IDEA:
- Open IntelliJ IDEA
- Select "New Project"
- Choose "Kotlin" from the left panel
- Select "Kotlin/JS for Web" or "Kotlin/JS for Node.js" template
- Configure your project settings and click "Finish"
Alternatively, you can set up a project using Gradle. Create a build.gradle.kts
file with the following content:
plugins {
kotlin("js") version "1.8.0"
}
repositories {
mavenCentral()
}
kotlin {
js(IR) {
browser {
commonWebpackConfig {
cssSupport {
enabled.set(true)
}
}
binaries.executable()
}
}
sourceSets {
val main by getting {
dependencies {
implementation("org.jetbrains.kotlin-wrappers:kotlin-react:18.2.0-pre.467")
implementation("org.jetbrains.kotlin-wrappers:kotlin-react-dom:18.2.0-pre.467")
}
}
}
}
Your First Kotlin/JS Program
Let's start with a simple "Hello World" program in Kotlin/JS. Create a file named App.kt
in the src/main/kotlin
directory:
import kotlinx.browser.document
fun main() {
document.addEventListener("DOMContentLoaded", {
val message = document.createElement("h1")
message.textContent = "Hello, Kotlin/JS!"
document.body?.appendChild(message)
})
}
When executed in a browser, this code will create an <h1>
element with the text "Hello, Kotlin/JS!" and append it to the document body.
Running the Application
To run your application:
- Execute the
./gradlew browserDevelopmentRun
command (for Gradle) - Open your browser at http://localhost:8080 (default port)
You should see "Hello, Kotlin/JS!" displayed in your browser.
DOM Manipulation with Kotlin/JS
Kotlin/JS provides access to the browser's DOM API, allowing you to manipulate web pages programmatically.
Example: Creating a Dynamic List
Here's an example of creating a dynamic list using Kotlin/JS:
import kotlinx.browser.document
import org.w3c.dom.HTMLLIElement
import org.w3c.dom.HTMLUListElement
fun main() {
document.addEventListener("DOMContentLoaded", {
// Create title
val title = document.createElement("h2")
title.textContent = "My Favorite Programming Languages"
document.body?.appendChild(title)
// Create list
val languageList = document.createElement("ul") as HTMLUListElement
document.body?.appendChild(languageList)
// Add items to list
val languages = listOf("Kotlin", "JavaScript", "Swift", "Python", "Rust")
languages.forEach { language ->
val listItem = document.createElement("li") as HTMLLIElement
listItem.textContent = language
languageList.appendChild(listItem)
}
})
}
This code will generate a heading followed by a bullet list of programming languages.
Event Handling
Handling events is crucial for interactive web applications. Here's how you can add event listeners in Kotlin/JS:
import kotlinx.browser.document
import org.w3c.dom.HTMLButtonElement
import org.w3c.dom.HTMLDivElement
import org.w3c.dom.events.Event
fun main() {
document.addEventListener("DOMContentLoaded", {
val button = document.createElement("button") as HTMLButtonElement
button.textContent = "Click me!"
document.body?.appendChild(button)
val output = document.createElement("div") as HTMLDivElement
document.body?.appendChild(output)
var clickCount = 0
button.addEventListener("click", { _: Event ->
clickCount++
output.textContent = "Button clicked $clickCount time(s)!"
})
})
}
When you click the button, the text will update to show how many times the button has been clicked.
Working with JavaScript Libraries
One of the biggest advantages of Kotlin/JS is the ability to use existing JavaScript libraries. You can do this through:
- Dynamic typing - Quick but unsafe access to JS libraries
- Kotlin wrappers - Type-safe Kotlin APIs for popular JS libraries
- Creating your own typings - For libraries without existing wrappers
Using Dynamic Type
Kotlin provides the dynamic
type for interacting with JavaScript libraries without type checking:
import kotlinx.browser.window
fun main() {
// Accessing a hypothetical JS library without typings
val jsLib = js("MyJSLibrary")
// Calling methods on the JS library
jsLib.initialize()
// Working with JS objects
val person = js("{ name: 'John', age: 30 }")
window.alert("Hello, ${person.name}!")
}
Using Kotlin Wrappers
For popular libraries like React, Kotlin provides official wrappers that offer type-safe APIs:
import react.*
import react.dom.*
import kotlinx.browser.document
external interface WelcomeProps : Props {
var name: String
}
val Welcome = FC<WelcomeProps> { props ->
h1 {
+"Hello, ${props.name}!"
}
}
fun main() {
val container = document.createElement("div")
document.body!!.appendChild(container)
createRoot(container).render(Fragment.create {
Welcome {
name = "Kotlin Developer"
}
})
}
Building a Real-World Application: To-Do List
Let's build a simple to-do list application to demonstrate Kotlin/JS in action:
import kotlinx.browser.document
import kotlinx.browser.window
import org.w3c.dom.HTMLButtonElement
import org.w3c.dom.HTMLInputElement
import org.w3c.dom.HTMLLIElement
import org.w3c.dom.HTMLUListElement
import org.w3c.dom.events.Event
data class TodoItem(val text: String, var completed: Boolean = false)
fun main() {
document.addEventListener("DOMContentLoaded", {
setupTodoApp()
})
}
fun setupTodoApp() {
// Create app elements
val heading = document.createElement("h1")
heading.textContent = "Kotlin/JS Todo App"
document.body?.appendChild(heading)
val inputContainer = document.createElement("div")
document.body?.appendChild(inputContainer)
val input = document.createElement("input") as HTMLInputElement
input.setAttribute("type", "text")
input.setAttribute("placeholder", "Enter a task...")
inputContainer.appendChild(input)
val addButton = document.createElement("button") as HTMLButtonElement
addButton.textContent = "Add Task"
inputContainer.appendChild(addButton)
val todoList = document.createElement("ul") as HTMLUListElement
document.body?.appendChild(todoList)
val todos = mutableListOf<TodoItem>()
// Handle add button click
addButton.addEventListener("click", {
val text = input.value.trim()
if (text.isNotEmpty()) {
todos.add(TodoItem(text))
renderTodos(todoList, todos)
input.value = ""
}
})
}
fun renderTodos(todoList: HTMLUListElement, todos: List<TodoItem>) {
// Clear existing items
while (todoList.firstChild != null) {
todoList.removeChild(todoList.firstChild!!)
}
// Render updated list
todos.forEachIndexed { index, todo ->
val item = document.createElement("li") as HTMLLIElement
val checkbox = document.createElement("input") as HTMLInputElement
checkbox.setAttribute("type", "checkbox")
checkbox.checked = todo.completed
checkbox.addEventListener("change", {
todos[index].completed = checkbox.checked
renderTodos(todoList, todos)
})
item.appendChild(checkbox)
val textSpan = document.createElement("span")
textSpan.textContent = todo.text
if (todo.completed) {
textSpan.style.textDecoration = "line-through"
}
item.appendChild(textSpan)
val deleteButton = document.createElement("button") as HTMLButtonElement
deleteButton.textContent = "Delete"
deleteButton.addEventListener("click", {
todos.removeAt(index)
renderTodos(todoList, todos)
})
item.appendChild(deleteButton)
todoList.appendChild(item)
}
}
This application allows you to add tasks to a list, mark them as complete, and delete them.
Building and Deploying Kotlin/JS Applications
When you're ready to deploy your Kotlin/JS application, you'll need to build it for production.
Production Build
For Gradle projects, run:
./gradlew browserProductionWebpack
This will generate optimized JavaScript files in the build/distributions
directory.
Deployment Options
You can deploy your Kotlin/JS application like any other JavaScript application:
- Static hosting services (GitHub Pages, Netlify, Vercel)
- Traditional web servers (Apache, Nginx)
- Cloud platforms (AWS, Google Cloud, Azure)
Simply upload the contents of the build/distributions
directory to your hosting provider.
Summary
In this guide, we've covered:
- Setting up a Kotlin/JS development environment
- Creating basic web applications with Kotlin/JS
- DOM manipulation and event handling
- Working with JavaScript libraries
- Building a practical to-do list application
- Building and deploying Kotlin/JS applications
Kotlin/JS offers a powerful way to build web applications using the Kotlin language you may already know from Android or backend development. By leveraging Kotlin Multiplatform, you can share code between your web frontend and other platforms, significantly reducing development time and effort.
Additional Resources
- Official Kotlin/JS Documentation
- Kotlin/JS Hands-On Tutorials
- Kotlin Wrappers GitHub Repository
- Kotlin Multiplatform Project Wizard
Exercises
- Extend the to-do list application to store tasks in the browser's localStorage
- Create a simple calculator application using Kotlin/JS
- Build a weather application that fetches data from a public API
- Convert an existing JavaScript application to Kotlin/JS
- Create a Kotlin/JS wrapper for a small JavaScript library
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)