Webpack Issues on a Gradle Kotlin/JS project

I’m trying to create a new project with Kotlin/JS and I’m running into some issues with the Webpack Server not appropriately hot reloading the changes. If I do a minimal change like this:

fun main() {
    println("Hello World!")
}

to:

fun main() {
    println("Hello World!")
    println("Hello Universe!")
}

The Webpack detects the change in the Main.kt file, but when I go check the webpage it does not show the changes at all. The messages being shown often are these:

[WDS] App updated. Recompiling...
[WDS] Nothing changed.

And when the webpage finally reflects the changes on the code, it does not show the latest change that I made, instead it shows a change that I could have made some time ago.

And last, but not least, it sometimes throws an error as well (after starting the server again and making a change to the code):

Module build failed (from C:/Users/xxxxxxx/Desktop/kotlin-js-demo/build/js/packages_imported/kotlin-source-map-loader/1.3.61/kotlin-source-map-loader.js):
Error: ENOENT: no such file or directory, open 'C:\Users\xxxxxxx\Desktop\kotlin-js-demo\build\js\packages\kotlin-js-demo\kotlin\kotlin-js-demo.js'

And I have to restart the server in order for the error to go away.

I would love to develop an app using Kotlin/JS but I simply can’t do it if the configuration is so mind boggingly unstable that I can’t even do the simplest of tasks without getting a massive headache.

Any help would be appreciated. Thanks.

PSA - All the configurations are the exact same as those shipped with the Kotlin/JS Gradle plugin. But for reference, here is my Webpack Config file:

var config = {
  mode: 'development',
  resolve: {
    modules: [
      "node_modules"
    ]
  },
  plugins: [],
  module: {
    rules: []
  }
};

// entry
if (!config.entry) config.entry = [];
config.entry.push("C:\\Users\\xxxxxxx\\Desktop\\kotlin-js-demo\\build\\js\\packages\\kotlin-js-demo\\kotlin\\kotlin-js-demo.js");
config.output = {
    path: "C:\\Users\\xxxxxxx\\Desktop\\kotlin-js-demo\\build\\distributions",
    filename: "kotlin-js-demo.js"
};

// source maps
config.module.rules.push({
        test: /\.js$/,
        use: ["kotlin-source-map-loader"],
        enforce: "pre"
});
config.devtool = 'eval-source-map';

// dev server
config.devServer = {
  "inline": true,
  "lazy": false,
  "noInfo": true,
  "open": true,
  "overlay": false,
  "port": 8080,
  "contentBase": [
    "C:\\Users\\xxxxxxx\\Desktop\\kotlin-js-demo\\build\\processedResources\\Js\\main"
  ]
};

// save evaluated config file
var util = require('util');
var fs = require("fs");
var evaluatedConfig = util.inspect(config, {showHidden: false, depth: null, compact: false});
fs.writeFile("C:\\Users\\xxxxxxx\\Desktop\\kotlin-js-demo\\build\\reports\\webpack\\kotlin-js-demo\\webpack.config.evaluated.js", evaluatedConfig, function (err) {});

module.exports = config

And here is my build.gradle file:

plugins {
    id 'org.jetbrains.kotlin.js' version '1.3.61'
}

group 'com.example'
version '1.0-SNAPSHOT'

repositories {
    jcenter()
    mavenCentral()
}

kotlin {
    target {
        browser()
        useCommonJs()
    }

    sourceSets["main"].dependencies {
        implementation npm("navigo", "7.1.2")
    }
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-js"
    implementation "org.jetbrains.kotlinx:kotlinx-html-js:0.6.12"
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core-js:1.3.3'
    testImplementation "org.jetbrains.kotlin:kotlin-test-js"
}

kotlin.target.browser { }

Failed to reproduce the problem. Do you run your application with gradlew run -t?

Yes. I have tried both gradlew run -t and gradlew run --continuous.

Can you attach a link to your project?

I have done some experimentation. My conclusions are that it doesn’t reload properly if I have NPM dependencies on the source sets, like this:

sourceSets["main"].dependencies {
    implementation npm("navigo", "7.1.2")
}

If I remove the NPM dependencies section it works just fine. It still throws the ENOENT error but it actually reloads the page as it should (so I can safely ignore the error, I guess?)

Anyways, here’s the link of my demo project:

https://mega.nz/#!8Ad2TA5Q!mqSHQKZxVDLzVj8ghlVia3P70pu6GbZIcHW6SC_5jCw

UPDATE: Adding these lines on a webpack.config.d/config.js file seems to fix the problem (no more ENOENT errors and it hot reloads properly with NPM dependencies):

// noinspection JSUnresolvedVariable
config.devServer = config.devServer || {}; // create devServer in case it is undefined
// noinspection JSUnresolvedVariable
config.devServer.watchOptions = {
    "aggregateTimeout": 5000,
    "poll": 1000
};

My theory is that perhaps the Webpack server doesn’t see the converted JavaScript files just right after they are compiled by the Kotlin compiler?

I saw this workaround on the following post: Kotlin JS + React, unstable building

1 Like