Have you ever tried to use your Kotlin code in React project? If not you should!
Hello, I am going to write a few pages about how to use Kotlin multiplatform, and what is its real power.
This is supposed to be a short course for those who are familiar with Kotlin multiplatform, ReactJS, Android, and IOS. I will not explain to you what is Kotlin multiplatform or React. I will show you what should you do in order to connect the Kotlin multiplatform project and React, IOS, Android projects. In this course, we will create a simple app that shows you events near you. My idea was to create an events app where you can find an interesting event, comment on it, create your own event, etc. The event could be a party or an exhibition, or any other activity in which people can be involved. But we will not do this in this course I will just show you a very simplified version of it. I guess UI will be just a list of events. But we will do that for Web, Android, and IOS. The idea is to write a server and a client using Kotlin and use the client side on all the platforms. But UI will be written in native languages. Android - Kotlin (Android Compose), Web - TypeScript (React), IOS - Swift (SwiftUI). Maybe we will also try the Compose for Web but I don't promise you :)
This is the first part. Today we'll learn how to create a Kotlin multiplatform project by ourselves, write a straightforward multiplatform code and connect Kotlin to TypeScript. All the code is available on GitHub
Let's start.
The first step is to create an empty Kotlin project with Gradle Kotlin DSL. We will configure Gradle by ourselves.
The project structure should look like this.
// build.gradle.kts
// We define repositories here to not duplicate them in every Gradle file.
buildscript {
repositories {
mavenLocal()
mavenCentral()
google()
}
}
allprojects {
repositories {
mavenLocal()
mavenCentral()
gradlePluginPortal()
google()
}
}
// settings.gradle.kts
// Here we define the name of the project and repositories for plugins
rootProject.name = "EventsMapBlog"
pluginManagement {
repositories {
mavenLocal()
mavenCentral()
gradlePluginPortal()
google()
}
}
# gradle.properties
#Gradle
org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M"
#Kotlin
kotlin.code.style=official
Step two. Creating a shared module.
To do that everything we need is to create a new directory with a build.gradle.kts file.
// shared/build.gradle.kts
plugins {
kotlin("multiplatform")
}
kotlin {
// Define the js platform. It means that this code can be compiled to js.
js(IR) {
moduleName = "shared"
// Define the modules system as commonJS. This helps us to easily use our kotlin library in TS.
useCommonJs()
browser()
// And finally we say to the compiler to create library
binaries.library()
}
sourceSets {
val commonMain by getting
val jsMain by getting
}
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions.jvmTarget = "16"
}
We also need to add some dependencies in our main gradle file to make the code above work.
// build.gradle.kts
buildscript {
...
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.20")
classpath("org.jetbrains.kotlin:kotlin-allopen:1.7.20")
}
}
And finally, we add this line in settings to make Gradle see our new module.
// settings.gradle.kts
...
include(":shared")
Let's create a very simple object to test if everything works. Also, I added JsExport annotation to make it visible in the js code.
Step three. Creating React project
You have to know how to do that already. My suggestion is to use TypeScript. This will prevent lots of errors in the future because TS uses a CommonJS modules system that makes importing our Kotlin code really easy.
npx create-react-app events-map --template typescript
Now we can build Kotlin code using jsBrowserProductionLibraryDistribution
gradle task. Then copy files from the build folder to our React project. But this is boring. Let's create our custom gradle task that will do all the work for us.
//shared/build.gradle.kts
...
tasks.register("buildJs") {
dependsOn("jsBrowserProductionLibraryDistribution")
doLast {
val from = File("$buildDir/productionLibrary")
val into = File("$projectDir/../reactApp/src/kotlin")
if (into.exists()) into.deleteRecursively()
from.copyRecursively(into, true)
}
}
P.S I created React project in our main Kotlin project folder and renamed it to reactApp.
Run the buildJs
task and enjoy!
In App.tsx
we can write something like this.
// reactApp/App.tsx
import React from 'react';
import './App.css';
import {Platform} from "./kotlin";
function App() {
return (
<div className="App">
<h1>The platform is {Platform.platformName}</h1>
</div>
);
}
export default App;
RUN!
npm start
Voilà, we imported kotlin code into the TypeScript project.
One more thing, to hide a huge amount of errors in the terminal while running npm start we can add “.eslintignore” file.
#reactApp/.eslintignore
kotlin/
Thanks for reading
In the next episodes, we will
- Create a ktor server and display events on our web page
- Create an Android app and setup MVVM architecture in the shared module
- Create an IOS app that also uses shared ViewModels