cfnz / muirwik-starterapp

Muirwik Starter Application
Mozilla Public License 2.0
8 stars 2 forks source link

Uncaught TypeError: e.defineModule is not a function #4

Open galex opened 5 years ago

galex commented 5 years ago

Hello, in reference to how I get the dependencies of my MPP dependencies explained in #2, when running dce-kotlin-js plugin with the webpack.config.prod.js I'm getting the following error:

kotlinx-serialization-runtime-js.js:9722 Uncaught TypeError: e.defineModule is not a function
    at Object.r (kotlinx-serialization-runtime-js.js:9722)
    at Object.<anonymous> (kotlinx-serialization-runtime-js.js:3)
    at n (bootstrap:19)
    at Object.<anonymous> (mu51k-core.js:3504)
    at n (bootstrap:19)
    at Object.<anonymous> (AuthResponseUtils.kt:8)
    at Object.<anonymous> (AuthResponseUtils.kt:8)
    at n (bootstrap:19)
    at Object.<anonymous> (hyphenateProperty.js:17)
    at n (bootstrap:19)

Which happens on the follwing line:

Kotlin.defineModule('kotlinx-serialization-runtime-js', _);

I tried to add an alias for kotlinx-serialization-runtime-js but then in dev I get an error where this module cannot be found. Any idea?

cfnz commented 5 years ago

I have not had time to try it out yet in the demo app yet, but I was playing with kotlinx-serialization the other day... I did not get the serialization code actually working yet, but did get the build working... you may need to add:

// This build script and the serialization plugin below just to try and get serialization working....
buildscript {
    repositories {
        jcenter()
        maven("https://kotlin.bintray.com/kotlin-dev")
    }

    dependencies {
        classpath("org.jetbrains.kotlin:kotlin-serialization:1.3.20")
    }
}

Not sure if you will need the plugin, the docs on one hand say for kotlin 1.3.20 the plugin is included, but then further on down say you need it... but it might be only if you are using the code directly...

the plugin is added as:

apply {
    if (production) plugin("kotlin-dce-js")
    plugin("kotlinx-serialization")
}

Or... if the plugin is not needed, then rather than the above, you might just need

    maven("https://kotlin.bintray.com/kotlin-dev")

added to the normal repositories...

Not sure if it will help, but might get you going further... I will be going back to looking at kotlin serialization later...

galex commented 5 years ago

You can use this demo project to illustrate the issue: https://github.com/galex/reproducer-bug-ktor

Ecerything works if you run ./gradlew clean cleanDist build webpackDevServer everything works as expected but when I turn to production=true and run ./gradlew clean cleanDist build webpackDevServerProdConfig I get then the error I mentioned:

kotlinx-serialization-runtime-js.js:9722 Uncaught TypeError: e.defineModule is not a function
    at Object.r (kotlinx-serialization-runtime-js.js:9722)
    at Object.<anonymous> (kotlinx-serialization-runtime-js.js:3)
    at n (bootstrap:19)
    at Object.<anonymous> (mu51k-core.js:3504)
    at n (bootstrap:19)
    at Object.<anonymous> (AuthResponseUtils.kt:8)
    at Object.<anonymous> (AuthResponseUtils.kt:8)
    at n (bootstrap:19)
    at Object.<anonymous> (hyphenateProperty.js:17)
    at n (bootstrap:19)

So the issue lies into kotlin-dce-js which seems to remove that defineModule function. What I don't understand is why this error is not happening much before (I doubt this is the first module that is loaded) and how to solve this.

Also, it seems there's an effort by Jetbrains to not use gradle and only npm dependencies for React (https://github.com/JetBrains/create-react-kotlin-app), maybe we got it wrong using gradle at all? But then how do you deploy locally libraries to npm from an MPP? 🤔

cfnz commented 5 years ago

Hi, yes, I was able to reproduce the issue. I also went back to the starter app, it also has the issue but still lets the UI render.

It does indeed seem to be related to kotlin-dce-js...

I found that if I used the un-minified version of kotlin.js then it worked, but added a few 100 KBs to the bundle size.

I almost gave up looking for a solution and was going to ask elsewhere, and then I recalled something about configuring DCE to not wipe things that might be used elsewhere... a couple of trial and errors and... this fixes the issue in the starter app, have not tried it in your app. I added this to the existing if (production) code at the bottom of the build.gradle.kts file.

if (production) {
    val runDceKotlinJs: KotlinJsDce by tasks
    runDceKotlinJs.keep.add("kotlin.defineModule")

    val build by tasks
    ...

Still not sure why it would be needed... perhaps some of the included js files use it and the DCE tool doesn't see that and removes it... which means any included Kotlin module that has an included javascript might use code that gets stripped out by DCE... so it may be a reoccurring problem. Will have to wait and see how often it happens and ask elsewhere if it is reoccurring often.

In terms of not using Gradle, I think that is OK for more trivial apps and getting started with Kotlin and React... but once you get into using other Kotlin dependencies then it won't work so well. I also followed the advice in this video (not sure if I mentioned it before) and it did seem to help me along quite a bit.

Regards Colin

galex commented 5 years ago

I see, weird indeed. I fixed my issue by using the frontend-gradle-plugin.