So I already have twenty or so JavaScript files that I create from ScalaJs and that number is probably only going to increase. I originally had them as separate sub projects, but because in Sbt you can’t have sub-sub-projects this became unmanageable. So I now have a single JS sub project and manually add in an extra source directory and set the mainclass as in the example below.
set Compile/unmanagedSourceDirectories += (ThisBuild/baseDirectory).value / "EGrid/JsAppsSrc/EarthApp";
set Compile/mainClass:= Some("ostrat.pSJs.EarthAppJs")
The extra source directory only has as single file with a one line Main object, as Sbt doesn’t allow you to add individual source files. The problem is how do I automate building all the assets. Is there a better way to do this in SBT or should I use Mill or just automate the process via a batch file?
You can define a command that chains all the required sets and builds in sbt. Use an addCommandAlias to do that without fuss. For example as is done here:
I don’t think Mill will help you. You’ll have the same issue there, AFAICT.
The reason I didn’t just chain the setting changes is that
set Compile/unmanagedSourceDirectories += (ThisBuild/baseDirectory).value / "EGrid/JsAppsSrc/EarthApp"
mutates the build state, so each artifact would add another file. I guess in retrospect that shouldn’t effect the final artifacts as the optimiser will strip out unneeded classes, but still I thought the whole point of Sbt is that the build is functional and is normally not mutated after loading. So I decided to use custom configurations.
This does become rather verbose but does maintain the immutability of the build. I wasn’t aware of addCommandAlias. Thanks for the tip. However I presumed I couldn’t use it in this instance as I wanted to copy the files as well. So I just used an ordinary Task.
Depending on the use case, you might also want to consider emitting multiple ES modules from a single Scala.js project. Especially if all these projects actually have a lot of code in common, and only differ in their entry points. Emitting multiple modules, each with a different entry point, would then share the common code as common ES modules. Producing those files is also a lot faster, since it’s a single linker run.