When I first discovered webJars a few months ago I was super-skeptical that it would be be a viable way means of handling client-side dependencies given the enormous complexity of some of these builds/buildsystems, and given the frequency that js
files are published. The second concern was of course not well-founded but I feel vindicated on the first after spending almost 36 hours now trying in vain to get about 10 scss/css/less
-type webJars and 8 JS webJars to live under one jsDependencies
roof.
What I found as that by the time you reach JS dependency 3, 4, or 5,you start getting into a ridiculous timekill loop:
[trace] Stack trace suppressed: run last client/compile:resolvedJSDependencies for the full output.
[error] (client/compile:resolvedJSDependencies) org.scalajs.core.tools.jsdep.JSLibResolveException: Some references to JS libraries could not be resolved:
[error] - Ambiguous reference to a JS library: bootstrap.min.js
[error] Possible paths found on the classpath:
[error] - META-INF/resources/webjars/bootstrap/3.3.6/js/bootstrap.min.js
[error] - META-INF/resources/webjars/bootstrap3-dialog/1.34.4/examples/assets/bootstrap/js/bootstrap.min.js
[error] originating from: client:compile, client:compile, client:compile, client:compile
[error] - Ambiguous reference to a JS library: bootstrap.js
[error] Possible paths found on the classpath:
[error] - META-INF/resources/webjars/bootstrap3-dialog/1.34.4/examples/assets/bootstrap/js/bootstrap.js
[error] - META-INF/resources/webjars/bootstrap/3.3.6/js/bootstrap.js
[error] originating from: client:compile, client:compile, client:compile, client:compile
lazy val webjarbs = "org.webjars" % "bootstrap" % version.bootstrap / s"${version.bootstrap}/bootstrap.js" minified s"${version.bootstrap}/bootstrap.min.js" dependsOn "jquery.js" commonJSName "bootstrap"
[trace] Stack trace suppressed: run last client/compile:resolvedJSDependencies for the full output.
[error] (client/compile:resolvedJSDependencies) org.scalajs.core.tools.jsdep.JSLibResolveException: Some references to JS libraries could not be resolved:
[error] - Missing JS library: 3.3.6/bootstrap.js
[error] originating from: client:compile, client:compile, client:compile, client:compile
[error] - Missing JS library: 3.3.6/bootstrap.min.js
[error] originating from: client:compile, client:compile, client:compile, client:compile
gg boys.
This goes over and over and around and around, and then I have to start doing
lazy val bs_sidebar = ( "org.webjars" % "bootstrap-sidebar" % version.bs_sidebar intransitive()) / "js/sidebar.js" dependsOn(s"bootstrap.js", s"bootstrap.min.js")
and now I'm not really even using the webjar, but it has a jsdependency named X and I cannot change that...
Hmmm? What if I just did what I used to do but build the dependencies without the app into some gigantic file, or set of files, and then feed that into the build? I have a proof of concept from online and I got it work (I think it was https://github.com/wav/material-ui-scalajs-react/blob/master/src/main/scala/wav/web/muiwrapper/package.scala ) which almost worked, and gave me the idea.
I know npm
works a lot better than sbt,
and I can still get it into my package... what's the downside, and am I missing something about sbt?
I agree with you. Once an application starts having non-trivial dependencies on JavaScript libraries, jsDependencies
does not scale. This is mostly because WebJars are missing critical features (just as transitive dependencies), but also because jsDependencies
was not a mechanism designed to scale.
As time passed, users have asked for more and more features of jsDependencies
, because they want to use it as their true app-scale (whatever that means) dependency mechanism. As a result, we've been patching more and more features/hacks on top of jsDependencies
. The result is not the prettiest thing in the world, and it definitely has shortcomings.
I would actually encourage using npm
to resolve your dependencies, especially if you are familiar with it and know how to integrate it into your workflow.