JavaScriptモジュール
Kotlinプロジェクトは、さまざまな一般的なモジュールシステムに対応したJavaScriptモジュールにコンパイルできます。現在、JavaScriptモジュールに対して以下の構成をサポートしています。
- [AMDとCommonJSの両方に対応するUnified Module Definitions (UMD)。
UMDモジュールは、インポートなしで、またはモジュールシステムが存在しない場合でも実行できます。これは、
browser
およびnodejs
ターゲットのデフォルトオプションです。 - 特にRequireJSライブラリで使用されるAsynchronous Module Definitions (AMD)。
- Node.js/npmで広く使用されているCommonJS
(
require
関数とmodule.exports
オブジェクト)。 - プレーン。モジュールシステム用にコンパイルしません。グローバルスコープでモジュール名を使用してアクセスできます。
ブラウザターゲット
Webブラウザ環境でコードを実行し、UMD以外のモジュールシステムを使用する場合は、webpackTask
構成ブロックで目的のモジュールタイプを指定できます。たとえば、CommonJSに切り替えるには、次のようにします。
kotlin {
js {
browser {
webpackTask {
output.libraryTarget = "commonjs2"
}
}
binaries.executable()
}
}
Webpackは、CommonJSの2つの異なる種類、commonjs
とcommonjs2
を提供します。これらは宣言の利用方法に影響を与えます。ほとんどの場合、生成されたライブラリにmodule.exports
構文を追加するcommonjs2
を使用することをお勧めします。または、CommonJS仕様に厳密に準拠するcommonjs
オプションを選択することもできます。commonjs
とcommonjs2
の違いについて詳しくは、Webpackリポジトリを参照してください。
JavaScriptライブラリとNode.jsファイル
JavaScriptまたはNode.js環境で使用するためのライブラリを作成し、別のモジュールシステムを使用する場合は、手順が少し異なります。
ターゲットモジュールシステムの選択
ターゲットモジュールシステムを選択するには、GradleビルドスクリプトでmoduleKind
コンパイラオプションを設定します。
- Kotlin
- Groovy
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
(デフォルト)、commonjs
、amd
、plain
です。
これは、webpackTask.output.libraryTarget
の調整とは異なります。ライブラリターゲットは、(コードがすでにコンパイルされた後)_webpackによって生成される_出力を変更します。compilerOptions.moduleKind
は、_Kotlinコンパイラによって_生成される出力を変更します。
Kotlin Gradle DSLには、CommonJSモジュール種類を設定するためのショートカットもあります。
kotlin {
js {
useCommonJs()
// ...
}
}
@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() + "!" // error here
より深いパッケージ階層のインポート
前の例では、JavaScriptモジュールは単一のパッケージをエクスポートしています。
ただし、一部のJavaScriptライブラリは、モジュール内から複数のパッケージをエクスポートします。
このケースは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モジュールとダウンロード可能な.js
ファイルの両方としてライブラリを配布します。これらのファイルは、プロジェクトの静的リソースにコピーして、<script>
タグを介して含めることができます。 @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は、Kotlin/JS標準ライブラリとともに単一のファイルとして配布され、それ自体がUMDモジュールとしてコンパイルされているため、上記のどのモジュールシステムでも使用できます。 Kotlin/JSのほとんどのユースケースでは、NPMでkotlin
パッケージとして入手可能なkotlin-stdlib-js
へのGradle依存関係を使用することをお勧めします。