What tricks can be used to stop javascript callouts to various online services from slowing down page loading?
The obvious solution is to do all the javascript calls at the bottom of the page, but some calls need to happen at the top and in the middle. Another idea that comes to mind is using iframes.
Have you ever had to untangle a site full of externally loading javascript that is so slow that it does not release apache and causes outages on high load? Any tips and tricks?
window onload is a good concept, but the better option is to use jQuery and put your code in a 'document ready' block. This has the same effect, but you don't have to worry about the onload function already having a subscriber.
http://docs.jquery.com/Core/jQuery#callback
$(function(){
// Document is ready
});
OR:
jQuery(function($) {
// Your code using failsafe $ alias here...
});
edit:
Use this pattern to call all your external services. Refactor your external script files to put their ajax calls to external services inside one of these document ready blocks instead of executing inline. Then the only load time will be the time it takes to actually download the script files.
edit2:
You can load scripts after the page has loaded or at any other dom event on the page using built in capability for jQuery.
http://docs.jquery.com/Ajax/jQuery.getScript
jQuery(function($) {
$.getScript("http://www.yourdomain.com/scripts/somescript1.js");
$.getScript("http://www.yourdomain.com/scripts/somescript2.js");
});
Not easy solution. In some cases it is possible to merge the external files into a single unit and compress it in order to minimize HTTP requests and data transfer. But with this approach you need to serve the new javascript file from your host, and that's not always possible.
I can't see iframes solving the problem... Could you please elaborate ?
See articles Serving JavaScript Fast and Faster AJAX Web Services through multiple subdomain calls for a few suggestions.
If you're using a third-party JavaScript framework/toolkit/library, it probably provides a function/method that allows you to execute code once the DOM has fully loaded. The Dojo Toolkit, for example, provides dojo.addOnLoad. Similarly, jQuery provides Events/ready (or its shorthand form, accessible by passing a function directly to the jQuery object).
If you're sticking with plain JavaScript, then the trick is to use the window.onload event handler. While this will ultimately accomplish the same thing, window.onload executes after the page--and everything on it, including images--is completely loaded, whereas the aforementioned libraries detect the first moment the DOM is ready, before images are loaded.
If you need access to the DOM from a script in the head, this would be the preferred alternative to adding scripts to the end of the document, as well.
For example (using window.onload):
<html>
<head>
<title>Test Page</title>
<script type="text/javascript">
window.onload = function () {
alert(document.getElementsByTagName("body")[0].className);
};
</script>
<style type="text/css">
.testClass { color: green; background-color: red; }
</style>
</head>
<body class="testClass">
<p>Test Content</p>
</body>
</html>
This would enable you to schedule a certain action to take place once the page has finished loading. To see this effect in action, compare the above script with the following, which blocks the page from loading until you dismiss the modal alert box:
<html>
<head>
<title>Test Page</title>
<script type="text/javascript">
alert("Are you seeing a blank page underneath this alert?");
</script>
<style type="text/css">
.testClass { color: green; background-color: red; }
</style>
</head>
<body class="testClass">
<p>Test Content</p>
</body>
</html>
If you've already defined window.onload, or if you're worried you might redefine it and break third party scripts, use this method to append to--rather than redefine--window.onload. (This is a slightly modified version of Simon Willison's addLoadEvent function.)
if (!window.addOnLoad)
{
window.addOnLoad = function (f) {
var o = window.onload;
window.onload = function () {
if (typeof o == "function") o();
f();
}
};
}
The script from the first example, modified to make use of this method:
window.addOnLoad(function () {
alert(document.getElementsByTagName("body")[0].className);
});
Modified to make use of Dojo:
dojo.addOnLoad(function () {
alert(document.getElementsByTagName("body")[0].className);
});
Modified to make use of jQuery:
$(function () {
alert(document.getElementsByTagName("body")[0].className);
});
So, now that you can execute code on page load, you're probably going to want to dynamically load external scripts. Just like the above section, most major frameworks/toolkits/libraries provide a method of doing this.
Or, you can roll your own:
if (!window.addScript)
{
window.addScript = function (src, callback) {
var head = document.getElementsByTagName("head")[0];
var script = document.createElement("script");
script.src = src;
script.type = "text/javascript";
head.appendChild(script);
if (typeof callback == "function") callback();
};
}
window.addOnLoad(function () {
window.addScript("example.js");
});
With Dojo (dojo.io.script.attach):
dojo.addOnLoad(function () {
dojo.require("dojo.io.script");
dojo.io.script.attach("exampleJsId", "example.js");
});
With jQuery (jQuery.getScript):
$(function () {
$.getScript("example.js");
});
If you don't need a particular script ad load time, you can load it later by adding another script element to your page at run time.
Related
I have some javascript that is not required for my initial page load. I need to load it based on some condition that will be evaluated client-side.
$(document).ready(function() {
let someCondition = true; // someCondition is dynamic
if (someCondition) {
var element = document.createElement('script');
element.src = 'https://raw.githubusercontent.com/Useless-Garbage-Institute/useless-garbage/master/index.js';
element.defer = true; // does this make a difference?
element.onload = function() {
// do some library dependent stuff here
document.getElementById("loading").textContent = "Loaded";
};
document.body.appendChild(element);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1 id="loading">Loading...</h1>
Does it make a difference (in terms of how browser will treat the script tag), if a new tag created using javascript, after document is ready, has 'defer' attribute or not? I think there is no difference, but how can I say for sure?
I believe I understand how deferred scripts behave when script tag is part of the initial html (as described here). Also, this question is not about whether element.defer=true can be used or not (subject of this question).
No that doesn't make any difference, the defer attribute is ignored in case of "non-parser-inserted" scripts:
<script defer src="data:text/javascript,console.log('inline defer')"></script>
<script>
const script = document.createElement("script");
script.src = "data:text/javascript,console.log('dynamic defer')";
script.defer = true;
document.body.append(script);
</script>
<!-- force delaying of parsing -->
<script src="https://deelay.me/5000/https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Look at your browser's console or pay attention to the logs timestamps to see that the dynamically inserted script actually did execute while we were waiting for the delayed script to be fetched.
There's a difference between adding them to the function and adding directly the CDN ( especially in your case ).
Let's look at the code execution of the above-mentioned code first,
You have added the jquery CDN first ( without defer ) so that loads first.
$(document).ready will be fired once after the complete load of jquery.
There'll be the creation and insertion of a new script tag to the dom.
Download the https://raw.githubusercontent.com/Useless-Garbage-Institute/useless-garbage/master/index.js asynchronously.
Let's look at another approach: adding CDN to the code:
Your DOM will have 2 script tags.
Both will start loading based on the type of load parallelly ( defer async etc ).
Notice you are not waiting for the dom ready event to load the second script.
I suggest adding only the main JS part in a js file and adding it to the CDN. Others can wait load with the delay.
In case you are really needed with a js src, then don't load it the first way since it waits for the complete page load.
I suggest you read and look at web-vitals and SEO for this.
and for your other question, yes you can add defer attribute with element.defer=true to the elements while creating and loading to DOM.
Hope this answer helps you!
Feel free to comment if you get any errors or doubts.
I think the JQuery Arrive lib will solve your case.
I am trying to get a script from another website using jQuery then document.write it
here is my code
var url = "https://code.jquery.com/jquery-1.10.2.js";
var dam = $.getScript(url);
document.write(dam);
But this doesn't work!!
all what I get on the page is [object Object]
Can this be achieved without XHR?
jsfiddle
Don't use document.write, it does not do what you think it does. What it does not do is write some data at the end of the document. What it does instead, is pipe data into the current write stream. And if there is no write stream, it will make a new one, resetting the document's content. So calling document.write(dam) means you just wiped your document. document.write is a low level JS function from an earlier era of JavaScript, don't use it.
Instead, you want to use modern DOM manipulation functions, so in jQuery, that's stuff like:
$(document.head).append($("<script>").attr("src", url));
where
$("<script>")
builds a new script element,
$(...).attr("src", url)
sets the "src" attribute to what you need it to be, and:
$(document.head).append(...)
or
$(document.body).append(...)
to get the script loaded into your document. If it's a plain script with src attribute, it can basically go anywhere, and if it's a script with text content that should run, you can only make that happen through document.head.
Although if it's just a script you need to load in and run, you can use getScript, but then you don't need to do anything else, it's just:
var url = "https://code.jquery.com/jquery-1.10.2.js";
jQuery.getScript(url);
Done, jQuery will load the script and execute it. Nothing gets returned.
Of course, the code you're showing is loading jQuery, using jQuery, so that's kind of super-odd. If you just want to load jQuery on your page, obviously you just use HTML:
<!doctype html>
<html>
<head>
...
</head>
<body>
...
<script src="http://https://code.jquery.com/jquery-1.10.2.js"></script>
</body>
</html>
with the script load at the end so the script load doesn't block your page. And then finally: why on earth are we loading jQuery version 1.x instead of 2.x? (if you need to support IE8: that's not even supported by Microsoft anymore, so you probably don't need to).
And finally, if we don't want to load the script, but we really just want its content, as plain text, there's only a million answers on Stackoverflow already that tell you how to do that. With jQuery, that's:
$.get("http://https://code.jquery.com/jquery-1.10.2.js", function(data) {
$(document.body).append($("div").text(data));
});
But you knew that already because that's been asked countless times on Stackoverflow and you remembered to search the site as per the how to ask instructions before asking your question, right?
executing the script on the page is not my goal!. I want to get the
script content and put it a div (USING JAVASCRIPT - NO XHR) , is that
possible ?
Try utilizing an <iframe> element
<div>
<iframe width="500" height="250" src="https://code.jquery.com/jquery-1.10.2.js">
</iframe>
</div>
jsfiddle http://jsfiddle.net/snygv469/3/
Make it easier... use my fiddle
http://jsfiddle.net/wwwfzya7/1/
I used javascript to create an HTML element
var url = "https://code.jquery.com/jquery-1.10.2.js";
var script = document.createElement("SCRIPT"); //creates: <script></script>
script.src = url; //creates: <script src="long_jquery_url.js"></script>
document.body.appendChild(script); //adds the javascript-object/html-element to the page.!!!
Use this way, it can fix your problems.
$.get( "https://code.jquery.com/jquery-1.10.2.js", function( data ) {
alert(data);
});
You can try adding
<script src="http://code.jquery.com/jquery-1.8.3.min.js" ></script>
Then an AJAX call, but it pulls data from CACHE. It looks like an AJAX but when <script> is added file goes in cache, then read from cache in the ajax. In cases where it is not stored in cache read it using normal AJAX.
jQuery.cachedScript = function(url, options) {
// Allow user to set any option except for dataType, cache, and url
options = $.extend(options || {}, {
dataType: "text",
cache: true,
url: url
});
// Use $.ajax() since it is more flexible than $.getScript
// Return the jqXHR object so we can chain callbacks
return jQuery.ajax(options);
};
$(document).on('ready', function() {
// Usage
$.cachedScript("http://code.jquery.com/jquery-1.8.3.min.js").done(function(script, textStatus) {
console.log(script);
});
});
Normal Solution
If you are ready to use AJAX look at this fiddle
How to fetch content of remote file and paste it on your document and execute that js code
I guess you want to get content written on remote file and want to write that content in your HTML. to do this you can use load() function.
To do this follow the following steps:
1. Create a file index.html Write the following code in it:
<pre id="remote_script"></pre>
<script>
$(document).ready(function() {
//var url = "https://code.jquery.com/jquery-1.10.2.js";
var url = "remote_script.html";/* For testing*/
$('#remote_script').load(url,function(){
eval($('#remote_script').text()); /* to execute the code pasted in #remote_script*/
});
});
</script>
2. Create another file remote_script.html for testing write alert('a'); in it without any <script> tag and run the above code.
I have a javascript code like this
<script type="text/javascript">
window.onload=myFunction;
</script>
Is there any difference in using the above snippet in the <head></head> tag and just before
</body> tag, as I would like to call my function after the page loads.
basically there's no pratical difference, but I recommend
to place that code at the bottom, since you need to use a script (blocking-rendering tag) it's better put it at the end of the document.
to avoid a destructive assignments like that: writing window.onload=myFunction you destroy other previous assignments to window.onload event (if any) so it's better something like
(function() {
var previousOnLoadIfAny = window.onload;
window.onload = function() {
if (typeof previousOnLoadIfAny === 'function') {
previousOnLoadIfAny();
}
yourfunction();
}
}());
Binding to window.onload will always run your function when the load event fires. This only fires after everything in the page has finished loading, including images etc. If you want to run your function when the DOM has finished loading but before everything else then you can bind to the DOMContentLoaded event or use a library like jQuery (e.g. $(function(){ myFunction() });).
The benefit about putting your function at the end of your <body> is that theoretically this means that the rest of your content has already loaded and you don’t need to bind your function to a load event. This sometimes works, but depends on the situation.
No, where you place that will not matter - anywhere in the document and it will trigger when the document and all external resources (images, scripts etc) has loaded.
Because onload triggers after all external resources one often want to use DOMContentLoaded instead which triggers when the HTML DOM is ready. Which will make for a page that is more responsive.
I want to ask a question about the Javascript’s onload.
I’m writing a JSP page with the code <%# include file ="body.jsp". The included body.jsp contains:
<table onload="function()">
This should load the javascript function, but it doesn't appear to have any effect on the page. Is onload only usable on the body tag?
Onload can only be used for <body>, <img>, <script>, <iframe> tags, because it tells you when an external resource (image, script, frame) or the whole page (body) has been loaded
Since HTML5 these can also fire a load event: <link>, <style>, <input type=image>, <object>
Support for these can still be a hit or miss though (e.g. older Android browsers)
Why not just include it via a <script tag>?
Inside your .jsp file
<script>
window.onload = function() {
alert("Hello!");
}
// or to execute some function
window.onload = myFunction; //notice no parenthesis
</script>
As the other guys already stated the onLoad event will not fire on a table. What you can do ist attaching the onLoad-handler to the body element (which will then fire, when the page is loaded) and manipulate the table by for example assigning an id to the table.
<body onload="function() { var table = document.getElementById("table-id"); ... }">
<table id="table-id"></table>
</body>
Are you using some javascript framework?
"onLoad" may be used on body- and frameset-tags.
To see some action you may use:
<body onload="function(){alert('This is an action!')}">
The easiest way i find is to use an external javascript file and jquery.
// Variables and functions you want to declare
var socket = io.connect();
// .....
// Function you want to run on load
$(function() {
$('#submit').click(function() {addUser();});
// ... any other functions you want to run on load
});
This is a code snippet from something that i was working on. The variable is declared before the code runs (It creates a web socket).
Then there is the jquery document selector ($) which runs on load and calls the init function to modify my html. I use it to call an anonymous function which runs right away.
You can throw a <script> tag right after your table with code. Once it gets to the script tag it would mean that the DOM for the table element above it has been loaded and can now be accessed in your script below it.
Note: The following below isn't applicable to the question but rather the other answers being given.
I recommend using the addEventListener function in javascript for adding the event. This makes sure that you are not overwriting or going to be overwritten by anyone else wanting to listen to the event.
Example
var iframe = document.getElementsByTagName('iframe')[0];
iframe.addEventListener('load', function(event){ console.log("iframe Loaded", event); })
I'm writing a webpage that relies on an external javascript file (that I have no control of), which returns data by using document.write's. Is there any way to dynamically call the function without it overwriting the whole document? Here's the most concise code I can think of:
<html>
<head>
<script type="text/javascript">
function horriblefunction () {
document.write("new text");
}
</script>
</head>
<body>
Starting Text...
<div id="pleasewriteinme"></div>
Other text...
<button onclick="horriblefunction();">Click</button>
</body>
</html>
The idea beginning that without altering "horriblefunction()" (as it's external) the new text could be placed in the div instead of overwriting the page. Is this possible or does the function have to be called inside the div as the page is created?
Thanks for you help
The only way to use document.write after the page has finished rendering is to temporarily replace the function with one of your own making that will shove the content into a div. E.g.
function horriblefunction() {
var old_dw = document.write;
document.write = function(text) {
document.getElementById( 'some_div' ).innerHTML = text;
}
// now call your external JS function that uses document.write
document.write = old_dw;
}
This will work as long as the external JS is already loaded and you're just calling a function. If you need to load the JS (say, by inserting a new <script> tag into the DOM) remember that that operation is asynchronous, and you'll need to watch the DOM to know when it's safe to restore the old version of document.write.
Try using dynamic script loading from http://bezen.org/javascript/index.html
bezen.domwrite.js - Captures document.write and writeln for the safe loading of external scripts after page load.