Google PageSpeed Insights with Multiple JavaScript Files - javascript

I'm optimizing my site based on Google's PageSpeed Insights. It recommends that I "Remove Render-Blocking JavaScript" for several files (names simplified for example's sake):
<script src="js/1.js" type="text/javascript"></script>
<script src="js/2.js" type="text/javascript"></script>
<script src="js/3.js" type="text/javascript"></script>
I'm trying Patrick Sexton's "Defer Loading Javascript" approach which only defers one file (defer.js):
<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>
My question is, how can this approach be modified to include multiple files (i.e. 1.js, 2.js, 3.js)?

you can use HeadJS
for this. I was using it for one of our projects and it was pretty useful.

<script type="text/javascript">
function downloadJSAtOnload() {
var links = ["js/1.js", "js/2.js", "js/3.js"],
headElement = document.getElementsByTagName("head")[0],
linkElement, i;
for (i = 0; i < links.length; i++) {
linkElement = document.createElement("script");
linkElement.src = links[i];
headElement.appendChild(linkElement);
}
}
if (window.addEventListener)
window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", downloadJSAtOnload);
else window.onload = downloadJSAtOnload;
</script>

Related

How to defer javascript of an embedded YouTube video on Wordpress?

I want to defer the loading of a particular Javascript file. On GTMetrix, I get a 14 score under the 'Defer Loading Of Javascript' category. I want to defer the loading of this file:
https://www.youtube.com/yts/jsbin/player_ias-vflRCamp0/en_US/base.js
I've tried inserting scripts in my Theme's Footer, right before the tag. Here's what I've tried:
`<script type="text/javascript">
function parseJSAtOnload() {
var element = document.createElement("script");
element.src = "https://www.youtube.com/yts/jsbin/player_ias-vflRCamp0/en_US/base.js";
document.body.appendChild(element);
}
if (window.addEventListener)
window.addEventListener("load", parseJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", parseJSAtOnload);
else window.onload = parseJSAtOnload;
</script>
`
I've also tried:
`<script type="text/javascript">
function downloadJSAtOnload() {
var element = document.createElement("script");
element.src = "https://www.youtube.com/yts/jsbin/player_ias-vflRCamp0/en_US/base.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>`
These scripts do nothing to the GTMetrix score.
I've tried this as well:
`<script type="text/javascript">
function parseJSAtOnload() {
var links = ["www.youtube.com/yts/jsbin/player_ias-vflRCamp0/en_US/base.js", "www.youtube.com/yts/jsbin/www-embed-player-vflO7uv3_/www-embed-player.js"],
headElement = document.getElementsByTagName("head")[0],
linkElement, i;
for (i = 0; i < links.length; i++) {
linkElement = document.createElement("script");
linkElement.src = links[i];
headElement.appendChild(linkElement);
}
}
if (window.addEventListener)
window.addEventListener("load", parseJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", parseJSAtOnload);
else window.onload = parseJSAtOnload;
</script>`
This script will work temporarily. I'll test the page on GTMetrix and it shows that the Javascript is deferred. On the Waterfall chart, it shows that those scripts are canceled (insight here would be appreciated as well?)
When I Retest to make sure it's working, I'm back to the original score of 14. What else can I try, or what am I doing wrong?
Website Here: https://www.fralinpickups.com/product/vintage-hot/
You should create a file with your code and queue it with [wp_enqueue_script][1] hook.
If your file is called my_script.js and it is in the folder /js/ of your theme, the function should look like this:
// You probably already have a function to enqueue scripts in your theme function.php file.
function my_script() {
wp_enqueue_script( 'my_script', get_template_directory_uri() . '/js/my_script.js', array(), '1.0.0', true );
}
add_action( 'wp_enqueue_scripts', 'my_script' );
The key to load it after other scripts is in the fifth parameter of the function, when set to true it loads the script in the footer, before the body tag. If your script requires jQuery and/or other dependencies you can add them in the array using the corresponding handle, as indicated in the documentation (here).
If you want to asign defer to the script tag you could use the following:
function add_defer_attribute($tag, $handle) {
if ( 'my_script' !== $handle )
return $tag;
return str_replace( ' src', 'defer="defer" src', $tag );
}
add_filter('script_loader_tag', 'add_defer_attribute', 10, 2);
More info on script_loader_tag.
Update:
Here is a valid answer that can help you with deferring youtube javascript: How do you Defer Parsing of JavaScript for YouTube video on a WordPress site?

Defer parsing javascript not working properly

I try to let my website load faster. I ran a speedtest and came across "defer parsing javascript".
I used different sites to run a speedtest.
Those suggested to put the external js in 1 file.
I found a script on this site: defer parsing js script and used that.
This before the last body:
<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>
And this in the defer.js:
(function() {
function getScript(url,success){
var script=document.createElement('script');
script.src=url;
var head=document.getElementsByTagName('head')[0],
done=false;
script.onload=script.onreadystatechange = function(){
if ( !done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete') ) {
done=true;
if(success && getScript.call(success) == '[object Function]') { success(); }
script.onload = script.onreadystatechange = null;
head.removeChild(script);
}
};
head.appendChild(script);
}
getScript('
http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js',function(){
getScript('highslide/highslide-full.js');
getScript('javascripts/bootstrap-v3.2.0.min.js');
getScript('http://www.statcounter.com/counter/counter.js');
getScript('js/jquery.flexslider-min.js');
getScript('http://chs02.cookie-script.com/s/3e2959acb953e61e326f4716f65b6748.js');
getScript('js/jquery.easing.1.3.js');
getScript('js/jquery.kwicks-1.5.1.js');
getScript('javascripts/dropdown-custom.js');
getScript('js/touchTouch.jquery.js');
getScript('js/jquery.cookie.js');
});
})();
But when I test that, the dropdown menu, the slider and my highslide images don't work properly. What can I change so that it will work?
This is the testpage: testpage
Johanna

Can scripts with async attribute trigger callback functions when loaded?

Google Pagespeed told me to load my JS files asynchronously, so I wrote this code:
// Add script elements as a children of the body
function downloadJSAtOnload() {
var filesToLoad = [
["/assets/plugins/typeahead.bundle.min.js", "onTypeaheadLoaded"],
["https://apis.google.com/js/client:plusone.js?onload=googlePlusOnloadCallback", ""]
];
filesToLoad.forEach(function(entry) {
var element = document.createElement("script");
element.src = entry[0];
if (entry[1] != "") { // if an onload callback is present (NOTE: DOES NOT SUPPORT NAMESPACES -- http://stackoverflow.com/a/359910/1101095)
element.onload = function() {
if (typeof window[entry[1]] != "undefined") {
window[entry[1]]();
}
};
}
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;
However, someone just directed me to this article, which says using the async attribute is better than injecting script tags (this is contrary to what I've read most places, but the author show evidence he's right).
So, my question is, if I change to using the async attribute, is there a way to have a function triggered when the script is done loading?

script conflict

I have 5 scripts on my page and I’d like to add them altogther but am not too sure how.
The first is
<script type="text/javascript"><!--//--><![CDATA[//><!--
sfHover = function() {
var sfEls = document.getElementById("nav").getElementsByTagName("LI");
for (var i=0; i<sfEls.length; i++) {
sfEls[i].onmouseover=function() {
this.className+=" sfhover";
}
sfEls[i].onmouseout=function() {
this.className=this.className.replace(new RegExp(" sfhover\\b"), "");
}
}
}
if (window.attachEvent) window.attachEvent("onload", sfHover);
//--><!]]>
</script>
With the below since I've added the stock control message change, the reload doesn’t work. I’ve added a no conflict script but I don't think I've added it correctly. I'd like to put all 5 scripts together (above and below) in one tag that works - can anyone help out?
<script language="JavaScript">
//
function ImageLoadFailed() {
window.event.srcElement.style.display = "None";
}
// reload after adding product
function AddProductExtras(){
document.location.reload(true);
}
// for stock control - change message
function AddProductExtras(catalogId,productId,ret) {
var td = document.getElementById('catProdTd_'+productId);
if (td.innerHTML == 'This product is unavailable or out of stock.')
td.innerHTML = 'Product added successfully.';
}
jQuery.noConflict();
</script>
create one js file and in that paste all your 5 script codes.
And include this javascript file on your index page as:
<script type="text/javascript" src="name.js"></script>
try to call it in a new js page and link it to your main page.
<script type="text/javascript" src="file.js"></script>

Get files into the DOM with Javascript

To avoid the Google Pagespeed Messeger "Parsing Javascript later" I've copied this script.
<script type="text/javascript">
function downloadJSAtOnload() {
var element = document.createElement("script");
element.src = "http://example.com/templates/name/javascript/jquery.js";
document.body.appendChild(element);
var element1 = document.createElement("script");
element1.src = "http://example.com/templates/name/javascript/jquery.colorbox-min.js";
document.body.appendChild(element1);
}
if (window.addEventListener)
window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", downloadJSAtOnload);
else
window.onload = downloadJSAtOnload;
</script>
How could I solve it with a loop because I need one more javascript file insert into the DOM.
Greets
Ron
You can make a function like this that takes an arbitrary number of script filenames:
function loadScriptFiles(/* pass any number of .js filenames here as arguments */) {
var element;
var head = document.getElementsByTagName("head")[0];
for (var i = 0; i < arguments.length; i++) {
element = document.createElement("script");
element.type = "text/javascript";
element.src = arguments[i];
head.appendChild(element);
}
}
function downloadJSAtOnload() {
loadScriptFiles(
"http://example.com/templates/name/javascript/jquery.js",
"http://example.com/templates/name/javascript/jquery.colorbox-min.js",
"http://example.com/templates/name/javascript/myJS.js"
);
}
if (window.addEventListener)
window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", downloadJSAtOnload);
else
window.onload = downloadJSAtOnload;
If your script files have a required load order (I presume colorbox must load after jQuery, for example), you will have to do something more sophisticated than this because this loads them all asynchronously so they have no guaranteed load order. Once you need a particular load order, it's probably best to get code that someone else has written to solve this problem like RequireJS or LABjs or Google.load().
Note: I'm also appending the script files to the <head> tag which is a bit better place to put them.
When using LABjs, you are not putting the .wait() in the right place. .wait() tells the loader to wait until all PRIOR scripts are loaded before loading the next one. I think you need it like this:
$LAB
.script("templates/name/javascript/jquery.js").wait()
.script("templates/name/javascript/jquery.colorbox-min.js");

Categories

Resources