scalascala.jssbt-web

How can scala-js integrate with sbt-web?


I would like to use scala-js with sbt-web in such a way that it can be compiled to produce javascript assets that are added to the asset pipeline (e.g. gzip, digest). I am aware of lihaoyi's workbench project but I do not believe this affects the asset pipeline. How can these two projects be integrated as an sbt-web plugin?


Solution

  • Scala-js produces js files from Scala files. The sbt-web documentation calls this a Source file task.

    The result would look something like this:

    val compileWithScalaJs = taskKey[Seq[File]]("Compiles with Scala js")
    
    compileWithScalaJs := {
      // call the correct compilation function / task on the Scala.js project
      // copy the resulting javascript files to webTarget.value / "scalajs-plugin"
      // return a list of those files
    }
    
    sourceGenerators in Assets <+= compileWithScalaJs
    

    Edit

    To create a plugin involves a bit more work. Scala.js is not yet an AutoPlugin, so you might have some problems with dependencies.

    The first part is that you add the Scala.js library as a dependency to your plugin. You can do that by using code like this:

    libraryDependencies += Defaults.sbtPluginExtra(
      "org.scala-lang.modules.scalajs" % "scalajs-sbt-plugin" % "0.5.5", 
      (sbtBinaryVersion in update).value, 
      (scalaBinaryVersion in update).value
    )
    

    Your plugin would look something like this:

    object MyScalaJsPlugin extends AutoPlugin {
      /* 
        Other settings like autoImport and requires (for the sbt web dependency), 
        see the link above for more information
      */
    
      def projectSettings = scalaJSSettings ++ Seq(
        // here you add the sourceGenerators in Assets implementation
        // these settings are scoped to the project, which allows you access 
        // to directories in the project as well
      )
    }
    

    Then in a project that uses this plugin you can do:

    lazy val root = project.in( file(".") ).enablePlugins(MyScalaJsPlugin)