Skip to content

Instantly share code, notes, and snippets.

@japgolly
Last active October 1, 2019 12:22

Revisions

  1. japgolly revised this gist Oct 1, 2019. 1 changed file with 20 additions and 0 deletions.
    20 changes: 20 additions & 0 deletions dev-prod-settings.sbt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,20 @@
    // SBT doesn't have a standard concept of dev/prod builds so however you decide to
    // specify that, you can use settings similar to below.
    // The `scalaJSLinkedFile in Compile` setting referenced in the snippet above will
    // choose fast/full opt via the `scalaJSStage` below.

    def jsDevSettings: Project => Project =
    _.settings(emitSourceMaps := true)

    def jsProdSettings: Project => Project =
    _.settings(
    emitSourceMaps := false,
    scalaJSStage := FullOptStage,
    scalaJSSemantics in fullOptJS ~= (_
    .withProductionMode(true)
    .withRuntimeClassNameMapper(Semantics.RuntimeClassNameMapper.discardAll())
    .withArrayIndexOutOfBounds(CheckedBehavior.Unchecked)
    .withAsInstanceOfs(CheckedBehavior.Unchecked)))
    scalaJSOptimizerOptions ~= (_
    .withBatchMode(true)
    .withCheckScalaJSIR(true)))
  2. japgolly created this gist Oct 1, 2019.
    44 changes: 44 additions & 0 deletions copy.sbt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,44 @@
    // Assumptions:
    // 1. You have one or more Scala.JS modules named jsModule1, jsModule2, ...
    // 2. You have a web-serving (or otherwise JVM) module that will serve the JS assets

    // The only "webby"/JS plugin I use apart from Scala.JS itself, is xsbt-web-plugin,
    // and even that, only on my pre-http4s projects.
    // xsbt-web-plugin allows me to quickly stop/start a servlet container from SBT.
    // The snippet below is for "webappPostProcess" which is an xsbt-web-plugin task but
    // if you aren't using it, you can just create a task with the same content and make
    // "package" depend on it.

    webappPostProcess := {
    implicit val log = streams.value.log
    val outputOfJsModule1 = (scalaJSLinkedFile in Compile in jsModule1).value
    val outputOfJsModule2 = (scalaJSLinkedFile in Compile in jsModule2).value
    // ...

    (target: File) => {

    // Copy Scala.JS assets
    def copyScalaJs(jsf: VirtualJSFile, to: String): Unit =
    jsf match {
    case f: FileVirtualJSFile => fileSync(f.file, target / to, mandatory = true)
    case other => sys.error("Unsupported virtual file type: " + other)
    }
    copyScalaJs(outputOfJsModule1, targetForJsModule1)
    copyScalaJs(outputOfJsModule2, targetForJsModule2)
    // ...

    // <copy other assets here too>
    }
    }

    // Little helper. Is it still needed in SBT 1.3.x? Who knows?? It was definately helpful in the 0.13.x days.
    def fileSync(from: File, to: File, mandatory: Boolean)(implicit log: Logger): Unit =
    if (from.exists()) {
    log.info(s"Copying $from$to")
    IO.copyFile(from, to, preserveLastModified = true)
    } else if (mandatory)
    sys.error("File not found: " + from.absolutePath)
    else if (to.exists()) {
    log.info(s"Deleting $to")
    IO.delete(to)
    }