Require once - Guarding Javascript against multiple inclusion

Under certain circumstances, it can happen that a page loads a static resource more than once. Most of the time this will lead to desastrous results, as objects already known inside the page are replaced by freshly created ones, destroying a great deal of state. Consider the following situation

<html>
 <head>
  <script type="javascript" src="/toscawidgets/tw.jquery/static/jquery.js"/>
  <script type="javascript" src="/toscawidgets/tw.jquery/static/cool_plugin.js"/>
 </head>
 <body>
   <div id="replace_me"/>
 </body>
</html>

Now let’s assume we render a snippet of HTML through an AJAX-call that replaces the #replace_me-element, which looks like this

<div id="#replace_me">
  <script type="javascript" src="/toscawidgets/tw.jquery/static/jquery.js"/>
  <script type="javascript" src="/toscawidgets/tw.jquery/static/other_cool_plugin.js"/>
  <span>Super!</span>
</div>

Because of the second inclusion of the jquery-library, the functionality of cool_plugin.js from the inital page-load is gone!

To prevent this, ToscaWidgets has grown a feature (Since version 0.9.8) that prevents this from happening. It’s called require once and is globally activated through the configuration option toscawidgets.middleware.require_once. See :doc:`configuration` on how to enable it.

If this option is set to True, all static javascript is surrounded automatically by guarding-statements that look like this:

if(typeof(tw_jquery_static_jquery_js) === "undefined") {
     // - the actual static file content
     tw_jquery_static_jquery_js = true;
}

This will make sure that additional includes won’t be re-defining objects.

Turning require once on on individual resources

Since the introduction of require once, it is also possible to define for a given resource individually if it is supposed to be guarded against multiple inclusion. This can be done through setting tw.api.JSLink.require_once to either True or False.

All JSLink-instances that don’t explictly define it are bound to the globally configured behavior.

Gotchas when using require once

There are two known gotchas when using require once:

  • Some static javascript might rely on side-effects when being included. For example, there are jquery-plugins that look like this

    (function($) {
      // define the plugin
    })(jQuery);
    // automatically do stuff for specific elements
    $(document).ready(function() {
       $("#some_class").do_something();
    }
    

    So what happens is that the plugin is not only declared, but also automatically performs some initialization on certain elements after being loaded.

    This won’t work of course after being guarded through require once! The solution is simple though: simply render the code yourself using JSSource yourself. This has the additional benefit of being finer granulated, e.g. only attaching events to the replaced parts of the page.

  • The tw.api.JSLink.require_once attribute is only effective if ToscaWidget itself serves the static resources. It’s implemented via passing an extra parameter to the GET-request.

    When serving the static resources through e.g. apache, you can only chose to either serve all or none of them with guarding statements.