In our configuration, we have a multi-project Gradle build:
- a “shared” project with the Kotlin sources and the related unit tests. It has a specific “shared” sourceSet that is standard-library-agnostic and that can be imported in the JS build.
- a “typescript” project that contains all of the legacy sources and that depends on the build of the “js” project.
Migration pain points
Kotlin seems to deliver its promises, the migration is so far a success. Congratulations for the solidity of this early version
I still want to share some pain points. Indeed, some issues I encountered might already have a solution. The current tooling around Kotlin-JS seems to be targeting Web development. As we’re instead building and publishing a Node package, I encountered a number of specific needs.
Typescript type definition
We need to provide Typescript type definitions along with the JS sources. At the moment, we maintain them manually, but that’s a lot of hassle for something that actually looks easy to automate.
We need to distribute our NPM package with a package.json file describing the right dependencies (at least kotlin, in the correct version). kotlin-frontend-plugin can generate such a package.json file, but only if at least one NPM dependency is specified. Also, most of the fields receive dummy/invalid values that can’t be configured. So it doesn’t seem to be the right tool for our needs. For now, we use a simple groovy template for this purpose.
The fact that the latest
kotlin library on npmjs is in version
1.1.0, and therefore different from the version of
kotlin we specify in our build (
1.1.2-2), doesn’t help.
Being able to expose the functions of the companion object as static functions on the JS classes would be really cool. This would help us preserve backwards-compatibility as we migrate our code to Typescript.
Incompatible standard libraries
Math is not visible with the Kotlin JS standard library. Our workaround was to create a
kotlin.js.Math in our JS build.
I haven’t searched very far here, but it seems like
Dates, number formats… are not necessarily behaving in the same way in the Java build and the JS build. I wonder if this is on purpose (APIs seen as too platform-specific) or if this will be improved in future versions.
@JsName is not available in the “Java” standard library, so we can’t use directly the annotation on our shared code. Our workaround was here also to create a typealias.
@JsName required on all functions
@JsName is supposed to be useful in case of function overload. However, it seems like the compiler will always add a suffix to the function name if the annotation is omitted. As a result, we have to add the annotation on each and every function of our codebase. This seems to be a bug.
We’re moving ahead with Kotlin, as it is the best solution to our use-case. None of the elements mentioned above is blocking. Thanks to all of the Kotlin team for the great work