Modular JavaScript for Portals Done Right
JavaScript has become more and more popular over the last few years, and without any doubt its usage continues to increase every day. A portal is an aggregation platform focusing on aggregating applications in the browser thanks to portlets or gadgets. This means it will also integrate JavaScript in the browser: each application comes with its own markup and JavaScript code, which more and more often is JavaScript.
GateIn 3.5 is a mature system and uses modular JavaScript integration capabilities providing key features for web applications. Let’s begin with a short introduction to JavaScript modules.
Modules
JavaScript will not have a native notion of modules until the forthcoming Ecmascript 6 version. Still modularity can be achieved easily in JavaScript; every good JavaScript book has a chapter on modules. GateIn 3.5 provides a simple module format adapted to the portal platform although it can also adapt to popular module formats. Independently of the format, modules follow the same pattern:
- A name or identifier
- A list of other modules it needs
- A JavaScript function that consumes dependencies and produce the module object itself
A module in GateIn is provided by a self-executing anonymous function that takes module arguments and returns a module. In this example we have three module definitions. The Customer and Order module definitions are functions, which return JavaScript objects that are the actual modules. The application module definition consumes both the Customer and Order modules as arguments of the function.
When GateIn loads a page containing our modules, the modules are connected to each other by the module system. How does GateIn knows how the modules should be connected? So far, we have just described the JavaScript part of our modules. We use a deployment descriptor named gatein-resources.xml to describe our modules:
<gatein-resources> <module> <name>customerModule</name> <script> <path>/customer.js</path> </script> </module> <module> <name>orderModule</name> <script> <path>/order.js</path> </script> </module> <module> <name>applicationModule</name> <script> <path>/application.js</path> </script> <depends> <module>customerModule</module> <depends> <depends> <module>orderModule</module> <depends> </module> </gatein-resources>
The resource descriptor file tells GateIn about our modules and how they are connected to each other. After this short introduction to modules, we will explain the benefits of modularity.
Benefits
Isolation
Without modules, JavaScript code uses the browser window object, which can create conflicts between objects. This can be controlled on a simple page. However, GateIn is a portal that aggregates applications at runtime on the same page: an application is never aware of the other JavaScript applications that may be on the same page.
Modularity is the silver bullet for solving this problem because it gives proper isolation between modules. In our example, the module system will inject the customer and order modules into the application module.
Furthermore several versions of the same library can be used at the same time. GateIn 3.5 is built with jQuery. Thanks to modules, you can use the jQuery of your choice without conflicting with GateIn’s jQuery.
Reusability
Modules are natural constructs for building modular applications. Common code can be extracted into a module, allowing the code to be reused.
Beyond reusing your own code, GateIn is able to integrate with existing module formats such as Asynchronous Module Definition or CommonJS: GateIn can leverage the large JavaScript ecosystem at a very small cost and the GateIn JS Cookbook page details a few of them.
Performance
Last but not least, modularity leads to excellent front-end performance because the loading of modules can be optimized by GateIn:
- Lazy loading: What is more efficient than not loading a resource? Modules can be lazy and loaded when required by a portlet or a portal at the most appropriate time instead of using page headers that block page rendering.
- Parallel loading: Modules that don’t depend on each other can be loaded at the same time.
- Load groups: Modularity leads to code fragmentation; however, this does not mean that GateIn will load a JavaScript resource per module. Each module can be assigned to a load-group, which bundles modules into a single JavaScript resource loaded by the browser.
The way
Early in 2012 we started to work on JavaScript with the main goal of improving the front-end performance of GateIn. It took the team three iterations, GateIn 3.3 and GateIn 3.4, before getting things right in GateIn 3.5.
In June 2012, the first milestone GateIn 3.3 was released based on the GateIn JavaScript Loader (an improvement over the GateIn 3.2 loader). Performance showed a significant improvement but there was no real notion of isolation and modules.
By that time we also identified that the Asynchronous Module Definition, best known as AMD, was a better choice and that it was the way to go so we decided to base GateIn JavaScript Modules on top of the RequireJS implementation. In September 2012 we released GateIn 3.4 with the revamped module system based on AMD.
We were really confident with AMD, yet something was itching: the module format was not natural. Indeed although we were using AMD, our module pattern (i.e. the way modules are written) was a legacy. So we made a few attempts to find the right module pattern to use and we found that the self-execution function was the best choice, since it is a simple and natural way to write JavaScript modules (it is the format used by jQuery plugins by the way).
Finally, GateIn 3.5 has just been released and ends the story nicely. It is a solid platform for delivering JavaScript applications with performance. In the next blog post, I will demonstrate to you the power of GateIn 3.5 JavaScript modules through the integration of the Backbone Todo MVC application in GateIn.