Kotlin and React Progress

So the new year is upon us and it’s time I got back to this. I’ve been a bit distracted lately – Christmas and all that, as well as building factories in Factorio.

This week I’ve tried to finish off my conversion to a React based interface. This has proved to be quite problematical, mostly because there seems to be two different build systems in play here – Kotlin’s build system in IDEA and the react build system via npm.

Moving to NPM

I tried at first to convert my existing project to use React, but that really didn’t seem obvious at all. Because I’d created my project using IDEA it didn’t seem to have any options to use a different build system, and I really don’t know enough about the internals to change it. I flirted briefly with attempting to use Gradle or Ant to build the whole thing, which should integrate into IDEA, but again a lack of knowledge (and given the time of year a lack of inspiration too!) proved too much.

I decided at this point to go back to the basics, and pretend I was making a completely new project, and started with the create-react-kotlin-app npm script, and the instructions there. This seemed to work, but again I don’t know enough about the internals to know how (yet!). Something to work on. However, I then had a working application, even it didn’t have any of my code in it yet. To compile and test it, instead of within IDEA I’m now using npm and it’s internal server; this is quite convenient although it’s a bit of a change of direction. I do find it annoying that it keeps recompiling though, as I save very frequently (I hit control-s pretty much automatically as I don’t trust things to not crash!).

At this point I could copy over some of my existing work, although most of the interface side of this will need to be rewritten. However, the message passing and existing entities are still usable.

The Web Worker

My big hurdle here, however, was that I already had an existing web worker that does most of the work. This is written in Kotlin and the output of this is a pure JS file. I have a script that copies the entity and message Kolin files into the new NPM based compiler so they can be used there (at some point I should work out how to make them not copied – this might be more possible now I’m not using IDEA for the main program compilation). The problem here is that the worker is compiled separately from the main project – it’s not a module as it’s not loaded by the main project.

As it stands I now have several stages to compilation

  • A module compile within IDEA to compile the worker
  • A script that combines the module output into a single javascript file
  • A copy of the combined output into the source area for the main application
  • An NPM based compile (which happens automatically) for the main application.

This, while a little bit clunky, does work and will be perfectly adequate for the present.

Importing the Worker

The next problem was caused by yet more lack of knowledge. NPM uses WebPack which takes the files used in the project and copies them to an output directory, and it also has an anti-cache renaming system applied (it puts a random string in the file name, so the browser can’t cache the contents of the file, forcing it to reload if I recompile). Unfortunately, I don’t know how it chooses which files to copy, and there wasn’t much in the way of documentation as to how to get a static javascript file to be included in a project, and crucially treated as a static file and not as a module to be included.

My first attempt was to use

@JsModule("src/worker/WitchWorker.js")
external val workerLocation: dynamic

fun main(args: Array<String>) {
   val worker = Worker(workerLocation)
...

This works up to a point – we have a worker file copied into the output directory. Unfortunately, this would then include the worker as a third party library. This is really not what I wanted!

I managed to work around this by using

@JsModule("src/worker/WitchWorker.worker")
external val workerLocation: dynamic

Since the worker is expecting javascript, it doesn’t need the js extension; so I’ve tricked the build system into thinking this is a media file, where it’s actually a javascript file. This does mean it’s put in the wrong place in the output, but I can deal with that for now. Perhaps with a bit more understanding of the webpack system I can make it do what I want rather properly.

Next Steps

I’ve got to a stage now where I can use Kotlin and React in the same project, so hopefully this will make things a bit easier when it comes to writing the UI. I have’t yet got back to the same place I was before, though, as I don’t have a properly updating interface – I hacked together using the default tutorial ticker something that shows the current state tick count, so I can see things are happening.

The next step is to work out how React works properly and show the values from my state objects correctly, hopefully getting to a point where I can write a nice interface without too much hassle, and I can get back to the far more interesting job of actually writing things rather than fighting the build tools!


Leave a Reply

Your email address will not be published. Required fields are marked *