0

I have written this piece of JS and CSS loading code and I would like some advice on it. Anything some of the Javascript Gurus could possibly point out would be much appreciated. The code works, but I have not done extensive testing, because I am concerned about replacing functions in this manner.

A single javascript file containing JQuery as well as the below code will be included on all the pages. We write all the components in house and keep them very modular separated into their own folder with the corresponding JS and CSS. You can imagine starting to use for instance a dropown, dialog and a datepicker on one page would require us to add 6 includes and this quite frankly is annoying, because I want the dependencies to resolve automatically and using JSP includes could possibly make multiple calls to the same resources.

Below is the src to load a single datepicker lazily

;(function($){
    //All Lazily loaded components go here
    $.fn.datepicker = function(settings){
        console.log("This should only be displayed once");
        loadCSS("/res/component/datepicker/datepicker.css");
        var elem = this;
        return loadJS("/res/component/datepicker/datepicker.js", 
                    function(){return elem.datepicker(settings)});//After Load Completion the $.fn.datepicker is replaced
                                                                  //by the proper working implementation, execute it and return it so we maintain the chain
    };
}(jQuery));

function loadCSS(absoluteUrl){
    if(loadCSS[absoluteUrl])
        return;//Css already loaded

    $('<link>')
      .appendTo('head')
      .attr({type : 'text/css', rel : 'stylesheet'})
      .attr('href', absoluteUrl);//Appending entire element doesn't load in IE, but setting the href in this manner does

    loadCSS[absoluteUrl] = true;//Memoize
}

function loadJS(absoluteUrl, onComplete){
    if(loadJS[absoluteUrl])
        return;//Script already loaded

    loadJS[absoluteUrl] = true;//Memoize

    var result;
    jQuery.ajax({
        async : false,//Synchronized because we need to maintain the JQuery chain
         type :'GET',
          url : absoluteUrl,
     dataType :'script',
      success : function(){
                    result = onComplete();
                }
    });

    return result;
}
3
  • 1
    This question appears to be off-topic because it is better suited to codereview.stackexchange.com Commented Sep 12, 2014 at 13:12
  • Why exactly are you rolling your own? Because you didn't know something like RequireJS existed, or because you want to learn, or because all the existing solutions somehow are not good enough, ... ? I ask because I attempted to do the same ("to learn") yet I only really learned how to properly setup a modularized application when I started to use existing libraries (RequireJS, to be exact). Commented Sep 12, 2014 at 14:16
  • The reason I am rolling my own is because my needs are very specific, hence the code snippet supplied. It does exactly what I want it to do and it is very minimalistic. All the other points mentioned are mere benefits. Relying on someone else's code has almost always caused me more headaches than solving problems whether its a licensing issue or browser support issue I need to maintain the code. If it breaks I can fix it type of scenario. Commented Sep 12, 2014 at 14:47

1 Answer 1

1

Have you looked in to Require JS, it will send async requests for only the modules you need for a given module.

In addition, because dependencies are scoped to the callback function, namespaces clashing is less of an issue

Typically you would have:

require(["jquery", "foo", "bar"], function($, foo, bar){...});

which allows your code to remain modularized both server side, and client side, in separate locations.

Of course, you need to set up require on your server with a config (described in the webpage), and wrap your resources in define blocks:

define("foo", ["jquery"], function($){...});

The downside is performance on pages that require many modules. In this situation you benefit more from having all resources in combined files, but note that query strings will cause the browser not to cache files in any case.. which is also another performance consideration.

Hope that helps

ps. In terms of CSS lazy loading, you could always use javascript to inject link tags into the head adhoc, and provide some javascript interface functions that your other code can call in order to request a CSS dependency dynamically.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.