Why is "Both-mode" (<https://blog.jetbrains.com/ko...
# javascript
r
Why is "Both-mode" (https://blog.jetbrains.com/kotlin/2020/03/kotlin-1-4-m1-released/#both-mode) better then publishing two different versions of a library (e.g.
1.0.0
and
1.0.0-IR
) and just let users choose the one they want to use? In my opinion "both-mode" makes a lot of mess for a Kotlin/JS project (e.g. strange module names).
h
Only a user here, but requiring the users to explicitly configure the dependency variant that should be used would be really strange... Additionally to the configuration of the compilation for their own project. It's much nicer to have the auto detection that is mentioned in the blog post and not having users to deal with it by hand. Must admit i have no idea what you mean by strange module names, though.
b
I'd vote for just enforcing IR compiler once it's stable
1
r
users have to deal with this by hand anyway - you need to set gradle option to use IR
if there was practice to put
-IR
in version number, at least it would be clear if a given library supports IR backend at all.
As for module names, if I build a library with
legacy
or
ir
the generated
package.json
have just
"name": "kvision"
. If I build with
both
I get two different modules: one is
kvision-jsLegacy
and the other
kvision-jsIr
. It's a problem when I need to use this module name in code.
Even the gradle configuration is problematic with
both
option. I currently have
dependsOn("testClasses")
and it works fine with
legacy
or
ir
. But with
both
the task is not there:
Copy code
FAILURE: Build failed with an exception.

Task with path 'testClasses' not found in project
It's definitely something wrong with this concept. And it surely took a lot of work to implement. And I would be happy to hear why it's better then just separate versions.
b
Why'd you need those explicit module names in code?
From consumer perspective gradle plugin is resolving the required variation of the package
It's a way to automatically load a module when it's added as a dependency of a project.
To load CSS and external JS from selected modules.
I haven't found any other way to make it work without requiring users to explicitly load it in the application code.
b
I see your problem. Couldn't you add those non js assets to kvision npm module and consume it as npm dependency?
That way you wouldn't have this issue anymore
r
probably it could work, I'll consider this option if I would have to deal with "both" :-)
b
You can even make it seemless from end user perspective by declaring npm module dependency in your lib as
api(npm("kvision-assets"), version)
i
We wanted to encapsulate different compiler artifacts inside one maven module to hide implementation details about particular compiler. It helps to migrate from current compiler to new one with just changing one property in gradle build, and not change GAV of any maven module. Additionally it is good point for future from compatibility point of view, if we will make IR compiler as a default, library names will not contain “weird” prefixes, and it will not lead to changing default version onto IR compiler, but legacy compiler with version “1.0.0-legacy”, and it brokes migration experience. And now user see “kotlinx-coroutines:1.0.0” and likely will write “kotlinx-coroutines:1.0.0”, and knowledge about additional prefixes can be error-prone factor. In fact choice of particular version of library (1.0 vs 1.0-IR) is a bit boilerplate and error-prone, because libraries are incompatible between compilers. We considered different options, but in the end we thought that it is some optimal solution (ofc with some disadvantages)
❤️ 2
In fact, now different problems can be on library-side, but library-users will not spend some time for resolving problems about using this or that version, especially on migration time
👍 2
r
library-authors are Kotlin users, too! 🙂 take care of them as well 🙂
in that case, shouldn't "both" be the default setting from the beginning?
i
Yes, of course, we take care, but unfortunately, there is balance between advantages and disadvantages, and we choose this way to distribute our libraries, and make this way for usage by other library authors too, so it can be used relatively easy, and it is how we take care 🙂 But of course there can be cases, where it will be inconvenient, and it is not problem to not use
both
mode for particular library, it can be done with difference in versions or name, if it is convenient for your particular case.
both
is only for library authoring in fact, it is questionable, what default should be, but we decided, that by default we will use
legacy
mode for compatibility, and necessity to enable both mode explicitly because of its specific behaviour
b
@Robert Jaros there's no good option here imo and JetBrains guys simply chose the least bad option
i
And you can override module name, which you will get in js file of legacy compiler There is option
moduleName
for this So you can use
Copy code
kotlin {
   js {
      moduleName = “foo”
      browser()
   }
}
And for legacy compiler
foo
name will be used