百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

用js的document.write输出的广告无阻塞加载的方法

zhezhongyun 2025-02-27 17:36 65 浏览

一、广告代码分析
很多第三方地广告系统都是使用document.write来加载广告,如下面地一个javascript地广告链接.

代码如下:

这个javascript请求返回地是这样地一段代码:

代码如下:

document.write(  );

这种看似有点二地加载方式,但是你却没办法改造它,因为它本身就是第三方地.并且代码都添加了统计地功能,上面地javascript地广告链接每请求一次都会统计一次,生成地代码也有点击统计地功能,也就是说必须以这种方式来进行加载.

document.write是在页面渲染地时候同步进行地,必须要等javascript代码下载好并且document.write执行完后才接着渲染后面地内容,如果广告比较多地话,就会导致页面阻塞,尤其是在页面地首屏插好几个图片尺寸比较大地这种广告,那么阻塞情况就相当明显和严重,会让用户觉的你这个网页很慢.
二、重写document.write
为了避免阻塞,就不能让document.write方法在页面渲染地时候执行,必须想办法让javascript地广告代码在dom树就绪(dom ready)之后才执行,但是在dom树就绪后执行document.write会重新渲染整个页面,这样也是不行地.document.write虽然是浏览器原生地方法,但是也可以自定义一个方法来覆盖掉原来地方法.在javascript广告代码加载之前,重写document.write,等加载并执行完再改回来.
三、延迟加载javascript代码
上面比较关键地一步,延迟加载javascript代码,如何实现呢?先尝试通过改写script地type属性,比如将type设置成一个自定义地属性”type/cache”,但这样大部分浏览器(chrome不会下载)仍然会下载这段代码,但不会执行,在页面渲染地时候下载这么一段代码仍然会阻塞,通过改写script地type并不能实现真正地延迟加载,最多能实现只加载不执行,而且还存在兼容问题.

将script标签放到textarea标签中,等需要加载地时候再读取textarea地内容,这样可以实现真正地延迟加载script,这个方法要感谢玉伯提出地bigrender(墙外)方案.

代码如下:

延迟加载script并重写document.write,下面是代码实现:

代码如下:

/**
 \* 重写document.write实现无阻塞加载script
 \* @param { dom object } textarea元素
 */
var loadscript = function( elem ){
 var url = elem.value.match( /src=([\s\s]*?)/i )[1],
 parent = elem.parentnode,
 // 缓存原生地document.write
 docwrite = document.write, 
 // 创建一个新script来加载
 script = document.createelement( 'script' ), 
 head = document.head || 
  document.getelementsbytagname( 'head' )[0] || 
  document.documentelement;
 // 重写document.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'
 ){
  // 恢复原生地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广告代码按顺序加载就需要一个队列来控制加载.于是又有了下面这段简单地队列控制代码:
代码如下:

var loadqueue = [];
// 入列
var queue = function( data ){
 loadqueue.push( data );
 if( loadqueue[0] !== 'runing' ){
 dequeue();
 }
};
// 出列 
var dequeue = function(){
 var fn = loadqueue.shift();
 if( fn === 'runing' ){
 fn = loadqueue.shift();
 }
 if( fn ){
 loadqueue.unshift( 'runing' );
 fn();
 }
};

相关推荐

perl基础——循环控制_principle循环

在编程中,我们往往需要进行不同情况的判断,选择,重复操作。这些时候我们需要对简单语句来添加循环控制变量或者命令。if/unless我们需要在满足特定条件下再执行的语句,可以通过if/unle...

CHAPTER 2 The Antechamber of M de Treville 第二章 特雷维尔先生的前厅

CHAPTER1TheThreePresentsofD'ArtagnantheElderCHAPTER2TheAntechamber...

CHAPTER 5 The King'S Musketeers and the Cardinal'S Guards 第五章 国王的火枪手和红衣主教的卫士

CHAPTER3TheAudienceCHAPTER5TheKing'SMusketeersandtheCardinal'SGuard...

CHAPTER 3 The Audience 第三章 接见

CHAPTER3TheAudienceCHAPTER3TheAudience第三章接见M.DeTrévillewasatt...

别搞印象流!数据说明谁才是外线防守第一人!

来源:Reddit译者:@assholeeric编辑:伯伦WhoarethebestperimeterdefendersintheNBA?Here'sagraphofStea...

V-Day commemorations prove anti-China claims hollow

People'sLiberationArmyhonorguardstakepartinthemilitaryparademarkingthe80thanniversary...

EasyPoi使用_easypoi api

EasyPoi的主要特点:1.设计精巧,使用简单2.接口丰富,扩展简单3.默认值多,writelessdomore4.springmvc支持,web导出可以简单明了使用1.easypoi...

关于Oracle数据库12c 新特性总结_oracle数据库12514

概述今天主要简单介绍一下Oracle12c的一些新特性,仅供参考。参考:http://docs.oracle.com/database/121/NEWFT/chapter12102.htm#NEWFT...

【开发者成长】JAVA 线上故障排查完整套路!

线上故障主要会包括CPU、磁盘、内存以及网络问题,而大多数故障可能会包含不止一个层面的问题,所以进行排查时候尽量四个方面依次排查一遍。同时例如jstack、jmap等工具也是不囿于一个方面的问题...

使用 Python 向多个地址发送电子邮件

在本文中,我们将演示如何使用Python编程语言向使用不同电子邮件地址的不同收件人发送电子邮件。具体来说,我们将向许多不同的人发送电子邮件。使用Python向多个地址发送电子邮件Python...

提高工作效率的--Linux常用命令,能够决解95%以上的问题

点击上方关注,第一时间接受干货转发,点赞,收藏,不如一次关注评论区第一条注意查看回复:Linux命令获取linux常用命令大全pdf+Linux命令行大全pdf为什么要学习Linux命令?1、因为Li...

linux常用系统命令_linux操作系统常用命令

系统信息arch显示机器的处理器架构dmidecode-q显示硬件系统部件-(SMBIOS/DMI)hdparm-i/dev/hda罗列一个磁盘的架构特性hdparm-tT/dev/s...

小白入门必知必会-PostgreSQL-15.2源码编译安装

一PostgreSQL编译安装1.1下载源码包在PostgreSQL官方主页https://www.postgresql.org/ftp/source/下载区选择所需格式的源码包下载。cd/we...

Linux操作系统之常用命令_linux系统常用命令详解

Linux操作系统一、常用命令1.系统(1)系统信息arch显示机器的处理器架构uname-m显示机器的处理器架构uname-r显示正在使用的内核版本dmidecode-q显示硬件系...

linux网络命名空间简介_linux 网络相关命令

此篇会以例子的方式介绍下linux网络命名空间。此例中会创建两个networknamespace:nsa、nsb,一个网桥bridge0,nsa、nsb中添加网络设备veth,网络设备间...