KotlinをNode.jsに変換してWebサーバーを作るメモ #teratail_kt

  • 5
    いいね
  • 0
    コメント

KotlinがJSに変換できるとのことだったので、調べたら出て来たYour first Node.js app with Kotlinの記事を追ってやってみました。

ちなみにCLIとVSCodeでKotlin開発を始めてみるメモに引き続きVSCodeとCLIで進めていきます。

環境

  • macOS Sierra
  • Kotlin 1.1.50
  • Gradle v4.2
  • Node.js v8.4.0

Gradleのインストール

GradleはNode.jsでいうnpmみたいなイメージです。
依存関係解決してくれます。

インストールはhomebrewでいけます。

$ brew install gradle
$ gradle -v

------------------------------------------------------------
Gradle 4.2
------------------------------------------------------------

Build time:   2017-09-20 14:48:23 UTC
Revision:     5ba503cc17748671c83ce35d7da1cffd6e24dfbd

Groovy:       2.4.11
Ant:          Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM:          1.8.0_101 (Oracle Corporation 25.101-b13)
OS:           Mac OS X 10.12.6 x86_64

無事にインストールできました。

プロジェクトを作っていく

任意フォルダを作って移動

$ mkdir myjsapp
$ cd myjsapp

Node.jsプロジェクトの初期化

$ npm init -y

npm initpackage-lock.jsonpackage.jsonが出来上がります。

次に必要なモジュールをインストール

$ npm i --save kotlin express

インストールされるとnode_modulesフォルダができます。

$ ls
node_modules      package-lock.json package.json

この階層にbuild.gradleというファイルを作成して次の内容を書き込みます。

build.gradle
group 'node-example'
version '1.0-SNAPSHOT'

buildscript {
  ext.kotlin_version = '1.1.1'
    repositories {
      mavenCentral()
    }
  dependencies {
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
  }
}

apply plugin: 'kotlin2js'

repositories {
  mavenCentral()
}

dependencies {
  compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"
}

compileKotlin2Js.kotlinOptions {
  moduleKind = "commonjs"
  outputFile = "node/index.js"
}

次に同じ階層にsrcフォルダを作成し、その中にmainフォルダ、さらにその中にkotlinフォルダを作り、その中にMain.ktを作成しましょう。

src/main/kotlin/Main.kt
external fun require(module:String):dynamic

fun main(args: Array<String>) {
    println("Hello JavaScript!")

    val express = require("express")
    val app = express()

    app.get("/", { req, res ->
        res.type("text/plain")
        res.send("i am a beautiful butterfly")
    })

    app.listen(3000, {
        println("Listening on port 3000")
    })
}

これで準備完了です。

普段Node.jsを書いている人ならval express = require("express")の箇所からも分かる通りexpressを使ったWebサーバーになります。

現状ではこんな感じのフォルダ構成になっています。

package.jsonbuild.gradleファイルがあるルートの階層でgradle buildコマンドを実行しましょう。

$ gradle build
> Configure project :
Gradle now uses separate output directories for each JVM language, but thisbuild assumes a single directory for all classes from a source set. This behaviour has been deprecated and is scheduled to be removed in Gradle 5.0
        at build_b5jf4f0juy83k80loi4m0mzgo.run(/Users/n0bisuke/dotstudio/2_events/20170930_kotlin/myjsapp/build.gradle:14)
        (Run with --stacktrace to get the full stack trace of this deprecation warning.)

w: /Users/n0bisuke/dotstudio/2_events/20170930_kotlin/myjsapp/src/main/kotli
n/Main.kt: (9, 20): Parameter 'req' is never used

BUILD SUCCESSFUL in 2s
2 actionable tasks: 2 executed

するとビルドが行われ、buildフォルダとnodeフォルダが出来上がります。

実行

nodeフォルダ内のindex.jsを指定します。

$ node node/index.js

Hello JavaScript!
Listening on port 3000

これで http://localhost:3000 にアクセスするとサーバーが立ち上がっていることが確認できます。

i am a beautiful butterflyって表示されましたか?

変換されたindex.js

変換後のindex.jsです

index.js
(function (_, Kotlin) {
  'use strict';
  var println = Kotlin.kotlin.io.println_s8jyv4$;
  function main$lambda(req, res) {
    res.type('text/plain');
    return res.send('i am a beautiful butterfly');
  }
  function main$lambda_0() {
    println('Listening on port 3000');
  }
  function main(args) {
    println('Hello JavaScript!');
    var express = require('express');
    var app = express();
    app.get('/', main$lambda);
    app.listen(3000, main$lambda_0);
  }
  _.main_kand9s$ = main;
  Kotlin.defineModule('index', _);
  main([]);
  return _;
}(module.exports, require('kotlin')));

感想

最初から最後までCLIとVSCodeだけで書けました。

調べているとGradleやMavenのようなツールが当たり前のように出てくるけど、普段使わないので調べ方で戸惑いました。

この仕組みが実用的かどうかはまだ何とも言えない段階な気もするので、とりあえずはこんなこともできるよってくらいの認識で良さそうです。

参考