-
Notifications
You must be signed in to change notification settings - Fork 320
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added support for Scala JS for the main scripts #930
Conversation
- 80:4000 | ||
command: jekyll serve --incremental |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm assuming that docker-compose is only used for development, but if this isn't the case I could be breaking things here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
correct it's optional dev-only stuff
/** | ||
* A basic logger for the debugging console | ||
*/ | ||
object Logger { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I browsed around for a few scala js logging implementation but didn't find one that fit my needs. I'm open to swapping this out for a different project vs my home-built solution
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps you could put a comment to that effect at the top of the file, and say briefly what the considerations were
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have two actual uses of this logger. I suggest replacing them by a good old println
.
@@ -1,6 +1,3 @@ | |||
--- | |||
--- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this isn't needed after #924
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My familiarity with Scala.js and front-end stuff in general is limited, but:
Cool! I like it and I lean towards accepting this (once complete). I think being used on scala-lang.org is good bragging rights for Scala.js.
My sense is that is that if we end up having Scala.js-related trouble there will be no shortage of volunteers wanting to help out. And yeah it makes the build more complicated, but I doubt that will affect anyone doing ordinary work on the site.
Interested in hearing other opinions on this. (@heathermiller? @sjrd?)
- 80:4000 | ||
command: jekyll serve --incremental |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
correct it's optional dev-only stuff
/** | ||
* A basic logger for the debugging console | ||
*/ | ||
object Logger { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps you could put a comment to that effect at the top of the file, and say briefly what the considerations were
I am skeptical. Even https://www.scala-js.org/ does not use any Scala.js code, and for one good reason: it is a mostly static website, with a couple scripts for isolated functions on the site. Most of the code consists in external libraries. The same applies to scala-lang.org. Scala.js does not shine on small scripts. You will bloat the download times because the Scala.js code size "tax" will be much larger than the features you are implementing---unlike in larger applications, where Scala.js is appropriate because the tax is dwarfed by the actual codebase of the website. Just look at the PR stats: +441 for -91. If you're increasing the codebase size by porting to Scala.js, you're likely doing yourself a disservice. One would say that most of it is about build scripts, and that is true. But let us also look at the features themselves. For example, this PR replaces the JavaScript code: // OS detection
function getOS() {
var osname = "linux";
if (navigator.appVersion.indexOf("Win") != -1) osname = "windows";
if (navigator.appVersion.indexOf("Mac") != -1) osname = "osx";
if (navigator.appVersion.indexOf("Linux") != -1) osname = "linux";
if (navigator.appVersion.indexOf("X11") != -1) osname = "unix";
return osname;
}
$(document).ready(function() {
if ($(".main-download").length) {
var os = getOS();
var intelliJlink = $("#intellij-" + os).text();
var sbtLink = $("#sbt-" + os).text();
var stepOneContent = $("#stepOne-" + os).html()
$("#download-intellij-link").attr("href", intelliJlink);
$("#download-sbt-link").attr("href", sbtLink);
$("#download-step-one").html(stepOneContent);
}
}); by a complex abstraction for the OS in addition to the following Scala.js code: private def setupMainDownload(): Unit = JsUtils.findElement(".main-download").foreach(_ => {
val osLabel: String = OS().label
val intelliJlink: String = $("#intellij-" + osLabel).text()
val sbtLink: String = $("#sbt-" + osLabel).text()
val stepOneContent: String = $("#stepOne-" + osLabel).html()
$("#download-intellij-link").attr("href", intelliJlink)
$("#download-sbt-link").attr("href", sbtLink)
$("#download-step-one").html(stepOneContent)
}) What have we gained? Virtually nothing. Just a little bit of type-safety, which TypeScript would have also been able to provide, without the Scala.js bloat. I think the PR was a worthwhile experiment, if only to demonstrate that Scala.js is not the best option for this specific job. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here are a couple suggestions for improvements, in case you decide to go through with this.
|
||
// move our output folder to static | ||
artifactPath in(Compile, fastOptJS) := baseDirectory.value / ".." / ".." / "resources" / "js" / s"scala-${name.value}.js" | ||
artifactPath in(Compile, fullOptJS) := baseDirectory.value / ".." / ".." / "resources" / "js" / s"scala-${name.value}.js" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't configure fastOptJS
and fullOptJS
to produce the same target file. It will confuse caches (fullOptJS
after fastOptJS
will not recreate the file, for example).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh good to know. What's the recommended way to setup a build like this? (Where I'd like my html file to be static and to just import the compiled output regardless of compilation target)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure. I think it depends on the web server and/or templating mechanisms that one use. The folks at https://gitter.im/scala-js/scala-js or https://stackoverflow.com/questions/tagged/scala.js might have more experience with that than I do.
js-src/functions/build.sbt
Outdated
@@ -0,0 +1,18 @@ | |||
import org.scalajs.core.tools.linker.backend.OutputMode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This import is unused.
js-src/functions/build.sbt
Outdated
// move our output folder to static | ||
artifactPath in(Compile, fastOptJS) := baseDirectory.value / ".." / ".." / "resources" / "js" / s"scala-${name.value}.js" | ||
artifactPath in(Compile, fullOptJS) := baseDirectory.value / ".." / ".." / "resources" / "js" / s"scala-${name.value}.js" | ||
scalaJSOptimizerOptions in (Compile, fullOptJS) ~= { _.withUseClosureCompiler(true) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This setting is redundant, as it is the default.
js-src/functions/build.sbt
Outdated
scalaJSOptimizerOptions in (Compile, fullOptJS) ~= { _.withUseClosureCompiler(true) } | ||
|
||
scalaJSUseMainModuleInitializer := true | ||
emitSourceMaps := false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer the more future-proof
scalaJSLinkerConfig ~= { _.withSourceMap(false) }
/** | ||
* A basic logger for the debugging console | ||
*/ | ||
object Logger { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have two actual uses of this logger. I suggest replacing them by a good old println
.
else { | ||
last | ||
} | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More simply:
val os = Array(Windows, Mac, Linux, Unix)
.find(os => appVersion.contains(os.navigator))
.getOrElse(default)
*/ | ||
sealed trait OS { | ||
val navigator: String | ||
val label: String |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In order to cut down on the boilerplate, consider declaring OS
as
sealed abstract class OS(val navigator: String, val label: String)
so that the instances are one-liners:
case object Windows extends OS("Win", "Windows")
Thanks for the feedback and detailed comments @SethTisue and @sjrd 😄 While this was a fun exercise I'm inclined to agree with @sjrd's analysis: we're better off sticking with vanilla JS. I'm closing out this PR but I've updated my code with the feedback so if we ever decide Scala.js makes sense we'll know where to find it. |
Thanks for your work Dylan 👍 Just in case you're thinking of playing around with Scala.js more, you can have a look at scala/docs.scala-lang#1107. |
Not Ready To Merge
This is a partial implementation of using Scala JS for our site's scripts instead of Vanilla JS.
I'm opening this pull request mainly to get feedback on the direction and to see if it's worth completing. I'm totally fine with tossing this code if we don't think it makes sense for the project.
Should we actually do this?
This is a large change with multiple moving pieces. Should we really be changing something that isn't broken?
Other Concerns
Missing Pieces
a.
sbt fullOptJS
I'm using the closure compiler to minify the output but we can turn that off to make prod debugging easierAnyway let me know if I should continue and if there is any feedback on my implementation.