The Client

As is typical for SPAs the client consists of a single HTML file and a number of supporting resources (JS and CSS). One of these resources is the actual JavaScript code generated by Scala.js from the Scala sources. The HTML is defined under the server project in twirl/views/index.scala.html using Play template system. Here you'll find the usual HTML things like links to CSS and JS files. As you can see, the <body> element is pretty empty, because all the HTML will be generated by the application itself. The @scalajs directive tells the ScalaJSWeb plugin to insert relevant <script> tags to load the generated JavaScript code and its dependencies. For your convenience, the _asset function prefixes your assets (css, js, images) with a CDN link of your choice defined in server/src/main/resources/application.conf. Note that the line with "${?APPLICATION_CDN}" is one way to override default values in production with environment variables if they are defined. The _asset function also adds a version to the file name automatically converting main.min.css to main-<version>.min.css in production which clears client proxy and browser cache when you make changes to the file. See PlayFramework Fingerprinting for more information about this best practice.

<body>
    <div id="root">
    </div>
    @scalajs.html.scripts(projectName = "client", name => _asset(name).toString, name => getClass.getResource(s"/public/$name") != null)
</body>
</html>

Instead of using external JavaScript references to React, jQuery, Bootstrap and to a chart component, the build system combines all these into a single JavaScript file (client-jsdeps.js). See here for details. The last JavaScript reference is the compiled application code.

Once the browser has loaded all the resources, it will call the SPAMain().main() method defined in the SPAMain.scala singleton class. This is the entry point of the application. The class itself is very simple,

@JSExport("SPAMain")
object SPAMain extends JSApp {
  @JSExport
  def main(): Unit = {
    // create stylesheet
    GlobalStyles.addToDocument()
    // create the router
    val router = Router(BaseUrl.until_#, routerConfig)
    // tell React to render the router in the document body
    React.render(router(), dom.document.getElementById("root"))
  }
}

The externally accessible classes and functions are annotated with @JSExport so the Scala.js compiler knows not to optimize them away and make them available with those exact names in the global scope.

What main() does is simply to create a router and instruct React to render it inside the document <div id="root"> tag.

Now at this point you've seen couple of references to React and might wonder what's it about. React is a JavaScript library for building user interfaces, developed by Facebook. You might ask "why use a JavaScript library with Scala.js if Scala is so great" and yes, it might make sense to do a similar library in Scala.js but since it's already there, why not use it. And to sweeten the deal there is a very nice wrapper for React called scalajs-react by David Barri (@japgolly).

There are also other Scala.js libraries available for building SPAs but I wanted to go with React, so that's what we'll use in this tutorial :)

results matching ""

    No results matching ""