Js document.write output of the advertisement with no blocking load method

  • 2020-03-30 03:10:07
  • OfStack

One, advertising code analysis

Many third-party advertising systems use document.write to load ads, as shown in the following javascript AD link.


<script type="text/javascript" src="http://gg.5173.com/adpolestar/5173/
;ap=2EBE5681_1BA3_4663_FA3F_E73D2B83FBDC;ct=js;pu=5173;/?"></script>

This javascript request returns the following code:


document.write( "<a href='http://gg.5173.com/adpolestar/wayl/;" + 
"ad=6FF3F844_33E6_86EE_3B96_D94C1CF1AEC4;ap=2EBE5681_1BA3_4663_FA3F_E73D2B83FBDC;" + 
"pu=5173;/?http://www.7bao.com/g/xlsbz/index' target='_blank'><img src='" +
"http://html.5173cdn.com/market/yunyinga/xly132.gif' " +
"border='0' width="132px" height="58px" /></a>" );

This seems like a bit of a second load, but you can't change it because it's third-party. And the code has added the function of statistics, the above javascript advertising link every request will be counted once, the generated code also has the function of click statistics, that is, must be loaded in this way.

Document. The write is in the page rendering time synchronization, will have to wait for download javascript code and document. Write after the execution to render it and then later, if more advertising, will lead to the page block, especially in the first screen of the page in this advertising several image size is larger, so congestion situation is quite obvious and serious, makes the user feel you this web page is slow.

< img SRC = "border = 0 / / files.jb51.net/file_images/article/201406/201465113411978.png? 201455113432 ">

Rewrite document.write

To avoid blocking, you can't have the document.write method execute while the page is being rendered. You have to figure out a way to get the javascript advertising code to execute after the DOM tree is ready, but executing document.write after the DOM tree is ready rerenders the entire page, which is also not possible. Document.write is the browser's native method, but you can also customize a method to override the original method. Before the javascript AD code loads, rewrite document.write, wait for it to load and execute, and then change it back.

< img SRC = "border = 0 / / files.jb51.net/file_images/article/201406/201465113450184.png? 201455113458 ">

Lazy loading of javascript code

The key step above, lazy loading of javascript code, how to achieve? First attempt to rewrite the script of the type attribute, such as the type set to a custom attribute "type/cache", but that most of the browser (Chrome will not download) will still be downloading the code, but you don't perform, download when page rendering so still a piece of code blocks, by rewriting the script type cannot achieve real lazy loading, most can realize loading does not perform only, but also compatibility problems.

Put the script tag into the textarea tag, and then read the textarea when it needs to be loaded, so as to realize the real lazy loading script, this method is thanks to the BigRender (outside the wall) scheme proposed by yu bo.


<div>
<textarea style="display:none">
<script type="text/javascript" src="http://gg.5173.com/adpolestar/5173/
;ap=2EBE5681_1BA3_4663_FA3F_E73D2B83FBDC;ct=js;pu=5173;/?"></script>
</textarea>
</div>

Lazy loading script and rewrite document.write, the following is the code implementation:



var loadScript = function( elem ){
 var url = elem.value.match( /src="([sS]*?)"/i )[1],
  parent = elem.parentNode,
  //Cache native document.write
  docWrite = document.write, 
  //Create a new script to load
  script = document.createElement( 'script' ), 
  head = document.head || 
   document.getElementsByTagName( 'head' )[0] || 
   document.documentElement;

 //Rewrite the document. The write
 document.write = function( text ){
  parent.innerHTML = text;
 };
 script.type = 'text/javascript';
 script.src = url;

 script.onerror = 
 script.onload = 
 script.onreadystatechange = function( e ){
  e = e || window.event;
  if( !script.readyState || 
  /loaded|complete/.test(script.readyState) ||
  e === 'error'
  ){
   //Restore native document.write
   document.write = docWrite;
   head.removeChild( script );

   //Unmount events and disconnect DOM references
   //Try to avoid memory leaks
   head =    
   parent = 
   elem =
   script = 
   script.onerror = 
   script.onload = 
   script.onreadystatechange = null;
  }
 }

 //Load the script
 head.insertBefore( script, head.firstChild );
};

Four, picture lazy load of enhanced version

Implementation of non-blocking lazy loading javascript advertising code, can be further optimized? If the AD does not appear on the first screen, can it be lazily loaded like the usual lazy loading of pictures? The answer is yes. I wrote before the image lazy loading plug-in extension, the original image loading method (replace SRC) to change the loadScript loading above can be achieved. Of course, just such a modification would be problematic. If there are multiple pictures, and loadScript is carried out at the same time, and document.write is A global method, it is guaranteed that when loading A, it will not affect B, so they must be loaded one by one in order, and B can only be loaded after loading A.

V. queue control

In order for javascript advertising code to load sequentially, you need a queue to control the loading. Here's a simple queue control code:


var loadQueue = [];
//  loaded 
var queue = function( data ){
 loadQueue.push( data );
 if( loadQueue[0] !== 'runing' ){
  dequeue();
 }
};
//Dequeue  
var dequeue = function(){
 var fn = loadQueue.shift();
 if( fn === 'runing' ){
  fn = loadQueue.shift();
 }

 if( fn ){
  loadQueue.unshift( 'runing' );
  fn();
 }
};


Picture lazy loader see biven: (link: #)  


Related articles: