Packaging HTML5HTML5 is powerful, expressive, and expansive. It does exactly what it was designed to do: describe the structure of web pages.
Loading external files is so commonplace, that you might be wondering why we’re talking about the different ways to load them. We don't dictate the way that our clients use our software. Some of our clients use Webpack, Browserify, or Gulp/Grunt, while many others simply include our files with old-fashioned <script> tags. We don’t want our clients to have to modify their workflow to accommodate our code, so we’re changing the way we package it. But why does this matter?
Moving Toward Modules
- Keep the global namespace clean.
- Make your code more readable.
- Encourage developers to write reusable code.
Chartn: an example module
To illustrate the benefits of the module pattern, let’s construct a fictional financial application called Chartn. Chartn is a technical analysis platform that competes with our retail financial application, Technician. It uses its own library, Chartn.js, to draw its charts and jQuery 1.11 to manage repetitive DOM manipulation tasks. Here’s an example of the core Chartn module:
This pattern is great—the global namespace remains clean, and we can import any dependency we need. However, this pattern limits the module to itself. There is no way for code in the global scope to access the Chartn object.
This problem of importing dependencies and exporting a useful object has been on the community’s mind for years. Several solutions exist, but until recently, TC39 (the committee that publishes the ECMAScript standard) had ignored the problem of module loading.
That changed with ES6’s import and export. Although these functions are now standard, they have only been implemented into Microsoft Edge. If you want to use import/export, but your user base doesn’t exclusively use Microsoft Edge, you’ll have to turn to popular transpilers, such as Babel or Traceur.
Until there is widespread adoption of native imports and exports, we have decided to support all three popular module loading implementations (RequireJS, CommonJS, and AMD). Thankfull, it’s just as easy to support all script loaders as it is to support one specific implementation. Thanks to a design pattern called Universal Module Definition (UMD), we can write code that will work with every module loader and maintains compatibility with <script> tags.
UMD is just the technical way of saying, “Figure out how your users want to load your module, then load it that way.” There is no magic to it. In fact, it builds upon the familiar module definition pattern that was discussed earlier.
Instead of passing outside global variables to the IIFE, the developer passes the definition of the module as a variable. Then, the program performs feature detection and exports your module (and its dependencies). Below is the fictional Chartn module wrapped in UMD boilerplate (if you’re a developer who wants to implement UMD, there are Gulp and Grunt tasks that will wrap your code in the necessary boilerplate).
That’s all there is to it. Chartn will now work in all of the most popular module loaders, along with run-of-the-mill <script> tags.
We believe that our software should be as agnostic as possible. It shouldn’t care about the way you load it. As long as it’s in a browser, it should work. Our next release will be packaged with UMD so that it will fit your workflow, whatever it may be.
You may also like to read The Bridge to HTML5 blog post series. This blog post series talks about how to use HTML5 containers, the many benefits of HTML5 within financial technology, and considerations UI/UX.