Scala.js workshop at flatMap(Oslo) 2017
Scala Shell
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.
Slides lightning talk.key
Slides lightning talk.pdf

Scala.js workshop at flatMap(Oslo) 2017

Join the chat at


git clone
cd scalajs-workshop

Application served at http://localhost:8080 Look at Suggestions at the bottom


This project consists of a simple file browser that uses Akka Http on the backend, and Scala.js with Bootstrap for the frontend code.

Furthermore, we use the «Li Haoyi stack» for type-safe Ajax calls (Autowire), html templating (ScalaTags), json serialization (uPickle) and testing (uTest).

These are all examples of good micro-libraries that are cross-compiled for Scala.js

We also use typed wrappers for javascript APIs, notably Scala.js DOM


We bundle the sbt-extras launcher for sbt in the project, so you can start it by simply running:

bash> ./sbt

Compiling Scala.js

The Scala.js compiler has two modes:

  • fastOptJS generates unoptimized javascript. Since it is by far the fastest mode, we will use this for development
  • fullOptJS also pipes the resulting javascript through the Google Closure compiler which does heavy DCE (Dead Code Elimination), among other optimizations. This is slower, but output file size drops from several megabytes to hundreds of kilobytes.

Usage is just running either of those commands:

sbt> fastOptJS
sbt> fullOptJS

Resulting files

bash> ls js/target/scala-2.11/
1.3M scala-js-workshop-fastopt.js     <-- Result of fastOptJS
436K <-- Source map for fastOptJS
309K scala-js-workshop-jsdeps.js      <-- Javascript dependencies concatenated by sbt
278K scala-js-workshop-jsdeps.min.js  <-- Minified Javascript dependencies concatenated bt
126B scala-js-workshop-launcher.js    <-- Generated script that runs main()
277K scala-js-workshop-opt.js         <-- Result of fullOptJS
920K     <-- Source map for fullOptJS

Rapid development

Since the project both has client and server code, we use two sbt plugins to automatically reload browser and restart server when necessary.

For the backend we use sbt-revolver. Usage is very simple:

# start server
sbt> tutorialJVM/re-start

# restart server
sbt> tutorialJVM/re-start

# stop server
sbt> tutorialJVM/re-stop

# status
sbt> re-status

# continuously restart server on changed code
sbt> ~tutorialJVM/restart

# alias
sbt> devBack

For the frontend we use workbench. This works by redirecting messages from sbt to the browser so you can see the project (not) compile, and automatically have the browser window reloaded on successful compilation.

Usage is again very simple:

sbt> ~;tutorialJS/fastOptJS;tutorialJS/refreshBrowsers

# alias
sbt> devFront

If you make changes both on client and server side, this snippet should do it:

sbt> ~;tutorialJVM/re-start;tutorialJS/fastOptJS;tutorialJS/refreshBrowsers

# alias
sbt> dev

Note that there is no synchronization between the two restarts, so it's possible that the client will reload just as the server is restarting. In that case, simply reload the browser.


Test code is transpiled and then executed on Node.js, which you need to install on your system if you want to run tests.

Additionally, it is recommended to install jsdom and source-map-support for a fake DOM and source map-support.

Just run yarn install / npm install in this folder.


The workshop is very much open ended, these are some suggestions for things that could be fun to play with:

  • Try to break it! The compiler generally has your back, and a lot of the pain points from traditional web development are gone, though some remain. By refactoring the application you can get a feeling for what is still brittle

  • Extend the application to show metadata. Last changed? file size? Right now it's pretty bare bones

  • Add support for showing content of files. Such basic functionality missing!. Can you make it happen?

  • Add support for several file browsers in tabs on the same page. Bootstrap has tabs, and the file browser just needs a DOM element to render to)

  • Add support for remembering state. The Local Storage API is defined in dom.localStorage. You probably want to use uPickle for serialization

  • Breadcrumbs for the parent folders instead of the back button.



  • Li Haoyi - «Scala.js - Safety & Sanity in the wild west of the web» Video Slides

  • Otto Chrons - «Scala.js: Next generation front end development in Scala» Video Slides

Further reading