Documentation for a historical release of Infusion: 1.3
Please view the Infusion Documentation site for the latest documentation.
If you're looking for Fluid Project coordination, design, communication, etc, try the Fluid Project Wiki.

The Challenge of Versioning in JavaScript

There's no formal mechanism for handling multiple versions of a library in JavaScript. In a portlet or mashup-based environment, where independent units of JavaScript coexist within the same document and namespace, it's especially important to shield against conflicting versions of a particular dependency. For example, if Portlet A requires the presence of Fluid 1.0 and and Portlet B expects Fluid 2.0, how do they express this dependency? Since they share the same namespace, how do we avoid conflicts between the two versions?

Ideas for Supporting Multiple Versions of the Fluid Framework

The fundamental challenge is the fact that all JavaScript code shares a single namespace. Good coding practice suggests treading lightly on the global namespace, so the Fluid framework currently declares a single variable, fluid. All other functions and objects are enclosed within this variable. Here's how it's currently done:

var fluid = fluid || {}; // Assign the fluid variable to itself it has already been defined, or assign it to a new empty object if not.

If we want to allow multiple versions of Fluid to coexist simultaneously, we have to ensure that our presence in the global namespace is itself versioned:

var fluid_01 = function () {
  // All of Fluid's code.
} ();

There are two interesting things going on in this example. Notice that we've created an anonymous function and we call it immediately, assigning its return value to the fluid_01 variable. In contrast to the previous example, wrapping our code in a closure provides a place for private code to live. Also, by explicitly including a version number in the fluid_01 variable, our presence in the global namespace is fully unique, even from future releases of the framework.

On the other hand, it would be highly inconvenient for client code to constantly use the fluid_01 name to reference Fluid objects and functions. In such a case, upgrading to a new version would require a tedious search-and-replace process. So, we need a better way to refer to Fluid without referencing the version number every time. Inspired by the typical pattern for a jQuery plugin, here's how a client could do this:

var myCodeThatUsesFluid = function (fluid) {
  var reorderer = new fluid.Reorderer ();
  fluid.showDogsAndPonies ();
} (fluid_01);

Notice that in this case, we've also defined all of our code inside an anonymous function to shield it from the rest of the world. But this time, we're taking a single argument, called fluid as a parameter to the function. This variable has function-level scope, and is invisible to the global namespace. Notice that we're also calling this function immediately, passing it a reference to fluid_01. So we've mapped the private fluid variable to a particular version of the Fluid library. This way, we can conveniently refer to any Fluid-related functions or objects with the unversioned variable, but it won't conflict with another piece of JavaScript that similarly encloses a private fluid variable. As a result, you could have two separate components that link against separate versions of the Fluid framework:

var myOldComponent = function (fluid) {
 var reorderer = new fluid.Reorderer (); // Do something that requires Fluid 0.1
} (fluid_01);

var myNewShinyComponent = function (fluid) {
 var superReorderer = new fluid.Reorderer ();
 superReorderer.invokeAwesomeTimeMachineOnlyAvailableInFluidVersion08 ();
} (fluid_08);

Sample Code and Unit Tests

I've put together a quick example of this approach to handling multiple versions, along with jsUnit tests that show its success. Feel free to take a look and share your thoughts.

  • No labels