こんにちは、マヤミトです。
この記事はKotlin Advent Calendar 2020 18日目の記事です。
皆さんはKotlin/JSを使っていますか?まだまだ記事が少ないこともあり、どう始めればいいのかわからないという人もいるかもしれません。今回は、普段Kotlinを書いている人がKotlin/JSでWebフロント開発を始めるのに最低限必要な知識を身につけられることをゴールにこの記事を書いています。解説不足の部分があれば気軽にコメントしてください。
Kotlin/JSについて
Kotlin/JSは、文字通りKotlinをJavaScriptにトランスパイルする技術です。
https://kotlinlang.org/docs/reference/js-overview.html
当然JVMの資産は使えませんが、その代わりにDOMの操作などをKotlinでType Safeに扱うことができます。
NodeJSの資産を使ってサーバーサイドの開発もできますが、今回の記事では特に触れないことにします(興味のある方は以前書いたこちらの記事をご覧ください)。
Kotlin/JSを扱う方法は大きく分けて2種類あり、通常のWebフロント開発のようにnpmのプロジェクトとして作成する方法と、通常のKotlinでの開発のようにGradleのプロジェクトとして作成する方法があります。古い記事ではnpmを使う方法が多くヒットしますが、最近だとGradle Pluginを使う後者の方法が公式では推奨されており、今回はそちらの方法を解説します。
今回使用したバージョンなど
IntelliJ IDEA Ultimate 2020.3
Kotlin 1.4.21
Gradle 6.7
Kotlin/JSは情報が古くなるサイクルが早いので、この記事の通りにやっても動かない場合は最新の情報を公式ドキュメントなどに直接探しに行くことをオススメします(まあその公式ドキュメントもたまに古かったりしますが……)
簡単なプロジェクトを作ってみる
プロジェクトのセットアップ
IntelliJ IDEAの New Project
の Gradle
から Kotlin/JS for browser
を選択し、新規プロジェクトを作成します。
この際、 Kotlin DSL build script
にチェックを付けることをおすすめします。
import kotlinx.browser.document
fun main() {
document.write("Hello, world!")
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HelloKotlinJS</title>
<script src="HelloKotlinJS.js"></script>
</head>
<body>
</body>
</html>
plugins {
id("org.jetbrains.kotlin.js") version "1.4.21"
}
group = "com.yt8492"
version = "1.0.0"
repositories {
mavenCentral()
}
dependencies {
implementation(kotlin("stdlib-js"))
}
kotlin {
js {
browser {
webpackTask {
cssSupport.enabled = true
}
runTask {
cssSupport.enabled = true
}
testTask {
useKarma {
useChromeHeadless()
webpackConfig.cssSupport.enabled = true
}
}
}
binaries.executable()
}
}
ページに Hello, world!
と表示されるだけの簡単なコードです。
デフォルトでは、 プロジェクト名.js
をHTMLから読み込んでいます。これが実際にビルドして吐き出されるファイル名です。任意のファイル名に設定したい場合、 build.gradle.kts
に設定を追記します。
kotlin {
js {
browser {
webpackTask {
cssSupport.enabled = true
outputFileName = "main.js" // 追加
}
runTask {
cssSupport.enabled = true
outputFileName = "main.js" // 追加
}
testTask {
useKarma {
useChromeHeadless()
webpackConfig.cssSupport.enabled = true
webpackConfig.outputFileName = "main.js" // 追加
}
}
}
binaries.executable()
}
}
実行してみる
プロジェクトルートで以下を実行します。
./gradlew browserRun --continuous
するとブラウザが立ち上がり、実際にページが表示されると思います。
--continuous
オプションはホットリロードを有効にします。開発中はこのオプションをつけて実行すると便利です。
ビルドしてみる
プロジェクトルートで以下を実行します。
./gradlew browserWebpack
プロジェクトルート/build/distributions/
以下にトランスパイルされたJavaScriptのファイルと resources
以下のファイルが吐き出されるので、 index.html
をブラウザで開くと、先程と同じページが表示されると思います。
DOMの操作をしてみる
デフォルトでは単純に Hello, world!
と表示するだけでしたが、ボタンをクリックしたらテキストが表示されるようなコードを書いてみましょう。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Hello Kotlin/JS</title>
</head>
<body>
<button id="greetButton">Greet</button>
<h1 id="greetText"></h1>
</body>
<script src="main.js"></script>
</html>
import kotlinx.browser.document
import org.w3c.dom.HTMLButtonElement
import org.w3c.dom.HTMLHeadingElement
fun main() {
val greetButton = document.getElementById("greetButton") as HTMLButtonElement
val greetText = document.getElementById("greetText") as HTMLHeadingElement
greetButton.addEventListener("click", {
greetText.textContent = "Hello, Kotlin/JS!"
})
}
Greet
ボタンを押すと、以下のように Hello, Kotlin/JS!
と表示されると思います。
document.getElementById
で要素を取得して操作しているのがわかると思います。
Kotlin/JSで使えるライブラリ集
今回の記事の目的はKotlin/JSでの開発に最低限必要な知識を身に着けてもらうことなので、各種ライブラリの使い方はここでは解説しませんが、自分がよく使うライブラリを紹介したいと思います。
kotlin-react
文字通り、KotlinでReactを扱うことができるようになるラッパーライブラリです。Kotlin/JS向けのJavaScriptラッパーライブラリ集kotlin-wrappersのうちの一つです。
https://github.com/JetBrains/kotlin-wrappers/blob/master/kotlin-react/README.md
最新版ではReact v17に対応していて、hooksも普通に使えます。
kotlin-wrappersリポジトリには、React Routerのラッパーやstyled-componentsのラッパーなどもあります。それらと組み合わせて使うと良いでしょう。
Ktor Client
Kotlin/MPP対応のHTTP Clientライブラリです。当然Kotlin/JSでも使うことができます。
https://ktor.io/docs/clients-index.html
Klock
Kotlin/MPP対応の時間を扱うライブラリです。Kotlin/JVMではJavaのDate型などが使えましたが、当然Kotlin/JSでは使えないので、こういったライブラリを使うと良いでしょう。
https://korlibs.soywiz.com/klock/
終わりに
今回はKotlin/JS初心者向けの記事でした。Kotlin好きな皆さんがこの記事を読んでKotlin/JSを始めてくれると嬉しいです。
最近のKotlin界隈ではKMMが盛り上がりを見せていますが、Kotlin/JSも流行るといいなぁ……と思いながら地道に活動をしています。興味のある方はぜひ一度試してみてほしいです。