1. Advertising code analysis
Many third-party advertising systems use document.write to load ads, such as the following javascript advertising link.
This javascript request returns a piece of code like this:
This seems to be a bit of a second-party loading method, but you can't modify it because it is third-party itself. And the code has added statistics function. The above javascript advertising link will be counted every time it is requested. The generated code also has the function of click statistics, which means it must be loaded in this way.
Document.write is performed synchronously when the page is rendered. You must wait for the javascript code to be downloaded and document.write to be executed before rendering the subsequent content. If there are many advertisements, it will cause the page to be blocked, especially If you insert several advertisements with relatively large image sizes on the first screen of the page, the blocking situation will be quite obvious and serious, which will make users think that your webpage is very slow.
2. Rewrite document.write
In order to avoid blocking, the document.write method cannot be executed when the page is rendered. You must find a way to make the javascript advertising code execute after the DOM tree is ready (DOM ready), but execute the document after the DOM tree is ready. write will re-render the entire page, which is not possible. Although document.write is a native browser method, you can also customize a method to override the original method. Before the JavaScript ad code is loaded, rewrite document.write, and then change it back after it is loaded and executed.
3. Delay loading of javascript code
The most critical step above is lazy loading of javascript code. How to implement it? First try to rewrite the script's type attribute, such as setting type to a custom attribute "type/cache", but most browsers (Chrome will not download it) will still download this code, but will not execute it. Downloading such a piece of code will still be blocked when the page is rendered. Real delayed loading cannot be achieved by rewriting the script type. At most, it can only load without executing, and there are still compatibility issues.
Put the script tag into the textarea tag, and then read the textarea content when it needs to be loaded. This can achieve real delayed loading of scripts. This method is thanks to the BigRender (outside the wall) solution proposed by Yubo.
Lazy load the script and rewrite document.write. The following is the code implementation:
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'
){
// 恢复原生的document.write
document.write = docWrite;
head.removeChild( script );
// 卸载事件和断开DOM的引用
// 尽量避免内存泄漏
head =
parent =
elem =
script =
script.onerror =
script.onload =
script.onreadystatechange = null;
}
}
// 加载script
head.insertBefore( script, head.firstChild );
};
四、图片延迟加载的增强版
实现了无阻塞式的延迟加载javascript广告代码,能否进一步优化?如果广告没在首屏出现,能否像通常的图片的延迟加载一样来进行延迟加载?答案是肯定的。对我之前写的图片延迟加载的小插件进行扩展,将原来的图片加载方式(替换src)改成上面的loadScript方式加载就可以实现。当然,仅仅是这样的修改还是会有问题的。如果有多个图片,并且loadScript是同时进行的,而document.write又是全局的方法,保不准在加载A的时候不影响到B,必须让它们一个个的按顺序加载,加载完A之后才能加载B。
五、队列控制
为了让javascript广告代码按顺序加载就需要一个队列来控制加载。于是又有了下面这段简单的队列控制代码: