Rewrite document. write to load js advertisement (Supplement) without blocking, document. writejs
Loading javascript without blocking has a great effect on page performance optimization, which can effectively reduce the blocking of page loading by js. Especially for some advertisement js files, because the advertisement content may be rich media, it is likely to become the bottleneck for your page loading speed. High-Performance javascript tells us that you can speed up your webpage, load JS without interruption.
Then the code appears.
(function() {var s = document.createElement('script');s.type = 'text/javascript';s.async = true;s.src = 'http://yourdomain.com/script.js';var x = document.getElementsByTagName('script')[0];x.parentNode.insertBefore(s, x);})();
Everyone is familiar with the above. Anyone who has read books knows the benefits of non-blocking loading. The results are quite good, when such a non-blocking script encounters a general js advertisement, a write problem occurs-the advertisement code appears in HTML but does not display the advertisement.
Nana? HTML is not rendered to the page?
First look at the js Code of the advertisement
Copy codeThe Code is as follows:
Document. write (' ');
The code is quite simple. The document. write outputs the HTML code (I believe many advertisers use this for their ads). What is the problem with the advertisement not displayed on the page? The problem lies in document. write. Why? First w3schools to see the definition of document. write is very useful.
Definition and usage
The write () method can write HTML expressions or JavaScript code to a document.
Multiple parameters (exp1, exp2, exp3,...) can be listed, and they will be appended to the document in order.
Method:
One is to use this method to output HTML in the document, and the other is to generate a new document in the window and framework outside the window that calls this method. In the second case, you must use the close () method to close the document.
However, it is executed in the page stream input process. Once the page is loaded, the document is called again. write (), which implicitly calls document. open () to erase the current document and start a new document. That is to say, if we use document. write after loading HTML, the html will be generated before it is deleted, and the output content of document. write will be displayed.
In our example, document. write is output in html after the page is loaded, and it will not be executed. I know the problem and the principle. How can I solve this problem?
Asynchronous use of ajax, line is different, many ad files are third-party, there are cross-origin problems under different domain names, and we cannot control the output of their code. In this case, we thought of a way to overwrite document. write and rewrite document. write after loading the js file. Check the code.
The first version does not block loading js ads:
function LoadADScript(url, container, callback){ this.dw = document.write; this.url = url; this.containerObj = (typeof container == 'string'?document.getElementById(container):container); this.callback = callback || function(){}; } LoadADScript.prototype = { startLoad: function(){ var script = document.createElement('script'), _this = this; if(script.readyState){ //IE script.onreadystatechange = function(){ if (script.readyState == "loaded" || script.readyState == "complete"){ script.onreadystatechange = null; _this.finished(); } }; }else{ //Other script.onload = function(){ _this.finished(); }; } document.write = function(ad){ var html = _this.containerObj.innerHTML; _this.containerObj.innerHTML = html + ad; } script.src = _this.url; script.type = 'text/javascript'; document.getElementsByTagName('head')[0].appendChild(script); }, finished: function(){ document.write = this.dw; this.callback.apply(); } };
Page call code:
var loadScript = new LoadADScript('ad.js','msat-adwrap',function(){ console.log('msat-adwrap'); }); loadScript.startLoad(); var loadScript = new LoadADScript('ad2.js','msat-adwrap',function(){ console.log('msat-adwrap2'); }); loadScript.startLoad(); var loadScript = new LoadADScript('ad3.js','msat-adwrap',function(){ console.log('msat-adwrap3'); }); loadScript.startLoad();
Advertisement js Code
//ad.jsdocument.write('');//ad2.jsdocument.write('');//ad3.jsdocument.write('');
The problem with the first version is that when multiple files are called, some problems may occur:
1. Because the file loading speed is different, some files may be loaded first and then unordered. What we need in many cases is ordered. For example, we need to first load the advertisement on the first screen.
2. You need to set parameters for some advertisements, such as google adsense.
In order to solve these two problems, we can further modify it to eventually load the js version without blocking.
HTML page code:
<!DOCTYPE html>
Loadscript. js source code
/*** Load the advertisement without blocking ** @ author Arain. yu */var loadScript = (function () {var adQueue = [], dw = document. write; // cache the js document. write function LoadADScript (url, container, init, callback) {this. url = url; this. containerObj = (typeof container = 'string '? Document. getElementById (container): container); this. init = init | function () {}; this. callback = callback | function () {};} LoadADScript. prototype = {startLoad: function () {var script = document. createElement ('script'), _ this = this; _ this. init. apply (); if (script. readyState) {// IE script. onreadystatechange = function () {if (script. readyState = "loaded" | script. readyState = "complete") {Script. onreadystatechange = null; _ this. startNext () ;};} else {// Other script. onload = function () {_ this. startNext () ;};}// rewrite document. write document. write = function (ad) {var html = _ this. containerObj. innerHTML; _ this. containerObj. innerHTML = html + ad;} script. src = _ this. url; script. type = 'text/javascript '; document. getElementsByTagName ('head') [0]. appendChild (script) ;}, finished: Function () {// restore document. write document. write = this. dw;}, startNext: function () {adQueue. shift (); this. callback. apply (); if (adQueue. length> 0) {adQueue [0]. startLoad ();} else {this. finished () ;}}; return {add: function (adObj) {if (! AdObj) return; adQueue. push (new LoadADScript (adObj. url, adObj. container, adObj. init, adObj. callback); return this;}, execute: function () {if (adQueue. length> 0) {adQueue [0]. startLoad ();}}};}());