how to solve the Defer parsing of JavaScript? - javascript

How to solve the following error:
826.9KiB of JavaScript is parsed during initial page load. Defer parsing JavaScript to reduce blocking of page rendering.
My Javascript code is:
{foreach $javascript.external as $js}
<script type="text/javascript" src="{$js.uri}" {$js.attribute} ></script>
{/foreach}

Assuming you are adding scripts in the head tag ,you can defer blocking of page rendering by adding the script near closing body tag instead of in header.
Alternatively create a IIFE and load the scripts after page has rendered
(function() {
function loadJS() {
var s = document.createElement('script'),
getScriptTag = document.getElementsByTagName('script')[0];
s.type = 'text/javascript';
s.async = true;
s.src = 'script location';
getScriptTag.parentNode.insertBefore(s, x);
}
(window.attachEvent) ? window.attachEvent('onload', loadJS): window.addEventListener('load', loadJS, false)
}());

Related

Load Multiple Scripts After Page Has Loaded?

I am using following code inside my HTML to load a JS file after page load.(DOMContentLoaded)
<script>
document.addEventListener('DOMContentLoaded', function() {
var script = document.createElement('script');
script.src = 'https://ajax.aspnetcdn.com/ajax/jquery/jquery-1.12.4.min.js';
document.getElementsByTagName('body')[0].appendChild(script);
});
</script>
But I have several scripts to load and I have no idea how to do this in the best possible way. For example, I have following files to link.
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-1.12.4.min.js"></script>
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/4.0.0/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2#8"></script>
Any help would be greatly appreciated.
If you know upfront the script names you can define an array like:
var scripts = ["script1.js", "anotherscript.js", "whatever.js"];
And then loop through it, and for each script you can append it as you did before
var scriptName;
for (scriptName in scripts) {
// create the script and set the src = scriptName as before
}

Load script in HTML after retrieving backend data via angular

I retrieve some HTML from database via angular and bind it on frontend with $sce.trustAsHtml. There is script that does some actions on retrieved HTML.
Angular controller:
$scope.Page= response.data;
$scope.pageContent = $sce.trustAsHtml($scope.Page.Content);
In page html file:
<div ng-bind-html="pageContent">
And there is script file which is loaded inside page html file:
<script src="scripts/script.js"></script>
This script must be executed after $scope.Page= response.data
What I tried is to use:
document.addEventListener("DOMContentLoaded", function(event) {
setTimeout(function(){
// script code
}, 2000);
});
And it works, but script file is however loaded immediately after page html file is loaded, it just timeouts "script code". I want to postpone script loading until I retrieve $scope.Page= response.data;
Is there angular directive or something to use on element to load it after $scope.Page is available or some other solution?
In your case, I would recommend you to store the script content in a cdn url or else you can store it in $templateCache in the application. Check the below sample for better understanding.
function sampleController($scope, $templateCache) {
//templateCache will store the template/script
$templateCache.put('myScript', 'alert("hi")');
//function to execute at a point of time
$scope.executeScript = function() {
var scriptContent = $templateCache.get('myScript');
var script = document.createElement('script');
script.type = 'text/javascript';
script.textContent = scriptContent;
document.head.appendChild(script);
};
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="sampleController" ng-app>
<button ng-click="executeScript()">Execute Script</button>
</div>
You can manually create a <script> element and set its src attribute to the desired URL after the HTML content is bound:
var tag = document.createElement('script'),
firstScript = document.getElementsByTagName('script')[0];
tag.src = 'scripts/script.js';
firstScript.parentNode.insertBefore(tag, firstScript);

How to dynamically add script which will be executed right now?

There is the simple page:
<html>
<head>
<script type="text/javascript" src="scripts/x.js"></script>
</head>
<body>
<script type="text/javascript">
console.log($);
</script>
</body>
</html>
'scripts.x.js':
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'https://code.jquery.com/jquery-1.12.3.min.js';
script.async = false;
script.defer = false;
document.currentScript.parentNode.insertBefore(script, document.currentScript.nextSibling);
This script just adds a new external script tag right after current script, but it doesn't work, because 'console.log' writes error 'index.html:8 Uncaught ReferenceError: $ is not defined'. What am I doing wrong? Thanks in advance!
The problem is that because of the asynchronous I/O model of JavaScript the script doesn't do what you expect. You probably think the script will stop executing while jQuery is loading, then continue once the external script (https://code.jquery.com/jquery-1.12.3.min.js in your case) is loaded.
What actually happens is that the I/O operation is done by another thread and by the time the JS interpreter reaches the console.log call, the I/O hasn't finished yet and therefore $ hasn't been initialized yet.
I suggest that you try requirejs - it handles loading of external scripts asynchronously.

Page loading blocks by remote javascript

I am loading external javascript on my site through:
<script language="javascript" type="text/javascript">
document.write("<script src='http://remoteserver/banner.php?id=10&type=image&num=3&width=200'><\/script>");
</script>
Everything was fine, but today was a big timeout from the remote server and page loading on site was blocking.
Is there possibility to load javascript asynchronous or to load it after page loads?
I don't want page load interruption while remote server not working.
I know there are tag async in HTML5, but it's not working, i think because this script is more complex than javascript (its ending with ".php").
Also i know it's better to put javascript files before /body tag to prevent this problem, but it's not the best solution.
Do you know other solutions?
Sync script blocks the parser...
Incorrect Method:
<script type="text/javascript" src="https://apis.google.com/js/plusone.js">
</script>
Async script will not block the rendering of your page:
Correct method:
<script type="text/javascript">
(function(){
var po = document.createElement('script');
po.type = 'text/javascript';
po.async = true;
po.src = "https://apis.google.com/js/plusone.js";
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(po, s);
})();
</script>
Source: http://www.youtube.com/watch?feature=player_detailpage&v=Il4swGfTOSM&t=1607
You can easily do it by creating DOM nodes.
<script>
var scriptEl = document.createElement("script"); //Create a new "script" element.
scriptEl.src = "http://remoteserver/banner.php?id=10&type=image&num=3&width=200";
// ^ Set the source to whatever is needed.
document.body.appendChild(scriptEl);
// Append the script element at the bottom of the body.
</script>

How to add jQuery CDN fallback in XHTML?

It is good practice to load a CDN-hosted jQuery but to fallback to a local file. E.g. HTML5 Boilerplate does it like this:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.8.0.min.js"><\/script>')</script>
But how can the same be implemented in XHTML? As document.write() doesn't work in proper XHTML (sent as application/xhtml+xml), is there an alternative?
This code creates a new <script/> element and appends it before first <script/> element on your page:
if (!window.jQuery) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'js/vendor/jquery-1.8.0.min.js';
var firstScript = document.getElementsByTagName('script')[0];
firstScript.parentNode.insertBefore(script, firstScript);
}
createElement, setAttribute, appendChild as per usual when replacing document.write or innerHTML
Expanding on Maxim Vi.'s reply, I made it closer to the original idea to insert it where it is called:
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script type="text/javascript" id="jQuery">
if (!window.jQuery) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = '/js/jquery-1.8.0.min.js';
var jQueryScript = document.getElementById('jQuery');
jQueryScript.parentNode.insertBefore(script, jQueryScript);
}
</script>
This way you can keep your scripts in the footer (in case you have other scripts inside the page, it won't get inserted too early or in different locations).
Edit: I had problems in some browsers with that solution, but moving the id="jQuery" further down solved it. I adjusted the code accordingly.

Categories

Resources