Introduction to WebAssembly and Kotlin
Modern web development requires ever-increasing performance, especially for complex calculations, image processing, games, and scientific applications. WebAssembly (Wasm) is a low-level binary format that runs in the browser at near-native speed. And Kotlin, thanks to its flexibility and support for multiple platforms, becomes an excellent candidate for compilation to Wasm.
In this article, we will thoroughly examine how to set up a Kotlin project for compilation to WebAssembly, write practical examples, and review best practices for optimization.
1. Setting up the environment for Kotlin/Native and WebAssembly
To work with WebAssembly in Kotlin, Kotlin/Native is used — a technology that allows compiling Kotlin code into native binary files, including Wasm. Let's look at the step-by-step setup.
Installing necessary tools
- IntelliJ IDEA (Community or Ultimate version) — the main development environment.
- Gradle (built into IDEA) — the build system.
- Emscripten SDK — a tool for working with Wasm (required for some advanced scenarios).
Creating the project
Create a new Gradle project and add the following configuration to build.gradle.kts:
plugins { kotlin("multiplatform") version "1.9.22" kotlin("plugin.serialization") version "1.9.22"}
kotlin { wasm { binaries.executable() browser { commonWebpackConfig { cssSupport.enabled = true } } }}
dependencies { commonMainImplementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2")}Note: For Kotlin 1.9+, the wasm target is used (previously it was wasm32). Make sure the Kotlin version is up to date.
Project structure
After setup, create the file src/wasmMain/kotlin/Main.kt — this will be the entry point of your Wasm application.
2. Writing the first Kotlin application for WebAssembly
Let's write a simple application that calculates the factorial of a number and interacts with JavaScript.
Kotlin code
// src/wasmMain/kotlin/Main.ktimport kotlinx.browser.documentimport kotlinx.browser.window
fun factorial(n: Int): Long { var result = 1L for (i in 1..n) { result *= i } return result}
fun main() { window.onload = { val output = document.getElementById("output") ?: return@onload val input = document.getElementById("number") ?: return@onload // Example call val num = 10 output.textContent = "Factorial of $num = ${factorial(num)}" // Add handler for dynamic input input.addEventListener("input", { val value = (input as? org.w3c.dom.HTMLInputElement)?.value?.toIntOrNull() ?: 0 output.textContent = "Factorial of $value = ${factorial(value)}" }) }}HTML template for running
Create the file src/wasmMain/resources/index.html:
<!DOCTYPE html><html><head> <meta charset="UTF-8"> <title>Kotlin Wasm Demo</title></head><body> <h1>Factorial Calculator on Kotlin/Wasm</h1> <input type="number" id="number" value="10"> <p id="output">Loading...</p> <script src="https://unpkg.com/kotlin-wasm-bridge@latest/dist/kotlin-wasm-bridge.js"></script> <script src="main.js"></script></body></html>3. Interaction between Kotlin and JavaScript via WebAssembly
One of the key