Modular JavaScript through RequireJS

The simplest way of injecting JavaScript libraries into the namespace is to add them to the HTML framework via <script>...</script> tags in the HTML header. For instance, to add JQuery, we would add the following line to the head of the document:

<script [email protected]("lib/jquery/jquery.js") type="text/javascript"></script>

While this works, it does not scale well to large applications, since every library gets imported into the global namespace. Modern client-side JavaScript frameworks such as AngularJS provide an alternative way of defining and loading modules that preserve encapsulation.

We will use RequireJS. In a nutshell, RequireJS lets us encapsulate JavaScript modules through functions. For instance, if we wanted to write a module example that contains a function for hiding a div, we would define the module as follows:

// example.js
define(["jquery", "underscore"], function($, _) {

  // hide a div
  function hide(div_name) {
    $(div_name).hide() ;
  }

  // what the module exports.
  return { "hide": hide }

}) ;

We encapsulate our module as a callback in a function called define. The define function takes two arguments: a list of dependencies, and a function definition. The define function binds the dependencies to the arguments list of the callback: in this case, functions in JQuery will be bound to $ and functions in Underscore will be bound to _. This creates a module which exposes whatever the callback function returns. In this case, we export the hide function, binding it to the name "hide". Our example module thus exposes the hide function.

To load this module, we pass it as a dependency to the module in which we want to use it:

define(["example"], function(example) {

  function hide_all() {
    example.hide("#top") ;
    example.hide("#bottom") ;
  }

  return { "hide_all": hide_all } ;
});

Notice how the functions in example are encapsulated, rather than existing in the global namespace. We call them through example.<function-name>. Furthermore, any functions or variables defined internally to the example module remain private.

Sometimes, we want JavaScript code to exist outside of modules. This is often the case for the script that bootstraps the application. For these, replace define with require:

require(["jquery", "example"], function($, example) {
  $(document).ready(function() {
    example.hide("#header") ;
  });
}) ;

Now that we have an overview of RequireJS, how do we use it in the Play framework? The first step is to add the dependency on the RequireJS web jar, which we have done. The Play framework also adds a RequireJS SBT plugin (https://github.com/sbt/sbt-rjs), which should be installed by default if you used the play-scala activator. If this is missing, it can be added with the following line in plugins.sbt:

// project/plugins.sbt

addSbtPlugin("com.typesafe.sbt" % "sbt-rjs" % "1.0.7")

We also need to add the plugin to the list of stages. This allows the plugin to manipulate the JavaScript assets when packaging the application as a jar. Add the following line to build.sbt:

pipelineStages := Seq(rjs)

You will need to restart the activator for the changes to take effect.

We are now ready to use RequireJS in our application. We can use it by adding the following line in the head section of our view:

// index.scala.html

<html>
  <head>
...

    <script
      type="text/javascript"
      [email protected]("lib/requirejs/require.js").url
      [email protected]("javascripts/main.js").url>
    </script>

  </head>
...
</html>

When the view is compiled, this is resolved to tags like:

<script type="text/javascript" 
  data-main="/assets/javascripts/main.js" 
  src="/assets/lib/requirejs/require.min.js">
</script>

The argument passed to data-main is the entry point for our application. When RequireJS loads, it will execute main.js. That script must therefore bootstrap our application. In particular, it should contain a configuration object for RequireJS, to make it aware of where all the libraries are.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset