JavaScriptモジュール
Kotlinプロジェクトを、さまざまな主要なモジュールシステム向けのJavaScriptモジュールにコンパイルできます。現在、JavaScriptモジュールに対して以下の構成をサポートしています:
- ES Modules: JavaScriptでモジュールを宣言するための標準的な方法です(
import/exportJavaScript構文を使用)。targetがes2015に設定されている場合、デフォルトで使用されます。 - Unified Module Definitions (UMD): AMDとCommonJSの両方に互換性があります。UMDモジュールは、インポートせずに実行することや、モジュールシステムが存在しない環境で実行することも可能です。これは
browserおよびnodejsターゲットのデフォルトのオプションです。 - Asynchronous Module Definitions (AMD): 特にRequireJSライブラリで使用されます。
- CommonJS: Node.js/npmで広く使用されています(
require関数とmodule.exportsオブジェクト)。 - Plain: どのモジュールシステム向けにもコンパイルしません。グローバルスコープ内の名前でモジュールにアクセスできます。
ブラウザターゲット
ウェブブラウザ環境でコードを実行する予定があり、UMD以外のモジュールシステムを使用したい場合は、webpackTask構成ブロックで目的のモジュールタイプを指定できます。例えば、CommonJSに切り替えるには以下のように記述します:
kotlin {
js {
browser {
webpackTask {
output.libraryTarget = "commonjs2"
}
}
binaries.executable()
}
}Webpackはcommonjsとcommonjs2という2つの異なるフレーバーのCommonJSを提供しており、これらは宣言を公開する方法に影響します。ほとんどの場合、生成されたライブラリにmodule.exports構文を追加するcommonjs2が必要になるでしょう。あるいは、CommonJS仕様に厳密に準拠したcommonjsオプションを選択することもできます。commonjsとcommonjs2の違いについて詳しく知るには、Webpackのリポジトリを参照してください。
JavaScriptライブラリとNode.jsファイル
JavaScriptまたはNode.js環境で使用するライブラリを作成しており、別のモジュールシステムを使用したい場合、手順が少し異なります。
ターゲットモジュールシステムの選択
ターゲットとなるモジュールシステムを選択するには、GradleビルドスクリプトでmoduleKindコンパイラオプションを設定します。
tasks.withType<org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrLink> {
compilerOptions.moduleKind.set(org.jetbrains.kotlin.gradle.dsl.JsModuleKind.MODULE_COMMONJS)
}compileKotlinJs.compilerOptions.moduleKind = org.jetbrains.kotlin.gradle.dsl.JsModuleKind.MODULE_COMMONJS利用可能な値は、umd (デフォルト)、es、commonjs、amd、plain です。
これは
webpackTask.output.libraryTargetを調整することとは異なります。ライブラリターゲットは(コードがコンパイルされた後に)webpackによって生成される出力を変更します。compilerOptions.moduleKindは Kotlinコンパイラによって生成される 出力を変更します。
Kotlin Gradle DSLでは、CommonJSおよびESMのモジュール種別を設定するためのショートカットも用意されています:
kotlin {
js {
useCommonJs()
// または
useEsModules()
// ...
}
}@JsModule アノテーション
externalなクラス、パッケージ、関数、プロパティがJavaScriptモジュールであることをKotlinに伝えるには、@JsModule アノテーションを使用できます。例えば、"hello" という名前の次のようなCommonJSモジュールがあるとします:
module.exports.sayHello = function (name) { alert("Hello, " + name); }Kotlinでは次のように宣言する必要があります:
@JsModule("hello")
external fun sayHello(name: String)パッケージへの @JsModule の適用
JavaScriptライブラリの中には、関数やクラスではなくパッケージ(名前空間)をエクスポートするものがあります。 JavaScriptの観点では、これはクラス、関数、プロパティをメンバとして持つオブジェクトです。 これらのパッケージをKotlinのオブジェクトとしてインポートするのは、不自然に見えることがよくあります。 コンパイラは、以下の記法を使用して、インポートされたJavaScriptパッケージをKotlinのパッケージにマッピングできます:
@file:JsModule("extModule")
package ext.jspackage.name
external fun foo()
external class Cこれに対応するJavaScriptモジュールは、次のように宣言されているものとします:
module.exports = {
foo: { /* some code here */ },
C: { /* some code here */ }
}@file:JsModule アノテーションが付けられたファイルでは、externalではないメンバを宣言することはできません。 以下の例はコンパイルエラーになります:
@file:JsModule("extModule")
package ext.jspackage.name
external fun foo()
fun bar() = "!" + foo() + "!" // ここでエラーが発生より深いパッケージ階層のインポート
前の例では、JavaScriptモジュールは単一のパッケージをエクスポートしていました。 しかし、JavaScriptライブラリの中には、1つのモジュール内から複数のパッケージをエクスポートするものもあります。 このケースもKotlinでサポートされていますが、インポートするパッケージごとに新しい .kt ファイルを宣言する必要があります。
例えば、先ほどの例を少し複雑にしてみましょう:
module.exports = {
mylib: {
pkg1: {
foo: function () { /* some code here */ },
bar: function () { /* some code here */ }
},
pkg2: {
baz: function () { /* some code here */ }
}
}
}このモジュールをKotlinでインポートするには、2つのKotlinソースファイルを書く必要があります:
@file:JsModule("extModule")
@file:JsQualifier("mylib.pkg1")
package extlib.pkg1
external fun foo()
external fun bar()および
@file:JsModule("extModule")
@file:JsQualifier("mylib.pkg2")
package extlib.pkg2
external fun baz()@JsNonModule アノテーション
宣言に @JsModule が付いている場合、JavaScriptモジュールとしてコンパイルしない環境ではKotlinコードからその宣言を使用できません。 通常、開発者はライブラリをJavaScriptモジュールとしてだけでなく、プロジェクトの静的リソースにコピーして <script> タグでインクルードできるダウンロード可能な .js ファイルとしても配布します。非モジュール環境から @JsModule 宣言を使用しても問題ないことをKotlinに伝えるには、@JsNonModule アノテーションを追加します。例えば、次のようなJavaScriptコードを考えてみましょう:
function topLevelSayHello (name) { alert("Hello, " + name); }
if (module && module.exports) {
module.exports = topLevelSayHello;
}Kotlinからは次のように記述できます:
@JsModule("hello")
@JsNonModule
@JsName("topLevelSayHello")
external fun sayHello(name: String)Kotlin標準ライブラリで使用されているモジュールシステム
Kotlin/JS標準ライブラリは、単一のファイルとして配布されており、それ自体がUMDモジュールとしてコンパイルされています。そのため、上述のどのモジュールシステムとも併用できます。Kotlin/JSのほとんどのユースケースでは、kotlin-stdlib-js へのGradle依存関係を使用することをお勧めします。これはNPMでも kotlin パッケージとして利用可能です。
