Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lazy loading JavaScript and Inline JavaScript

I noticed in the <head> of my site (for work), there are a lot of <link rel="stylesheet" type="text/css" href="" /> and <script type="text/javascript" src=""> tags. There are even more JavaScript/CSS files that are only loaded for specific pages (we're using CodeIgniter, and the file paths are passed to the header view).

I was considering using a conditional/asynchronous loader (eg. yepnope.js, head.js, etc.), but I noticed a small problem with doing this.

In our views, there is inline JavaScript, some uses $(function(){}) some uses $(document).ready(function(){}), and some just has code (using jQuery) that's not in a ready block.

Without editing EVERY view file to wrap its code in a function and calling that when the JS files are loaded, is there a way to delay the inline code until the JavaScript is asynchronously loaded?

like image 725
Rocket Hazmat Avatar asked Jan 20 '12 19:01

Rocket Hazmat


2 Answers

You can actually lazyload inline javascript: 1- Change the type parameter in the inline script to: text/delayscript

FROM

    <!– Inline Script –>
<script type="text/javascript" language="javaScript">
             /* Code */
</script>

To

    <!– Inline Script –>
<script type="text/delayscript">
             /* Code */
</script>

Giving the script tag a custom Mime type text/delayscript forces the browser to ignore its content (Please note that leaving it out entirely will default to text/javascript).

2- Lazy load all inline scripts Once heads.js (Or an other framework you might be using) confirms that it lazy loaded all your external JS, you can then grab the content of all your custom script tags and inject them in the page:

<script>
head.ready(function() {
    var 
        _head = document.getElementsByTagName("head")[0],
        _script = document.createElement('script'),
        _scripts = document.getElementsByTagName("script"),
        _txt = "text/delayscript",
        _contents = []
    ;

    for(var i=0,l=_scripts.length;i<l;i++){
        var _type = _scripts[i].getAttribute("type");
            if(_type && _type.toLowerCase() ==_txt)
                _contents.push(_scripts[i].innerHTML)
    }


    _script.type = 'text/javascript';
    _script.innerHTML = _contents.join(" ");
    _head.appendChild(_script);

});

To be even more graceful, you can actually keep the inline scripts in their original hierarchy in the DOM tree instead of jamming all their content in one script, as I have suggested above, by replacing the marked inline script tag by a new one that has mime type text/javascript:

head.ready(function() {
var 
    _scripts = document.getElementsByTagName("script"),
    _doc = document,
    _txt = "text/delayscript"
;

for(var i=0,l=_scripts.length;i<l;i++){
    var _type = _scripts[i].getAttribute("type");
        if(_type && _type.toLowerCase() ==_txt)
            _scripts[i].parentNode.replaceChild((function(sB){
                var _s = _doc.createElement('script');
                _s.type = 'text/javascript';
                _s.innerHTML = sB.innerHTML;

                return _s;
            })(_scripts[i]), _scripts[i]);
}
});
like image 162
YoussefTaghlabi Avatar answered Sep 29 '22 04:09

YoussefTaghlabi


You have to consider moving inline code "outside" and include it with

<script defer="defer" type="text/javascript" src="">
like image 34
Salaros Avatar answered Sep 29 '22 05:09

Salaros