Showing posts with label js. Show all posts
Showing posts with label js. Show all posts

Tuesday, June 12, 2012

open source JS files loaders: LabJS review

It's heated topic and people always do some differently (http://www.phpied.com/preload-cssjavascript-without-execution/) for loading HTML resources without blocking.

I have a several thoughts. Actually i spent some time and reviewed LabJS codebase and found few conclusions.

LabJs is playing with ready event with XHR technique to load files ( see how many ways we can load js files without blocking .... http://www.stevesouders.com/blog/2009/04/27/loading-scripts-without-blocking/).

The ready event occurs after the HTML document has been loaded, while the onload event occurs later, when all content (e.g. images etc) also has been loaded.

The onload event is a standard event in the DOM, while the ready event is specific to browser(so
it required various browser checks).

The purpose of the ready event is that it should occur as early as possible after the document has loaded, so that code that adds functionality to the elements in
the page doesn't have to wait for all content to load.

As i said ready event is not standard event so it need different cross browser checks and it's not necessary that its always return correct result.

On time by time people tried to get ready event but it's not full proof.
---------------------------------------------------------------------
Let's check how much reliable is Ready event
---------------------------------------------------------------------

------------------------------
LAB JS History
------------------------------


We have seen different script loaders but i think LABjs’s goal is a bit different from others.
It enable parallel downloading of JavaScript files while maintaining execution order.


To do so, LABjs needs to know which browsers allow parallel downloads by default and then provide
other solutions for the browsers that don’t.

All loaders are using various browser detection techniques to determine the correct action
to optimize script loading.

BUT Browser detection is still not full proof in JS.

http://www.nczonline.net/blog/2009/12/29/feature-detection-is-not-browser-detection/


Unfortunately LABJs was failed in past to maintain execution order. See below links.

https://twitter.com/getify/status/26109887817 [ by Kyle]

Blog post of Kyle ( http://blog.getify.com/ff4-script-loaders-and-order-preservation/comment-page-1/)
and See Guy's comment who wrote Firefox Gecko engine code.
(http://blog.getify.com/ff4-script-loaders-and-order-preservation/comment-page-1/#comment-748)

Finally Kyle have wiki website ( http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order) where he maintain list of issues ( due to different behavior of browsers like Mozilla Gecko and Web-kit) so that browser vendors internalize these issues and come up with ways to solve them.

----------------------------
negative side effects
----------------------------
In below links Kyle mentioned that LABjs will not work properly :

  • if page is used document.write
  • if codebase is used ready event poorly
  • Other negative effects which are mentioned, BTW nice abbreviated by Kyle: "FUBC" (flash of un-behaviored content)
http://labjs.com/description.php#whennottouse

http://blog.getify.com/labjs-new-hotness-for-script-loading/#ux-labjs

-----------------------------
Why we need LoadJs ?
-----------------------------

First, all loader scripts are trying to enable parallel downloading of JavaScript resources. That’s a worthy goal but one that’s already being handled by newer browsers.

see below link where i load 19 HTML resources in normal manner but still JS files are loaded parallel.

http://172.16.3.228/public/test.html



Second, LABjs is very focused on maintaining script execution order.
With this comes an assumption that we want to download multiple JavaScript files that have
dependencies on one another. This is something that don’t recommend but I think that some people  feel it’s important.



Third, other loaders are focused on separation of download and execution of JavaScript. It is the
idea that download a JavaScript file and not execute it until a point in time determined by
us(requirejs did same job in very decent manner)
. The assumption here is that page is progressively
enhanced such that JavaScript isn’t immediately needed. LABjs doesn’t address this problem. Browsers are also not helping with this.

So all these loaders require constant monitoring and updating as new browser versions come
out. Maintenance is important in JS based websites and these libraries add maintenance
overhead that isn’t necessary.

----------------------------------------------------
Then What Lazyload does actually do ?
---------------------------------------------------

In shiksha.com we use loadscript & upLoadJsOnDemand function for parallel downloading.

We can easily GREP codebase with "loadScript" or "
upLoadJsOnDemand".

Actually Lazyload was introduced for different purpose. It servers files which are
not required in main page rendering.
 Some features are listed below.

1. load file only once
2. load file after on load event ( before lazyload API, it was unable to load js files in javascript code )
3. callback Fn execution
4. pass objects to callback Fn in global scope
5. callback Fn execution even files are loaded




Friday, December 17, 2010

W3C DOM vs. innerHTML which is slower ?

We can check by running test script.


<div id="writeroot" style="width:1px; height:1px; overflow:hidden;"></div>
<script>
 function removeTable() {
  document.getElementById('writeroot').innerHTML = '';
 }
</script>


W3CDOM 1: Create all elements as needed:-



removeTable();
var x = document.createElement('table');
var y = x.appendChild(document.createElement('tbody'));
for (var i = 0; i < 20; i++) {
 var z = y.appendChild(document.createElement('tr'));
 for (var j = 0; j < 20; j++) {
  var a = z.appendChild(document.createElement('td'));
  a.appendChild(document.createTextNode('*'));
 }
}
document.getElementById('writeroot').appendChild(x);

Result is 55 % slower as compare others.

W3CDOM 2: Create elements once, then clone:-


removeTable();
var x = document.createElement('table');
var y = x.appendChild(document.createElement('tbody'));
var tr = document.createElement('tr');
var td = document.createElement('td');
var ast = document.createTextNode('*');
for (var i = 0; i < 20; i++) {
 var z = y.appendChild(tr.cloneNode(true));
 for (var j = 0; j < 20; j++) {
  var a = z.appendChild(td.cloneNode(true));
  a.appendChild(ast.cloneNode(true));
 }
}
document.getElementById('writeroot').appendChild(x);


Result is 36 % slower as compare others.

tableMethods:-


removeTable();
var x = document.createElement('table');
var y = x.appendChild(document.createElement('tbody'));
for (var i = 0; i < 20; i++) {
 var z = y.insertRow(0);
 for (var j = 0; j < 20; j++) {
  var a = z.insertCell(0).appendChild(document.createTextNode('*'));
 }
}
document.getElementById('writeroot').appendChild(x);

Result is 50 % slower as compare others.

INNERHTML 1: concatenate one string:-


removeTable();
var string = '<table><tbody>';
for (var i = 0; i < 20; i++) {
 string += '<tr>';
 for (var j = 0; j < 20; j++) {
  string += '<td>*</td>';
 }
 string += '</tr>';
}
string += '</tbody></table>';
document.getElementById('writeroot').innerHTML = string;

Result is 5 % fastest as compare others.

INNERHTML 2: push and join:-


removeTable();
var string = new Array();
string.push('<table><tbody>');
for (var i = 0; i < 20; i++) {
 string.push('<tr>');
 for (var j = 0; j < 20; j++) {
  string.push('<td>*</td>');
 }
 string.push('</tr>');
}
string.push('</tbody></table>');
var writestring = string.join('');
document.getElementById('writeroot').innerHTML = writestring;

Result is 2% slower than others tests.

Actual results are as follows.
Columns as as follows. innerHTML1,innerHTML2,W3CDOM 1,W3CDOM 2,tableMethods and No of Tests


Chrome 8.0.552 197 194 617 647 634 10
Chrome 9.0.597 175 180 349 362 398 5
Chrome 10.0.612 202 207 743 718 684 3
Firefox 3.6.11         93 90 81 71 79 1
Firefox 3.6.12         208 204 177 150 172 4
Firefox 3.6.13         115 112 105 86 106 3
Firefox Beta
 4.0b7                786 696 508 409 378 7
IE 6.0                20 84 18 19 10 8
IE 8.0                240 234 43 47 47 9
iPhone 4.2.1       18 19 47 49 49 1
Opera 11.00       772 752 347 491 383 1
Safari 5.0.2       190 196 616 607 589 1
Safari 5.0.3       209 219 623 595 584 11

So Finally inner HTML won and it's fastest among all methods. 

Monday, November 22, 2010

Web site Front-end optimization headaches

I have seen that typically 80-90% of page response time comes from other things than fetching HTML of the page :- fetching CSS, JavaScript, Images,banners which makes it number one thing to focus your optimization. Sharing few points, specially for front-end optimization. Hope this will be helpful.

1. Try to split initial payload .. first load all required js to load page then other scripts/things.
Lazyload,ajaxload,load scripts in parrller,load script after on windowload, these are different things and you must know about it.When the browser starts downloading an external script, it won’t start any additional downloads until the script has been completely downloaded, parsed, and executed. So load external scripts asynchronously only. we also need to care about inline JS, here we can use callback functions,timers,on window load etc see following chart , here few techniques are listed to load JS scripts.


2. Flushing the Document Early:-

 As the server parses the PHP page, all output is written to STDOUT. Rather than being sent immediately, one character, word, or line at a time, the output is queued up and sent to the browser in larger chunks. This is more efficient because it results in fewer packets being sent from the server to the browser. Each packet sent incurs some network latency, so it’s usually better to send a small number of large packets, rather than a large number of small packets. Calling flush() causes anything queued up in STDOUT to be sent immediately. How- ever, simply flushing STDOUT isn’t enough to achieve the type of speedup experienced in the preceding example. The call to flush has to be made in the right place. idea is , flush before a long time taking process, it can be divide as module wise also like header,footer,sidebar,widgets etc.

3. Repaint and Reflow is costly:-

A repaint occurs when a visual change doesn't require recalculation of layout Changes to visibility, colors (text/background), background images, etc.
  
  
A reflow occurs when a visual change requires a change in layout Initial page load
 browser resize,DOM structure change,layout style change layout information retrieved
 
 

4. Eliminate unnecessary cookies:- 

Keep cookie sizes as low as possible to minimize the impact on the user response time,Be mindful of setting cookies at the appropriate domain level so other sub-domains are not affected

5. DOM manipulations are the slowest,Never update the DOM, if that's not possible, at least do it as infrequently as possible. Bunch up your updates to the DOM and save them for a later time.

6. Clone the DOM node you want to work with. Now you will be working with a clone of the real node, and the cloned node doesn't exist in the DOM. Updating the cloned node doesn't affect the DOM. When you are done with your manipulations, replace the original node with the cloned node.

7. However, note that the performance problems in point 4, because of the content and rendering reflow that the browser has to do. You might get similar benefits by simply hiding the element first, making the changes, and then showing it.

Wednesday, June 23, 2010

Java Script Anonymous functions , Closures

People have doubts about closures and anonymous functions. actually closures are a type of function which allow the creation of functions which have no specified name. they are very useful when you want control over callback or you want use function as the values of variables. every language provide a freedom to create anonymous/closures functions. PHP also provide such feature .. 

$greet = function($name)
{
    
printf("Hello %s\r\n"$name);
};
$greet('World');$greet('PHP');
?>
http://php.net/manual/en/functions.anonymous.php


Back to our discussion. here, i summarized about js anonymous, closures. 


Anonymous functions
  • Any function that is defined as a function expression is technically an anonymous function since there is no definitive way to reference it.
  • With no definitive way to reference a function, recursive functions become more complicated.
  • Recursive functions should always use arguments.callee to call themselves recursively instead of using the function name, which may change.
Closures
Closures are created when anonymous functions are defined inside other functions, allowing the closure access to all of the variables inside of the containing function, as follows:-
  • Behind the scenes, the closure ’ s scope chain contains a scope for itself, a scope for the containing function, and the global scope.
  • Typically a function ’ s scope and all of its variables are destroyed when the function has finished executing.
  • When a closure is returned from that function, its scope remains in memory until the closure no longer exists.
Using closures, it ’ s possible to mimic block scoping in JavaScript, which doesn ’ t exist natively, as follows:-
  • A function can be created and called immediately, executing the code within it but never leaving a reference to the function.
  • This results in all of the variables inside the function being destroyed unless they are specifically set to a variable in the containing scope.
Closures can also be used to create private variables in objects, as follows:-
  • Even though JavaScript doesn ’ t have a formal concept of private object properties, anonymous functions can be used to implement public methods that have access to variables defined within the containing scope.
  • Public methods that have access to private variables are called privileged methods.
  • Privileged methods can be implemented on custom types using the constructor or prototype patterns as well as on singletons by using the module or module - augmentation patterns.
  • Anonymous functions and closures are extremely powerful in JavaScript and can be used to accomplish many things. Keep in mind that closures maintain extra scopes in memory, so overusing them may result in increased memory consumption.
original source  from Nicholas C. Zakas (Yahoo's principal front-end engineer) 

Thursday, June 10, 2010

How to detect a click outside an element to close overlay or modal box ?

function clickedOutsideElement(elemId) {
    var theElem = getEventTarget(window.event);
    while(theElem != null) {
        if(theElem.id == elemId)
            return false;
        theElem = theElem.offsetParent;
    }
    return true;
}


function getEventTarget(evt) {
    var targ = (evt.target) ? evt.target : evt.srcElement;
    if(targ != null) {
        if(targ.nodeType == 3)
            targ = targ.parentNode;
    }
    return targ;
}


document.onclick = function() {
    if(clickedOutsideElement('divTest'))
        alert('Outside the element!');
    else
        alert('Inside the element!');
}