Skip to content

JavaScriptモジュール

Kotlinプロジェクトを、さまざまな一般的なモジュールシステム向けのJavaScriptモジュールとしてコンパイルできます。現在、JavaScriptモジュールに対して以下の設定をサポートしています。

  • Unified Module Definitions (UMD): AMDCommonJSの両方と互換性があります。UMDモジュールは、インポートされなくても、またはモジュールシステムが存在しない場合でも実行できます。これはbrowserおよびnodejsターゲットのデフォルトオプションです。
  • Asynchronous Module Definitions (AMD): 特にRequireJSライブラリで利用されます。
  • CommonJS: Node.js/npmで広く使用されています(require関数とmodule.exportsオブジェクト)。
  • Plain (プレーン): いかなるモジュールシステム用にもコンパイルしません。モジュールはグローバルスコープ内でその名前でアクセスできます。

ブラウザターゲット

コードをウェブブラウザ環境で実行し、UMD以外のモジュールシステムを使用したい場合、webpackTask設定ブロックで希望するモジュールタイプを指定できます。例えば、CommonJSに切り替えるには、以下を使用します。

groovy
kotlin {
    js {
        browser {
            webpackTask {
                output.libraryTarget = "commonjs2"
            }
        }
        binaries.executable()
    }
}

Webpackは、CommonJSの2つの異なるフレーバー、commonjscommonjs2を提供しており、これらは宣言が利用可能になる方法に影響を与えます。ほとんどの場合、生成されるライブラリにmodule.exports構文を追加するcommonjs2が望ましいでしょう。あるいは、CommonJS仕様に厳密に準拠するcommonjsオプションを選択することもできます。commonjscommonjs2の違いについてさらに学習するには、Webpackリポジトリを参照してください。

JavaScriptライブラリとNode.jsファイル

JavaScriptまたはNode.js環境で使用するライブラリを作成しており、異なるモジュールシステムを使用したい場合、手順はわずかに異なります。

ターゲットモジュールシステムの選択

ターゲットモジュールシステムを選択するには、GradleビルドスクリプトでmoduleKindコンパイラオプションを設定します。

kotlin
tasks.withType<org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrLink> {
    compilerOptions.moduleKind.set(org.jetbrains.kotlin.gradle.dsl.JsModuleKind.MODULE_COMMONJS)
}
groovy
compileKotlinJs.compilerOptions.moduleKind = org.jetbrains.kotlin.gradle.dsl.JsModuleKind.MODULE_COMMONJS

利用可能な値は、umd(デフォルト)、commonjsamdplainです。

NOTE

これはwebpackTask.output.libraryTargetの調整とは異なります。ライブラリターゲットは、(コードがすでにコンパイルされた後の)_webpackによって生成される_出力を変更します。compilerOptions.moduleKindは、_Kotlinコンパイラによって生成される_出力を変更します。

Kotlin Gradle DSLでは、CommonJSモジュール種別を設定するためのショートカットも用意されています。

kotlin
kotlin {
    js {
        useCommonJs()
        // ...
    }
}

@JsModuleアノテーション

externalなクラス、パッケージ、関数、またはプロパティがJavaScriptモジュールであることをKotlinに伝えるには、@JsModuleアノテーションを使用します。"hello"というCommonJSモジュールが以下のようにあるとします。

javascript
module.exports.sayHello = function (name) { alert("Hello, " + name); }

Kotlinでは、次のように宣言する必要があります。

kotlin
@JsModule("hello")
external fun sayHello(name: String)

@JsModuleをパッケージに適用する

JavaScriptライブラリの中には、関数やクラスの代わりにパッケージ(名前空間)をエクスポートするものがあります。 JavaScriptの観点から見ると、それはクラス、関数、プロパティであるメンバーを持つオブジェクトです。 これらのパッケージをKotlinオブジェクトとしてインポートすると、不自然に見えることがよくあります。 コンパイラは、インポートされたJavaScriptパッケージをKotlinパッケージに、以下の記法を使用してマッピングできます。

kotlin
@file:JsModule("extModule")

package ext.jspackage.name

external fun foo()

external class C

対応するJavaScriptモジュールが次のように宣言されている場合です。

javascript
module.exports = {
  foo: { /* some code here */ },
  C: { /* some code here */ }
}

@file:JsModuleアノテーションでマークされたファイルは、非externalメンバーを宣言できません。 以下の例は、コンパイル時エラーを生成します。

kotlin
@file:JsModule("extModule")

package ext.jspackage.name

external fun foo()

fun bar() = "!" + foo() + "!" // error here

より深いパッケージ階層のインポート

前の例では、JavaScriptモジュールは単一のパッケージをエクスポートしていました。 しかし、一部のJavaScriptライブラリは、単一モジュール内から複数のパッケージをエクスポートします。 このケースもKotlinでサポートされていますが、インポートする各パッケージごとに新しい.ktファイルを宣言する必要があります。

例えば、例を少し複雑にしてみましょう。

javascript
module.exports = {
  mylib: {
    pkg1: {
      foo: function () { /* some code here */ },
      bar: function () { /* some code here */ }
    },
    pkg2: {
      baz: function () { /* some code here */ }
    }
  }
}

このモジュールをKotlinにインポートするには、2つのKotlinソースファイルを記述する必要があります。

kotlin
@file:JsModule("extModule")
@file:JsQualifier("mylib.pkg1")

package extlib.pkg1

external fun foo()

external fun bar()

kotlin
@file:JsModule("extModule")
@file:JsQualifier("mylib.pkg2")

package extlib.pkg2

external fun baz()

@JsNonModuleアノテーション

宣言が@JsModuleとしてマークされている場合、JavaScriptモジュールとしてコンパイルしない限り、Kotlinコードからそれを使用することはできません。 通常、開発者はライブラリをJavaScriptモジュールとしてだけでなく、ダウンロード可能な.jsファイルとしても配布します。これらはプロジェクトの静的リソースにコピーして<script>タグを介してインクルードできます。 @JsModule宣言を非モジュール環境で使用しても問題ないことをKotlinに伝えるには、@JsNonModuleアノテーションを追加します。例えば、以下のJavaScriptコードを考えます。

javascript
function topLevelSayHello (name) { alert("Hello, " + name); }

if (module && module.exports) {
  module.exports = topLevelSayHello;
}

Kotlinからは次のように記述できます。

kotlin
@JsModule("hello")
@JsNonModule
@JsName("topLevelSayHello")
external fun sayHello(name: String)

Kotlin標準ライブラリが使用するモジュールシステム

Kotlinは、Kotlin/JS標準ライブラリを単一ファイルとして配布しています。これはそれ自体がUMDモジュールとしてコンパイルされているため、上記のどのモジュールシステムでも使用できます。Kotlin/JSのほとんどのユースケースでは、NPMでkotlinパッケージとしても利用可能なkotlin-stdlib-jsへのGradle依存関係を使用することをお勧めします。