Is there anyone here who can help me understand `j...
# javascript
d
Is there anyone here who can help me understand
jsBrowserDevelopmentWebpack
? I feel like the output its producing is stale
Basically, my code lives in a subfolder under the root (called
site
). I am running my code in continuous mode (
gradlew ... -t
), and when I change some code, I have a javascript file dropped in three places:
Copy code
$root/build/js/packages/myproject/kotlin/myproject.js
$root/site/build/developmentExecutable/myproject.js
$root/site/compileSync/main/developmentExecutable/kotlin/myproject.js
The
site/build/developmentExecutable
path is the one generated by webpack, pretty sure, but when I make a change to my code, the other js files are updated but that one isn't
If I stop, clean my project, and rerun, then everything is up to date. So it's clear that the webpack produced output is bundling my code.
To make things fun: • I'm not using
jsBrowserRun
on my own - I have my own web server, and I want to take the distributed
js
file and use it directly. I wonder if
jsBrowserRun
does something interesting to make this work. • I also generate my own
index.html
file programatically. I don't write it by hand. Because of this, I compile everything into a monolithic js file, instead of a bunch of separate js files (because I couldn't ever figure out how to generate an index.html file which knows which order to specify all the broken up js files in)
I'm starting to think that jsBrowserDevelopmentWebpack is supposed to be a final task in a chain, and I'm over here putting another task after it. I'm a little worried about this line in the code, because it means it's trying to do something smart in continuous mode, and I just want to rely on it to create a file for me and go away 🙂
I'll try to create a minimal repro project later, to either see what I'm doing wrong or so that I can share something to demonstrate the problem
a
can you try registering the
site
directory as a Gradle task input?
Copy code
// build.gradle.kts

tasks.matching { it.name == "jsBrowserDevelopmentWebpack" }.configureEach {
  inputs.dir(layout.projectDir.dir("./site")
}
d
I have a repro case and was just about to file a bug and noticed one was already filed 2 years ago: https://youtrack.jetbrains.com/issue/KT-40573/Gradle-JS-continuous-mode-doesnt-update-js[…]-in-distributions-folder-with-jsBrowserDevelopmentWebpack
That's an old bug, so I'll create a new one with an attached project and repro steps just in case it's different.... but I think it's the same.
I spent a lot of time on that report JB so I hope someone fines it useful and easy to work with The short version is
jsBrowserDevelopmentWebtask --continuous
is busted.
@Adam S Yeah, today I'm going to experiment with causing the task to run extra aggressively. I started to experiment with that last night, but that caused a weird cast exception to happen, something to do with the custom Handle logic that the
KotlinWebpack
task is using: https://github.com/JetBrains/kotlin/blob/4af0f110c7053d753c92fd9caafb4be138fdafba/[…]org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpack.kt
I'm not sure I can just add my site as an input though, because it might be a code change from another module that
site
depends on which should kick off a recompilation.
a
Do you have Gradle build or config cache enabled?
d
Check out the bug I filed. It comes with a sample project. (I just tweaked permissions in case you weren't seeing it a few minutes ago, I guess they got uploaded with private permissions somehow)
It's literally a new web project created from scratch with a few minor modifications.
If you run
jsBrowserDevelopmentWebtask
but not in continuous mode, it works.
@Adam S OK out of curiosity, I disabled the build cache explicitly by putting
org.gradle.caching=false
in the
gradle.properties
file but still got the same behavior, sadly.
OK, I'm currently using an awful reflection hack which seems to be working. I hope sharing the hack will make someone at JB so nauseous that they'll prioritize fixing it 😏:
Copy code
private fun Project.hackWorkaroundSinceWebpackTaskIsBrokenInContinuousMode() {
    tasks.withType(KotlinWebpack::class.java).forEach { webpackTask ->
        // Gradle generates subclasses via bytecode generation magic. Here, we need
        // to grab the superclass to find the private field we want.
        webpackTask::class.java.superclass.declaredFields
            // Note: Isn't ever null for now but checking protects us against future
            // changes to KotlinWebpack
            .firstOrNull { it.name == "isContinuous" }
            ?.let { isContinuousField ->
                isContinuousField.isAccessible = true
                isContinuousField.setBoolean(webpackTask, false)
            }
    }
}
(The code above sets this value to false.) JB folks, I appreciate that the
KotlinWebpack
task is trying to do something smart in live reloading mode (probably related to performance?) but it's busted. I wonder if it's worth just always treating
isContinuous
as false for now until someone on your team has a chance to dig into this further.