0
# JavaScript and WebAssembly Support
1
2
This document covers specialized support for Kotlin/JS and Kotlin/WebAssembly compilation with browser, Node.js, and other runtime targets.
3
4
```kotlin
5
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
6
```
7
8
## JavaScript Targets
9
10
### JS Target Configuration
11
12
```kotlin { .api }
13
interface KotlinJsTarget : KotlinTarget {
14
val irTarget: Boolean
15
16
fun browser(configure: KotlinJsBrowserDsl.() -> Unit = {})
17
fun nodejs(configure: KotlinJsNodeDsl.() -> Unit = {})
18
19
val testRuns: NamedDomainObjectContainer<KotlinTargetTestRun<*>>
20
val compilations: NamedDomainObjectContainer<KotlinJsCompilation>
21
}
22
```
23
24
**Basic JS Target Setup:**
25
26
```kotlin
27
kotlin {
28
js(IR) { // Use IR compiler (recommended)
29
browser {
30
webpackTask {
31
outputFileName = "app.js"
32
sourceMaps = true
33
}
34
35
distribution {
36
outputDirectory = File("$projectDir/web")
37
}
38
}
39
40
nodejs {
41
runTask {
42
args.add("--experimental-modules")
43
}
44
}
45
}
46
}
47
```
48
49
### Browser Configuration
50
51
```kotlin { .api }
52
interface KotlinJsBrowserDsl {
53
fun webpackTask(configure: KotlinWebpack.() -> Unit)
54
fun runTask(configure: KotlinWebpack.() -> Unit)
55
fun testTask(configure: KotlinWebpack.() -> Unit)
56
57
val distribution: Distribution
58
}
59
60
interface KotlinWebpack : Task {
61
var outputFileName: String
62
var sourceMaps: Boolean
63
var devServer: KotlinWebpackDevServer?
64
65
val entry: RegularFileProperty
66
val destinationDirectory: DirectoryProperty
67
val configDirectory: DirectoryProperty
68
}
69
70
interface KotlinWebpackDevServer {
71
var enabled: Boolean
72
var port: Int
73
var proxy: MutableMap<String, String>
74
var static: MutableList<String>
75
}
76
```
77
78
**Advanced Browser Configuration:**
79
80
```kotlin
81
kotlin {
82
js(IR) {
83
browser {
84
webpackTask {
85
outputFileName = "myapp.js"
86
sourceMaps = true
87
88
devServer = KotlinWebpackDevServer().apply {
89
enabled = true
90
port = 3000
91
proxy.apply {
92
put("/api", "http://localhost:8080")
93
}
94
static.apply {
95
add("static")
96
add("resources")
97
}
98
}
99
}
100
101
runTask {
102
sourceMaps = false
103
devtool = "eval-cheap-source-map"
104
}
105
106
testTask {
107
useKarma {
108
useChromeHeadless()
109
useFirefoxHeadless()
110
}
111
}
112
113
distribution {
114
outputDirectory = File("$buildDir/distributions")
115
}
116
}
117
}
118
}
119
```
120
121
### Node.js Configuration
122
123
```kotlin { .api }
124
interface KotlinJsNodeDsl {
125
fun runTask(configure: NodeJsExec.() -> Unit)
126
fun testTask(configure: NodeJsExec.() -> Unit)
127
}
128
129
interface NodeJsExec : Exec {
130
val args: MutableList<String>
131
val environment: MutableMap<String, String>
132
val ignoreExitValue: Boolean
133
}
134
```
135
136
**Node.js Configuration Example:**
137
138
```kotlin
139
kotlin {
140
js(IR) {
141
nodejs {
142
runTask {
143
args.addAll("--experimental-modules", "--trace-warnings")
144
environment["NODE_ENV"] = "development"
145
}
146
147
testTask {
148
args.add("--experimental-vm-modules")
149
environment["NODE_OPTIONS"] = "--max-old-space-size=4096"
150
}
151
}
152
}
153
}
154
```
155
156
## WebAssembly Targets
157
158
### WASM-JS Target
159
160
```kotlin { .api }
161
@ExperimentalWasmDsl
162
interface KotlinWasmJsTarget : KotlinTarget {
163
fun browser(configure: KotlinWasmJsBrowserDsl.() -> Unit = {})
164
fun nodejs(configure: KotlinWasmJsNodeDsl.() -> Unit = {})
165
fun d8(configure: KotlinWasmJsD8Dsl.() -> Unit = {})
166
}
167
168
interface KotlinWasmJsBrowserDsl {
169
fun webpackTask(configure: KotlinWebpack.() -> Unit)
170
fun runTask(configure: KotlinWebpack.() -> Unit)
171
fun testTask(configure: KotlinWebpack.() -> Unit)
172
}
173
```
174
175
**WASM-JS Configuration:**
176
177
```kotlin
178
kotlin {
179
@OptIn(ExperimentalWasmDsl::class)
180
wasmJs {
181
browser {
182
webpackTask {
183
outputFileName = "app.wasm.js"
184
sourceMaps = true
185
}
186
}
187
188
nodejs {
189
runTask {
190
args.add("--experimental-wasm-modules")
191
}
192
}
193
194
d8 {
195
// V8 shell configuration for testing
196
}
197
}
198
}
199
```
200
201
### WASM-WASI Target
202
203
```kotlin { .api }
204
@ExperimentalWasmDsl
205
interface KotlinWasmWasiTarget : KotlinTarget {
206
fun nodejs(configure: KotlinWasmWasiNodeDsl.() -> Unit = {})
207
}
208
```
209
210
**WASM-WASI Configuration:**
211
212
```kotlin
213
kotlin {
214
wasmWasi {
215
nodejs {
216
runTask {
217
args.addAll("--experimental-wasi-unstable-preview1", "--experimental-wasm-bigint")
218
}
219
}
220
}
221
}
222
```
223
224
## NPM and Yarn Integration
225
226
### NPM Dependencies
227
228
```kotlin { .api }
229
// NPM dependency declaration
230
fun npm(name: String, version: String): NpmDependency
231
fun npm(name: String, version: String, generateExternals: Boolean): NpmDependency
232
fun devNpm(name: String, version: String): NpmDependency
233
fun peerNpm(name: String, version: String): NpmDependency
234
fun optionalNpm(name: String, version: String): NpmDependency
235
```
236
237
**NPM Usage Example:**
238
239
```kotlin
240
kotlin {
241
js(IR) {
242
browser()
243
nodejs()
244
}
245
246
sourceSets {
247
jsMain {
248
dependencies {
249
// Kotlin wrappers
250
implementation("org.jetbrains.kotlin-wrappers:kotlin-react:18.2.0-pre.467")
251
implementation("org.jetbrains.kotlin-wrappers:kotlin-react-dom:18.2.0-pre.467")
252
253
// NPM packages
254
implementation(npm("react", "18.2.0"))
255
implementation(npm("react-dom", "18.2.0"))
256
implementation(npm("lodash", "4.17.21"))
257
258
// Development dependencies
259
implementation(devNpm("webpack", "5.88.0"))
260
implementation(devNpm("webpack-dev-server", "4.15.1"))
261
}
262
}
263
}
264
}
265
```
266
267
### Yarn Configuration
268
269
```kotlin { .api }
270
// Configure Yarn in root project
271
rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin> {
272
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().apply {
273
yarnLockMismatchReport = org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockMismatchReport.WARNING
274
reportNewYarnLock = false
275
yarnLockAutoReplace = false
276
}
277
}
278
```
279
280
## D8 Engine Support
281
282
### D8 Configuration
283
284
```kotlin { .api }
285
interface D8RootExtension {
286
val version: Property<String>
287
val downloadBaseUrl: Property<String>
288
val installationDirectory: DirectoryProperty
289
}
290
291
interface D8EnvSpec {
292
val version: String
293
val downloadUrl: String
294
val executablePath: String
295
}
296
```
297
298
**D8 Setup:**
299
300
```kotlin
301
// Configure D8 for WASM testing
302
rootProject.extensions.configure<org.jetbrains.kotlin.gradle.targets.wasm.d8.D8RootExtension> {
303
version.set("11.4.183")
304
downloadBaseUrl.set("https://storage.googleapis.com/chromium-v8/official/canary")
305
}
306
307
kotlin {
308
wasmJs {
309
d8 {
310
// D8-specific configuration
311
}
312
}
313
}
314
```
315
316
### D8 Tasks
317
318
```kotlin { .api }
319
abstract class D8Exec : AbstractExecTask<D8Exec> {
320
abstract val inputFileProperty: RegularFileProperty
321
abstract val outputFileProperty: RegularFileProperty
322
abstract val d8Args: ListProperty<String>
323
}
324
325
abstract class D8SetupTask : DefaultTask() {
326
abstract val d8EnvSpec: Property<D8EnvSpec>
327
abstract val destinationDirectory: DirectoryProperty
328
}
329
```
330
331
## JavaScript Module Systems
332
333
### Module Kind Configuration
334
335
```kotlin { .api }
336
enum class KotlinJsModuleKind {
337
MODULE_AMD, // AMD modules (require.js)
338
MODULE_COMMONJS, // CommonJS modules (Node.js)
339
MODULE_PLAIN, // Plain JS (global scope)
340
MODULE_UMD, // Universal Module Definition
341
MODULE_ES // ES6 modules
342
}
343
```
344
345
**Module Configuration:**
346
347
```kotlin
348
kotlin {
349
js(IR) {
350
compilations.all {
351
compilerOptions.configure {
352
moduleKind.set(KotlinJsModuleKind.MODULE_ES)
353
target.set("es2015")
354
sourceMap.set(true)
355
sourceMapEmbedSources.set(org.jetbrains.kotlin.gradle.dsl.SourceMapEmbedSources.SOURCE_MAP_SOURCE_CONTENT_ALWAYS)
356
}
357
}
358
}
359
}
360
```
361
362
## Testing Configuration
363
364
### Browser Testing
365
366
```kotlin { .api }
367
// Karma test configuration
368
testTask {
369
useKarma {
370
useChromeHeadless()
371
useFirefoxHeadless()
372
373
webpackConfig.cssSupport {
374
enabled.set(true)
375
}
376
377
webpackConfig.bundleAnalyzerReportDir = file("$buildDir/reports/webpack")
378
}
379
}
380
```
381
382
### Node.js Testing
383
384
```kotlin
385
kotlin {
386
js(IR) {
387
nodejs {
388
testTask {
389
args.addAll(
390
"--experimental-vm-modules",
391
"--experimental-wasm-modules"
392
)
393
394
environment["NODE_OPTIONS"] = "--max-old-space-size=4096"
395
environment["NODE_ENV"] = "test"
396
}
397
}
398
}
399
}
400
```
401
402
## Build Output Structure
403
404
### Distribution Directory
405
406
```kotlin { .api }
407
interface Distribution {
408
var outputDirectory: File
409
var name: String
410
411
fun from(source: Any)
412
fun exclude(pattern: String)
413
fun include(pattern: String)
414
}
415
```
416
417
**Distribution Configuration:**
418
419
```kotlin
420
kotlin {
421
js(IR) {
422
browser {
423
distribution {
424
outputDirectory = File("$projectDir/web")
425
}
426
}
427
}
428
}
429
```
430
431
## WebPack Integration
432
433
### WebPack Task Configuration
434
435
```kotlin { .api }
436
abstract class KotlinWebpack : Task {
437
abstract val entry: RegularFileProperty
438
abstract val outputFileName: Property<String>
439
abstract val destinationDirectory: DirectoryProperty
440
441
abstract val sourceMaps: Property<Boolean>
442
abstract val devtool: Property<String>
443
abstract val mode: Property<String>
444
445
abstract val configDirectory: DirectoryProperty
446
abstract val reportEvaluatedConfigFile: RegularFileProperty
447
}
448
```
449
450
**Advanced WebPack Configuration:**
451
452
```kotlin
453
kotlin {
454
js(IR) {
455
browser {
456
webpackTask {
457
outputFileName = "bundle.[contenthash].js"
458
sourceMaps = false
459
mode = "production"
460
461
// Custom webpack configuration
462
File(project.projectDir, "webpack.config.d/custom.js").writeText("""
463
config.optimization = {
464
splitChunks: {
465
chunks: 'all'
466
}
467
};
468
""".trimIndent())
469
}
470
}
471
}
472
}
473
```
474
475
## External Declarations
476
477
### JavaScript Externals
478
479
```kotlin
480
// @file:JsModule annotation for NPM modules
481
@file:JsModule("lodash")
482
external fun debounce(func: () -> Unit, wait: Int): () -> Unit
483
484
// @JsNonModule for global libraries
485
@JsNonModule
486
@JsName("jQuery")
487
external val `$`: dynamic
488
```
489
490
### TypeScript Definitions
491
492
```kotlin
493
// Generate TypeScript definitions
494
tasks.register("generateTypeScriptDefinitions") {
495
dependsOn("compileKotlinJs")
496
497
doLast {
498
val outputDir = file("$buildDir/js/packages/${project.name}/kotlin")
499
// Generate .d.ts files from Kotlin/JS output
500
}
501
}
502
```