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?
Instead of inline scripts, create inline functions. Then at the end of your javascript file, call the function if it exists.
Inside your concatenated jquery+etc async javascript file:
You'll have to do some shuffling to make sure you only have one inline_script per page, or use some kind of caching to put them together if you call it more than once.
It's still a fun problem in the current age even though this question is old, async scripts = pretty awesome
You have to consider moving inline code "outside" and include it with
You can actually lazyload inline javascript: 1- Change the type parameter in the inline script to: text/delayscript
FROM
To
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:
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:
HTML5 introduced a new
async
parameter for scripts having a definedsrc
.You can add it directly on any
<script>
element :BUT : keep in mind that it will not work on inline scripts!
And if your some of your pages mix either external and inline scripts, if you load the external asynchronously, it means that the inline scripts will actually be executed before the asynchronous ones... Which can have unwanted effects.
For instance, if you have the following configuration :
Depending on your setup, you might want to look into the service from www.cloudflare.com. Their current beta functionality called rocket loader, does exactly that, including the inline scripts.
It's a free service. try it out ;)
Plus you get a free caching proxy on top :)
First of all I would recommend you to analyse the loading of the scripts on the client side very carefully and not only for the first JavaScript loading, but on the loading of the same JavaScript files at the second time or its loading on another page. If the ETag are correctly set on the scripts by the web server or if you use other caching options of HTTP (see the caching tutorial for details) for the JavaScripts files than no loading of the files itself will take place and only the cache revalidation will be done. So it can be that the problem which you describes is not so important like it looks like.
If you do decide to load some scripts dynamically you can use jQuery.getScript and place all dependent code inside of the
success
callback. If you need to load one or two JavaScript files the way will work very good, but if you need to load a list of JavaScript files with more complex dependency the implementation could be not so easy. In the case you can usedocument.writeln
inside of<head>
. The usage of the method inside of<head>
has almost no disadvantages (see here for details).