Hi everyone, I have a problem in setting up a mult...
# javascript
p
Hi everyone, I have a problem in setting up a multimodule gradle project leveraging kotlinjs and I'm looking for help. this is my project structure:
Copy code
Root project 'kjs'
\--- Project ':web'
in the web project I have configured the kotlin multiplatform plugin as shown here, in the tutorial on kotlin doc portal about kotlinjs + react. my problem is that when I run the app I get an error in the browser console about a missing dependency on react-dom/client ``````
this is the content of the build.gradle.kts in the web project:
Copy code
plugins {
    kotlin("multiplatform") version "2.0.0"
    kotlin("plugin.serialization") version "2.0.0"
}

kotlin {
        js(IR) {
            browser {
                commonWebpackConfig {
                    cssSupport {
                        enabled.set(true)
                    }
                }
            }
            binaries.executable()
        }
        sourceSets {
        val jsMain by getting {
            dependencies {
                implementation(enforcedPlatform("org.jetbrains.kotlin-wrappers:kotlin-wrappers-bom:1.0.0-pre.787"))
                implementation("org.jetbrains.kotlin-wrappers:kotlin-react")

                implementation("org.jetbrains.kotlin-wrappers:kotlin-react-dom")

                implementation("org.jetbrains.kotlin-wrappers:kotlin-emotion")

                implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
                implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
            }
        }
    }
}
in the root project I'm just setting up the repos for all the subprojects:
Copy code
group = "org.xaos.supply"
version = "1.0-SNAPSHOT"

subprojects{
    repositories {
        mavenCentral()
    }
}
e
Can you look under the output directory and check whether you have a
kjs.js
file? Could you also paste the content of your
index.html
file?
It looks like you're trying to load the wrong JS file in your HTML file.
p
hi Edoardo, thank you for answering: I've no kjs.js file: kjs is the root project and there there is no actual source code, that's why I think that there is no kjs.js file. in the index.html I load the
kjs-web.js
file, the file generated relative to my javascript module in the project hierarchy
Copy code
Root project 'kjs' <- no source code
\--- Project ':web' <- multiplatform plugin is applied here, actual kotlin source code is here
e
Seems ok to me. I'll do a couple tests in a sample project as it's been a while I've used the browser target.
p
wow! thank you
e
Which task are you running to start the application? Also, which version of Kotlin are you using? Nevermind, it's 2.0
React works fine here it seems. I'm on 2.0.20-RC. App is started via
jsBrowserDevelopmentRun
p
jsBrowserDevelopmentRun, with gradle 8.7
e
To me it seems you're loading a JS file that hasn't been processed by Webpack
p
uhm...
e
What is your
<script>
src
value?
p
actually I'm just doing this
Copy code
import react.FC
import react.Fragment
import react.Props
import react.create
import react.dom.client.createRoot
import react.dom.html.ReactHTML.h1
import react.dom.html.ReactHTML.h3
import react.dom.html.ReactHTML.div
import react.dom.html.ReactHTML.p
import react.dom.html.ReactHTML.img
import web.dom.document

fun main() {
    val container = document.getElementById("root") ?: error("Couldn't find root container!")
    createRoot(container).render(Fragment.create {
        h1 {
            +"Hello, React+Kotlin/JS!"
        }
    })
}
index.html
Copy code
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello, Kotlin/JS!</title>
</head>
<body>
<div id="root"></div>
<script src="kjs-web.js"></script>
</body>
</html>
e
Looks ok. That's strange. Could you try switching to 2.0.20-RC? So that we are not working on a version that unfortunately had many issue.
p
do I need to add a different repo in the buildsource to get that version?
e
Nope. Just replace 2.0.0
p
👍
e
The serialization plugin might need to be updated too. You are also using an outdated version of
kotlinx-coroutines-core
, but I suppose for this sample you might just remove it.
p
I've removed the serialization plugin and the extra dependencies, just to be straight to the point
✔️ 1
nothing changed
always the same error
btw: I have this problem only in a gradle multimodule build
e
Can you open up kjs-web.js and check if it's minified or not?
p
in a plain gradle project with just the multiplatform plugin everithing works fine
Copy code
(function (factory) {
  if (typeof define === 'function' && define.amd)
    define(['exports', 'react-dom/client', 'react', './kotlin-kotlin-stdlib.js', './kotlin-react.js', './kotlin-react-dom.js', './kotlin-react-core.js'], factory);
  else if (typeof exports === 'object')
    factory(module.exports, require('react-dom/client'), require('react'), require('./kotlin-kotlin-stdlib.js'), require('./kotlin-react.js'), require('./kotlin-react-dom.js'), require('./kotlin-react-core.js'));
  else {
    if (typeof globalThis['react-dom/client'] === 'undefined') {
      throw new Error("Error loading module 'kjs:web'. Its dependency 'react-dom/client' was not found. Please, check whether 'react-dom/client' is loaded prior to 'kjs:web'.");
    }
    if (typeof react === 'undefined') {
      throw new Error("Error loading module 'kjs:web'. Its dependency 'react' was not found. Please, check whether 'react' is loaded prior to 'kjs:web'.");
    }
    if (typeof globalThis['kotlin-kotlin-stdlib'] === 'undefined') {
      throw new Error("Error loading module 'kjs:web'. Its dependency 'kotlin-kotlin-stdlib' was not found. Please, check whether 'kotlin-kotlin-stdlib' is loaded prior to 'kjs:web'.");
    }
    if (typeof globalThis['kotlin-react'] === 'undefined') {
      throw new Error("Error loading module 'kjs:web'. Its dependency 'kotlin-react' was not found. Please, check whether 'kotlin-react' is loaded prior to 'kjs:web'.");
    }
    if (typeof globalThis['kotlin-react-dom'] === 'undefined') {
      throw new Error("Error loading module 'kjs:web'. Its dependency 'kotlin-react-dom' was not found. Please, check whether 'kotlin-react-dom' is loaded prior to 'kjs:web'.");
    }
    if (typeof globalThis['kotlin-react-core'] === 'undefined') {
      throw new Error("Error loading module 'kjs:web'. Its dependency 'kotlin-react-core' was not found. Please, check whether 'kotlin-react-core' is loaded prior to 'kjs:web'.");
    }
    globalThis['kjs:web'] = factory(typeof globalThis['kjs:web'] === 'undefined' ? {} : globalThis['kjs:web'], globalThis['react-dom/client'], react, globalThis['kotlin-kotlin-stdlib'], globalThis['kotlin-react'], globalThis['kotlin-react-dom'], globalThis['kotlin-react-core']);
  }
}(function (_, $module$react_dom_client_y5z5eu, $module$react, kotlin_kotlin, kotlin_org_jetbrains_kotlin_wrappers_kotlin_react, kotlin_org_jetbrains_kotlin_wrappers_kotlin_react_dom, kotlin_org_jetbrains_kotlin_wrappers_kotlin_react_core) {
  'use strict';
  //region block: imports
  var createRoot = $module$react_dom_client_y5z5eu.createRoot;
  var Fragment = $module$react.Fragment;
  var toString = kotlin_kotlin.$_$.f3;
  var IllegalStateException_init_$Create$ = kotlin_kotlin.$_$.p;
  var create = kotlin_org_jetbrains_kotlin_wrappers_kotlin_react.$_$.a;
  var ReactHTML_getInstance = kotlin_org_jetbrains_kotlin_wrappers_kotlin_react_dom.$_$.a;
  var addChild = kotlin_org_jetbrains_kotlin_wrappers_kotlin_react_core.$_$.b;
  var Unit_getInstance = kotlin_kotlin.$_$.g1;
  var addChildNode = kotlin_org_jetbrains_kotlin_wrappers_kotlin_react_core.$_$.a;
  //endregion
  //region block: pre-declaration
  //endregion
  function main() {
    var tmp0_elvis_lhs = document.getElementById('root');
    var tmp;
    if (tmp0_elvis_lhs == null) {
      var message = "Couldn't find root container!";
      throw IllegalStateException_init_$Create$(toString(message));
    } else {
      tmp = tmp0_elvis_lhs;
    }
    var container = tmp;
    var tmp_0 = createRoot(container);
    var tmp_1 = Fragment;
    tmp_0.render(create(tmp_1, main$lambda));
  }
  function main$lambda($this$create) {
    // Inline function 'react.ChildrenBuilder.invoke' call
    // Inline function 'react.dom.html.ReactHTML.h1' call
    ReactHTML_getInstance();
    // Inline function 'react.IntrinsicType' call
    // Inline function 'kotlin.js.unsafeCast' call
    // Inline function 'kotlin.js.asDynamic' call
    var block = main$lambda$lambda;
    addChild($this$create, 'h1', block);
    return Unit_getInstance();
  }
  function main$lambda$lambda($this$h1) {
    // Inline function 'react.ChildrenBuilder.unaryPlus' call
    // Inline function 'react.ReactNode' call
    // Inline function 'kotlin.js.unsafeCast' call
    // Inline function 'kotlin.js.asDynamic' call
    var tmp$ret$2 = 'Hello, React+Kotlin/JS!';
    addChildNode($this$h1, tmp$ret$2);
    return Unit_getInstance();
  }
  function mainWrapper() {
    main();
  }
  mainWrapper();
  return _;
}));

//# sourceMappingURL=kjs-web.js.map
i'd say that it's not minified
e
Yeah that's not what is supposed to be loaded. It's
require
-ing other JS files.
Could you invoke
useEsModules()
under
js { ... }
?
p
now I have a big 404when loading kjs-web.js
if I load the .mjs file I have this error:
(btw what is an *.mjs file?)
e
mjs
is an extension used to identify JS file which use the ES2015 module system.
p
👍
e
I don't know what's going wrong on your end tbh. What you might want to do is push that sample project to GitHub, so that I can clone it.
p
ok
e
But it's definitely some weird behavior...
p
it seems strange also to me... my initial idea was that the multiplatform plugin was not meant to be used in a multimodule gradle build.. but looking on the internet it seemed that everyone could do that... but me, obviously
e
I've cloned it, let's see
p
I'm eager to know the dumb mistake I did 😄
e
I can reproduce the error, yup
Use
Copy code
<script src="web.js"></script>
Instead. There you go
p
wow
it works
thank yu very much!
e
If you want to be sure about which JS file name to use, you can set the Webpack output name via
Copy code
browser {
  webpackTask {
    mainOutputFileName = "custom-name.js"
  }
}
p
this is very interesting
e
But the key is, the module name is what will be used for the file name by default.
p
I've tried to tweak that name with the
moduleName
property but it actually doesn't work
if I change the module name actually I get back to the old error
e
moduleName
is used when compiling the various modules to their respective JS files. It's not used to produce the minified file via Webpack.
p
ok. just to summarize my understanding: • when I run the
jsBrowserDevelopmentRun
task the minified version of the jaavascript file is run • the reference file is the one I find in the build/dist directory under the gradle subproject
e
the reference file under build/dist
To distribute it (e.g., to a webserver) it's correct IIRC. The Webpack tasks will also output the bundled/minified files under
build/kotlin-webpack
p
ok, great
e
You can configure the distribution task via the
Copy code
browser {
  distribution { ... }
}
DSL in case.
I don't use the browser target so I don't know anything else
p
great, need to study more 😄 on fe development I'm totally out of my comfort zone 😄 (and that's why I'm trying out kotlinjs)
e
Well it's normal. Front-end with Kotlin/JS is a bit different compared to other platforms.