I am attempting to try speed up my web page by "Removing render-blocking JavaScript" using this defer method:
<script type="text/javascript">
function downloadJSAtOnload() {
var element = document.createElement("script");
element.src = "js/combination.js"; // replace defer.js with your script instead
document.body.appendChild(element);
}
if (window.addEventListener)
window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", downloadJSAtOnload);
else window.onload = downloadJSAtOnload;
</script>
I've combined all my javascript files into 1 called combinations.js but whenever I try combine this jquery library UI:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
with combinations.js, my jquery scripts don't work.
So Google Page speed is still saying that I need "Removing render-blocking JavaScript" for this library but how?
UPDATE:
When I add the Jquery UI Library to the top of my combination.js file and test it on CHROME and IE9 it works! The problem I now have above, is when I test it on Firefox (I've got version 35). So this seems to be a firefox issue
It looks like It was my history in firefox not re-loading my Jquery Library even when I did a full refresh (CRTL + F5). Strange, anyway if anyone happens to get this problem, delete all your history and load up your website up again. Amazing how such a simple solution can take up so much time.
Related
Hi there I have a wordpress site with and I have defered scripts setup per the GT Metrix recommendations. All scripts are defered except for Onesignal Push Notification plugin,
<script src="https://cdn.onesignal.com/sdks/OneSignalSDK.js" async></script>
function js_defer_attr($tag){
$scripts_to_exclude = array('.jsdelivr');
foreach($scripts_to_exclude as $exclude_script){
if(true == strpos($tag, $exclude_script ) )
return $tag;
}
return str_replace( ' src', ' defer="defer" onload src', $tag );
}
add_filter( 'script_loader_tag', 'js_defer_attr', 10 );
I am guessing it is adding script loading after page load/defering has been done?
Any help?
Cheers
I did it on my websites and it is working fine... and more important page stuff will load first. The user experience is better this way.
I will explain what I did.
I changed the OneSignal plugin code and moved to another file all that code it ads to the header. A file is created at runtime when it does not exists.
Let's suppose I create a new file called "onesignal_deferred.js".
Then I added to the footer of the page:
function add_script(url){
var element = document.createElement("script");
element.src = url;
document.body.appendChild(element);
}
function downloadJSAtOnload(){
add_script("add_script("https://<domain>/onesignal_deferred.js")
}
if (window.addEventListener)
window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", downloadJSAtOnload);
else window.onload = downloadJSAtOnload;
The manifest is not necessary as well... as it is suited for older versions of Chrome... so it is a new optimization you can do to save one more request per page view.
I can also use this same function "add_script" to defer other scripts like Google Analytics and any other.
p.s.: when you defer Google Analytics, sometimes it will not count as a view a page that is closed before the Load Event... in this case you might be tricked by a false Google Analytics report saying that pages as loading faster. The case is that too slow loading pages will not be counted on...as Google Analytic script will not even be loaded.
I've been looking around at JavaScript to try and get some code to load asynchronously
I found this code sample
<script type="text/javascript">
function downloadJSAtOnload() {
var element = document.createElement("script");
element.src = "defer.js";
document.body.appendChild(element);
}
if (window.addEventListener) {
window.addEventListener("load", downloadJSAtOnload, false);
}
else if (window.attachEvent) {
window.attachEvent("onload", downloadJSAtOnload);
}
else {
window.onload = downloadJSAtOnload;
}
</script>
from http://www.feedthebot.com/pagespeed/defer-loading-javascript.html
The thing is it doesn't quite do what I'm trying to achieve. I would like to be able to do something similar but setup a deferred or some type of function that is called after this has all loaded. Is that possible? If so can anyone help explain how?
You can try to use the onload event of the script tags you are loading. See this question, for example: Trying to fire the onload event on script tag. However, this mechanism seems pretty sketchy and may not be cross-browser.
Another possible approach is to have the script that is being loaded trigger an event that can be handled by the existing javascript on the page. This may or may not make sense for your particular case, and it requires you to have control over the loaded script.
Finally, these days it's rare for javascript loading to be a performance bottleneck for your website. So why are you trying to dynamically load javascript? Could you solve the same problem by loading some other resource, e.g. by doing an AJAX request?
You've tagged jQuery on your question. It has $.getScript() which does exactly what you're asking for in a purely cross browser fashion. It will load the script asynchronously and then call the specified callback when the script has finished loading and initializing:
$.getScript("defer.js", function() {
// script loaded here
// you can run code here that uses that script
});
If you really want to wait until the DOM is loaded before loading this script (generally not necessary), you could do this:
$(document).ready(function() {
$.getScript("defer.js", function() {
// script loaded here
// you can run code here that uses that script
});
});
Or, to wait until ALL other resources are loaded including images:
$(window).load(function() {
$.getScript("defer.js", function() {
// script loaded here
// you can run code here that uses that script
});
});
If you're interested in some references on when scripts are loaded (particularly with defer and async attributes, you can read this detailed post.
I have written a jQuery plugin, say jquery.plugin.js. I want to use this plugin on a large number of sites.
What I want to do is to write a piece of js code at the top of jquery.plugin.js which will load the jquery.main.js and execute it so that $ is available to be used in jquery.plugin.js.
Thanks.
What you probably want to do is create a new tag in js
script = document.createElement('script');
script.src = 'URL-TO-JQUERY';
And then append that element before the first tag.
document.body.insertBefore(document.getElementsByTagName('script')[0], script);
This will most probably work as the script is inserted before any other js. (except in the head)
Yes, just a interval that checks if jQuery exists:
interval = setInterval(check, 100);
function check(){
if($.version){
// Exec script
}
}
This page may be useful for you
http://code.google.com/p/jquery-ajaxq/
with this script you can use files sequentially
Works only if jQuery is loaded already,
$.when($.getScript("path_to_script")).then(function() {
alert("loaded");
})
Fiddle - http://jsfiddle.net/fLuDd/
Edit
var fileref = document.createElement('script')
fileref.setAttribute("type", "text/javascript")
fileref.setAttribute("src", 'http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js')
document.getElementsByTagName("head")[0].appendChild(fileref)
var t = setInterval(function() {
if (typeof(jQuery) == 'function') {
alert("jquery loaded");
clearInterval(t);
}
}, 2000);
Fiddle - http://jsfiddle.net/fLuDd/1/
Just include the jquery.main.js above the jquery.plugin.js. It should work if you place the script tags in this order.
<script src="jquery.main.js"></script>
<script src="jquery.plugin.js"></script>
If you do not have full control over the html or if jQuery might be loaded from other places also, do this to check if it is loaded or not, and load only if needed.
Load from google
if (typeof jQuery == 'undefined') {
document.write('<script type="text/javascript" src="http://www.google.com/jsapi"></script>');
document.write('<script type="text/javascript">');
google.load("jquery", "1.4.2");
document.write('</script>');
}
Load from same server
if (typeof jQuery == 'undefined') {
document.write('<script type="text/javascript" src="path/to/jquery.min.js"></script>');
}
There are some AMD packages that do what you want, like requirejs, but... you'll have to load them first!
You could use a polling technique (load jQuery dynamically and poll until $ exists), not very elegant or efficient.
You could also attach an onload event handler to the dynamic jQuery script, which will trigger your plugin after loading jQuery. Of course such event handlers have cross-browser compatibility issues, so it's easier to write them... with jQuery.
Bottom line: it's a lot of trouble and you're usually better off just writing two script tags.
P.S.: Some of the above techniques are explained in this article:
http://www.stevesouders.com/blog/2008/12/27/coupling-async-scripts/
I know about document.ready() but I don't want to wait for some content on external servers like Google Analytics, some ad serving content or anything else that isn't absolutely required for the website. I see this problem on sites that have user comments, and usually every single external piece of content has to be loaded before comments become available to use and even if one of the many CDNs is late, it blocks everything else.
I don't think you need to test it as much as you need to defer it. Here is a really simple example from Google.
(the following code copied from Google)
// Add a script element as a child of the body
function downloadJSAtOnload() {
var element = document.createElement("script");
element.src = "deferredfunctions.js";
document.body.appendChild(element);
}
// Check for browser support of event handling capability
if (window.addEventListener)
window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", downloadJSAtOnload);
else window.onload = downloadJSAtOnload;
Essentially, add a new script tag at the documentReady state when you're executing your code already.
This is how I'm trying to hook into the mobileinit event:
$(document).bind("mobileinit", function() {
console.log("Mobile init");
});
But this doesn't work on Chrome (Latest version), Ripple v0.9.1 and on a BlackBerry bold 9790 running OS7.0.
Note: I also tried using .on() instead of .bind() but no luck. Both jQuery mobile versions (1.0.1 and 1.1.0) failed.
I've used this and it does work.
Is it possible something else is breaking the script or the mobileinit isn't being fired?
Does Chrome fire mobileinit?
I just found some code I used in jQuery Mobile 1.0 and we just upgraded to 1.1.0 and it works.
You're making sure to also include regular ol' jQuery, right?
jQueryMobile's docs do it, so I'm sure it works. Something else must be wrong. Sorry I'm not much help. Do you have any more info? Or try with a different device.
[edit] On that same self page, it says "Because the mobileinit event is triggered immediately, you'll need to bind your event handler before jQuery Mobile is loaded. Link to your JavaScript files in the following order:"
<script src="jquery.js"></script>
<script src="custom-scripting.js"></script> <!-- Note your script before jqm -->
<script src="jquery-mobile.js"></script>
Looks like the script order can matter.
Here is another simple example that works with me (for android and ios)
<script type="text/javascript" src="files/resources/lib/jquery/jquery-1.8.2.js"> </script>
<script type="text/javascript">
$(document).bind("mobileinit", function()
{
if (navigator.userAgent.toLowerCase().indexOf("android") != -1)
{
// your logic here
$.mobile.defaultPageTransition = 'none';
$.mobile.defaultDialogTransition = 'none';
}
if (navigator.userAgent.toLowerCase().indexOf("msie") != -1)
{
// your logic here
$.mobile.allowCrossDomainPages = true;
$.support.cors = true;
}
});
</script>
<script type="text/javascript" src="files/resources/lib/jquerymobile/1.3.2/jquery.mobile-1.3.2.js"></script>
include the main jquery file
bind mobileinit before jquery mobile
include jquery mobile js file