JavaScriptモジュール
Kotlinプロジェクトを様々な人気モジュールシステム向けのJavaScriptモジュールにコンパイルできます。現在、JavaScriptモジュール向けに以下の設定をサポートしています。
- ESモジュール。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の2つの異なるフレーバー、commonjsとcommonjs2を提供しており、これらは宣言が利用可能になる方法に影響します。ほとんどの場合、生成されるライブラリに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()
// OR
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() + "!" // 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モジュールとしても、プロジェクトの静的リソースにコピーして<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はKotlin/JS標準ライブラリとして単一のファイルで配布されており、それ自体がUMDモジュールとしてコンパイルされているため、上記のどのモジュールシステムでも使用できます。Kotlin/JSのほとんどのユースケースでは、kotlin-stdlib-jsへのGradle依存関係を使用することをお勧めします。これはNPMでもkotlinパッケージとして利用可能です。
