Reputation: 580
I’ve been using Kotlin to develop a small 2D simulation software, and I’m using Kotlin multiplatform projects to make it run on both the JVM and in a browser. So far it works well.
However, I have a problem when I want to call functions defined in Kotlin/JS from regular Javascript.
To make my application work in the browser, I’m including the big JS file which is under the “build/distributions” folder after running the “build” Gradle task. When my Kotlin/JS application contains a main() function, this one is automatically being called when the HTML pag referencing the JS file is opened, and it works well.
But if I remove the main function and instead I create a start() function which is supposed to be called manually (after a click on a button, for instance), it does not work: it says the function start() is not defined even though it is declared in the Kotlin code.
After opening the generated JS file it seems that indeed there is no start() function. It looks like all the name of the functions have been minified.
I tried adding @JsName, but it didn’t change anything.
So I guess I’m doing something wrong, but I really don’t know what and how to make it work.
Note: I'm using Kotlin 1.3.70
EDIT: Here is the core of my build.gradle.kts:
plugins {
kotlin("js") version "1.3.70-eap-184"
}
repositories {
mavenLocal()
mavenCentral()
maven(url = "https://dl.bintray.com/kotlin/kotlin-eap")
}
dependencies {
}
kotlin {
target {
nodejs {
}
browser {
webpackTask {
mode = org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig.Mode.PRODUCTION
bin = "$projectDir/node_modules/$bin"
}
}
}
}
Upvotes: 1
Views: 1901
Reputation: 905
You should call the function with the module name and qualified name:
https://kotlinlang.org/docs/reference/js-to-kotlin-interop.html#package-structure
package my.qualified.packagename
fun foo() = "Hello"
alert(myModule.my.qualified.packagename.foo());
https://kotlinlang.org/docs/reference/js-to-kotlin-interop.html#jsname-annotation
In some cases (for example, to support overloads), Kotlin compiler mangles names of generated functions and attributes in JavaScript code. To control the generated names, you can use the
@JsName
annotation
UPD: You have two ways to change the module name:
1) If you use gradle you can add this code to your build.gradle
compileKotlinJs {
kotlinOptions.outputFile = "${rootDir}/web/app.js" // should be valid js variable name
}
or in your build.gradle.kts
kotlin {
target {
compilations.all {
kotlinOptions.outputFile = "${rootDir}/web/app.js"
}
}
}
in this case you should use generated file (app.js
) in the web
folder
(you can use other folder and file names).
2) You should create folder webpack.config.d
and create js file with any name, and content which configures library mode for webpack
config.output = config.output || {} // just in case where config.output is undefined
config.output.library = "libraryName" // should be valid js variable name
Upvotes: 3