KEEP icon indicating copy to clipboard operation
KEEP copied to clipboard

Use JavaScript modules from Kotlin

Open bashor opened this issue 9 years ago • 17 comments

Provide the way to add information about related JS module when write native declarations in Kotlin and use this information to generate dependencies.

bashor avatar May 17 '16 16:05 bashor

Thanks a lot for creating this proposal for JavaScript modules support, I really appreciate such open process.

What I like in the current proposal is a that this is a pragmatic solution that allows to choose how the generated code will load the modules (AMD, Common JS, UMD, etc.). Maybe the kind of module used could be just configured globally for a project, not sure if there is a real need to configure that for each module.

But the @JsModule and @JsPackage approach described in not what I had in mind, so let me propose an alternative approach that will maybe not be doable, or has already be evaluated, but I would like to understand why.

Kotlin 1.1 is intended to support both Java 9 module system and ES6 module system. Why not trying to find a pragmatic solution (accordingly to Kotlin mindset) to define modules in Kotlin in a unified way that could be used to support Jigsaw and ES6 modules?

I know there is differences between these module systems, but it seems to me that they share some common goals. Unlike Ceylon which created its own module system, Kotlin has wait enough for Jigsaw to be (almost) here so why not using that as an advantage to use the Kotlin way to handle Jigsaw modules to be able to generate also ES6 modules based on these common module metadatas?

If Kotlin stdlib is modularized, that could help to avoid generating a 800 kbytes+ monolitic kotlin.js file, which is one of the main blocker for Kotlin usage for client side application IMO.

Any thoughts about this common way of dealing with modules for both JVM and JavaScript platforms?

sdeleuze avatar May 18 '16 15:05 sdeleuze

Note it's only about consume JS modules in Kotlin. I.e. only about external declarations.

bashor avatar May 19 '16 20:05 bashor

@sdeleuze

Any thoughts about this common way of dealing with modules for both JVM and JavaScript platforms?

We should investigate it separately. TBH I think the supporting Jigsaw will not significantly affect on JS.

If Kotlin stdlib is modularized, that could help to avoid generating a 800 kbytes+ monolitic kotlin.js file, which is one of the main blocker for Kotlin usage for client side application IMO.

We can split kotlin.js independently of Jigsaw or JVM part.

Advantages of the one "big" file:

  • simpler to manage (for users, tools) You should not think which files you need in which order they should be loaded
  • it can be cashed (will be loaded once and for a long time)

Disadvantages:

  • it's big :)

Personally, I prefer to have one "big" file with analyzer friendly code. So for production You can minify your code + kotlin.js to get js file(s) with only necessary part.

In addition I don't know how to split it in the best way. To tiny core.js and big stdlib.js? So do we really need core.js w/o stdlib.js? I would not like to develop w/o all these useful funs.

Anyway feel free to create issue or post where we can discuss about it separately.

bashor avatar May 19 '16 20:05 bashor

Accidentally some part of discussion is here

bashor avatar May 19 '16 20:05 bashor

The problem is not only consume but declare modules too. Some libraries like Aurelia needs this kind of structure and I had to create and define the modules by hand to let the systemjs load them, so aurelia can use them.

I didn't think that kotlin should generate one JS for each file to be loaded as a module, because with that you will have to configure task builds using gulp or another to generate bundles. But after looking to the way kotlin resolve the project modules I think that, will a little change, you could use a way to continue working like today, but with some adapters to allow js module loaders to work.

A quick example is change the Kotlin.modules['my-module'] to Kotlin.modules.get("my-module").then(function(m) { .. do your job here }). And then, you could inject a load for all the project application to be compatible with AMD, SystemJS, CommonJS etc...

About the runtime, well while I can agree with you about the big size, that will be good for apps and no for simple apps (page scripts). If you have to load 800kb to create a script of ten lines, then I'll prefer to write in pure JS or Typescript.

And for some web apps that have multiple pages with little js inject into each, that is really a problem.

To be honest, I think that, for JS only, most of the library should be defined in the kotlin-js-library with the most native functions as possible, or with polyfills to it. If you are a JVM programmer, you will like to use the things that you know at the web, but if you are a frontend programmer, comming from JS / TS, you will hate the fact that you will need to create almost all support for the language to be more "javascript friendly".

danfma avatar May 29 '16 02:05 danfma

Ok so let's forget my idea for a common module support for Jigsaw and Javascript modules (maybe not doable) and let's discuss the scope of this proposal.

Note it's only about consume JS modules in Kotlin. I.e. only about external declarations.

So the current scope of this proposal is only about consuming existing JS Modules, so declaring JS modules written in Kotlin is totally out of the scope and won't be supported?

sdeleuze avatar Jun 02 '16 10:06 sdeleuze

@sdeleuze: the ability to generate JS modules from kotlin code will in master soon

bashor avatar Jun 02 '16 11:06 bashor

FYI, I will create a dedicated thread about removing unused code for frontend application in https://discuss.kotlinlang.org/c/javascript.

sdeleuze avatar Jun 02 '16 12:06 sdeleuze

Should it be possible to put @JsModule annotation on a non-toplevel declaration? I.e. is the code like this possible?

class A {
    @JsModule("bbb") @native class B {
    }
}

konsoletyper avatar Jun 29 '16 12:06 konsoletyper

Can @JsModule be nested? For example

@file:JsModule("foo")
package foo

@native fun bar()

@JsModule("baz") @native fun baz()

konsoletyper avatar Jun 29 '16 13:06 konsoletyper

Should it be possible to put @JsModule annotation on a non-toplevel declaration?

I'd prohibit it now.

Can @JsModule be nested? For example

I think no

bashor avatar Jun 29 '16 16:06 bashor

What if a file is marked with JsNonModule, it has foo method and another module with plain type calls foo? How should it be translated to JS?

konsoletyper avatar Jul 04 '16 12:07 konsoletyper

Is foo non-native declaration? Right now I'd prohibit non-native declarations inside file annotated by any of JsModule and JsNonModule.

bashor avatar Jul 04 '16 17:07 bashor

foo is a native declarations.

konsoletyper avatar Jul 05 '16 09:07 konsoletyper

Well, what is a problem? This case is the same as native foo inside file w/o any annotations.

bashor avatar Jul 05 '16 09:07 bashor

It looks inconsistent with, for example, object, members of which will be referenced via dot qualifier. Also, it's unclear what to do with UMD wrappers in this case.

konsoletyper avatar Jul 05 '16 09:07 konsoletyper

It looks inconsistent with, for example, object, members of which will be referenced via dot qualifier.

Please clarify your thought.

Also, it's unclear what to do with UMD wrappers in this case.

For UMD we said:

  • Prohibit to use native declarations annotated by JsNonModule and not annotated by JsModule when compile with module kind != PLAIN.
  • Prohibit to use declarations annotated by only JsNonModule or JsNonModule when compile with module kind == UMD.

bashor avatar Jul 05 '16 10:07 bashor