Hi. I've upgraded a KMP project targeting `jvm` an...
# javascript
f
Hi. I've upgraded a KMP project targeting
jvm
and
js
to kotlin 2.0. In this project I've a gradle module producing a ES module (contains
useEsModules
). This module consumes a CJS module from NPM (
node-jose
), however the generated JS code does not seem to be correct. Looking into
build/dist/js/productionLibrary
, the generated code contains
Copy code
import * as Jose from 'node-jose';
and then uses
Jose
to access the exported symbols, e.g.
Copy code
Jose.JWK.asKey(...)
Looking into https://nodejs.org/docs/latest-v18.x/api/esm.html#esm_commonjs_namespaces, it seems the correct way of importing a CJS module in an ESM module would be
Copy code
import {default as Jose} from 'node-jose'
The
Jose
object is defined in Kotlin as
Copy code
@JsModule("node-jose")
@JsNonModule
external object Jose {
  ...
}
t
Valid declaration:
Copy code
@file:JsModule("node-jose")

@JsName("default")
external object Jose {
  ...
}
f
Thanks! That did solve my problem. I also needed to add
Copy code
@file:JsNonModule
to be able to use it from UMD.
t
Do you need UMD in fact?
f
Not sure. I've a multi-module project, and some where producing CJS while other were producing UMD (the default, right?).
One additional question: does this means that the way we annotate the kotlin source code with
@JsModule
depends on the target module? Because I went back to CJS and then I had to revert the change. I.e. use
Copy code
@JsModule("node-jose")
@JsNonModule
external object Jose {
   ...
}
t
In common case library can provide different bundles for different module types
f
How can that be achieved?
t
With
package.json
configuration
f
I see. Thanks! But I need KMP to produce artefacts for all the formats (CJS, ESM), right?
t
But I need KMP to produce artefacts for all the formats (CJS, ESM), right?
Library?
f
Sorry, not sure I understood the question. I've a multi-module KMP project, where: • Each module is a library. • Some modules depend on other modules. All modules should be consumed from pure JS/TS apps, both node or browser.
Is it possible to configure a module to simultaneously generate UMD, CJS, and ESM?
t
ESM works fine in Browser and Node.js
It's fine Kotlin output also
f
I see. So the suggestion is to target only ESM on all modules, since ESM is usable on all modern JS hosts, and supported by bundlers.
t
Yes
For bundlers is best input format
f
Thanks. One additional question: the
@JsModule
kotlin decoration that we discussed at the beginning of this question does depend on the output format of the module where it is used? I.e. if the output format is CJS, then I need to use the original annotation format, where
@JsModule
annotates the class directly, while if the output format is ESM then I need to annotate the file, as you suggested?
t
In common case - no
But library can provide different JS files for CJS and ESM for different reasons (backward compatibility for example).
Simpest solution - use ESM 🙂