As https://github.com/antonkulaga/threejs-facade is heavily outdated I tried an approach like: https://github.com/Katrix-/threejs-facade and would like to create a facade for the new three.js library.
I am by no means a JS expert, nor am I a Scala.js expert, so odds are I am doing something really dumb.
After another question I am using this sbt-scalajs-bundler and sbt-web-scalajs-bundler
My build.sbt looks like this:
lazy val client = (project in file("modules/client"))
.enablePlugins(ScalaJSBundlerPlugin, ScalaJSWeb) // ScalaJSBundlerPlugin automatically enables ScalaJSPlugin
.settings(generalSettings: _*)
.settings(
name := "client"
//, scalaJSModuleKind := ModuleKind.CommonJSModule // ScalaJSBundlerPlugin implicitly sets moduleKind to CommonJSModule enables ScalaJSPlugin
,jsDependencies += ProvidedJS / "three.min.js"
)
lazy val server = (project in file("modules/server"))
.enablePlugins(PlayScala, WebScalaJSBundlerPlugin)
.settings(generalSettings: _*)
.settings(
name := "server"
,scalaJSProjects := Seq(client)
,pipelineStages in Assets := Seq(scalaJSPipeline)
//,pipelineStages := Seq(digest, gzip)
,compile in Compile := ((compile in Compile) dependsOn scalaJSPipeline).value
)
three.min.js is in the resources-folder of my client project.
One part of the Facade is e.g.
@js.native
@JSImport("THREE", "Scene")
class Scene extends Object3D {
and I want to use it like this: val scene = new Scene. On scala.js side this actually compiles just fine, but when I run it I get:
Error: Cannot find module "THREE"
in the browser and I wonder why. It's called like this in three.min.js after all.
Now I tried providing and serving the three.min.js file from the server side as well, because I thought that maybe it was just missing at runtime, but no, that does not seem to be the cause.
So now I wonder what am I doing wrong here?
Just to clarify: Rest of transpiled js works just fine, if I do not export any usage of the Facade!
As explained in this part of Scala.js documentation,
@JSImportis interpreted by the compiler as a JavaScript module import.When you use the
CommonJSModulemodule kind (which is the case when you enable theScalaJSBundlerPlugin), this import is translated into the following CommonJS import:This annotation only tells how your Scala code will be interfaced with the JS world, but it tells nothing about how to resolve the dependency that provides the
THREEmodule.With scalajs-bundler you can define how to resolve JS dependencies from the NPM registry by adding the following setting to your
clientproject:(And note that you can’t use
jsDependenciesto resolve these modules with@JSImport)Also, note that the correct CommonJS import to use three.js is
"three"instead of"THREE", so your@JSImportannotation should look like the following:Alternatively, if you don’t want to resolve your dependencies from the NPM registry, you can supply your CommonJS module as a resource file. Just put it under the
src/main/resources/Scene.jsand refer to it in the@JSImportas follows:You can see a working example here.