Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In a ScalaJs sbt build, is there any advantage to use webjars instead of npm or bower with 'Provided'?

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:

1. "Oh nos! fastOptJS failed because there was some random file that was also named the same as a dependency in the webjar!"

[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

2. I know what to do! I'll add a version to the defined js!

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"

3. "Oh no! fastOptJS failed!"

[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...

Question

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?

like image 374
tacos_tacos_tacos Avatar asked Apr 24 '16 15:04

tacos_tacos_tacos


2 Answers

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.

like image 67
sjrd Avatar answered Oct 08 '22 14:10

sjrd


The principal advantage to using web jars, in my opinion, is not having to use npm. Plus, they go through the usual maven resolution / download process, so while it isn't perfect, it's only one pipeline of breakage instead of two.

Regardless, they can be painful. I've got about 30 dependencies in my scala.js app, and they are mostly managed with web jars. I have found that, in general, I get better results using npm webjars vs. bower webjars, and it is folly to attempt to rely on web jar transitive dependencies.

My jsDependencies tend to look like this:

("org.webjars" % "morrisjs" % "0.5.1" intransitive ())
        / "morris.js"
        minified "morris.min.js"
        dependsOn "2.1.2/raphael.js",
("org.webjars" % "raphaeljs" % "2.1.2-1" intransitive ())
        / "2.1.2/raphael.js"
        minified "2.1.2/raphael-min.js"

The first thing to note is the version number mangled onto basically everything that ever gets depended on. If it gets used much, I extract the version out into a variable. The second thing is the intransitive() annotation. While I can sometimes get away without it, I find that being explicit keeps things working and my hair in place.

I tend to stick to front-end friendly packages like react and angular. Some of the new react libraries have dozens of transitive dependencies and attempting to use them would be painful. I avoid those =p

like image 20
easel Avatar answered Oct 08 '22 15:10

easel