广告代码分析
很多第三方的广告系统都是使用document.write来加载广告,如下面的一个javascript的广告链接。
1 |
<script type="text/javascript" src="http://gg.5173.com/adpolestar/5173/ |
2 |
;ap=2EBE5681_1BA3_4663_FA3F_E73D2B83FBDC;ct=js;pu=5173;/?"></script> |
这个javascript请求返回的是这样的一段代码:
2 |
"ad=6FF3F844_33E6_86EE_3B96_D94C1CF1AEC4;ap=2EBE5681_1BA3_4663_FA3F_E73D2B83FBDC;" + |
5 |
"border='0' width="132px" height="58px" /></a>" ); |
这种看似有点二的加载方式,但是你却没办法改造它,因为它本身就是第三方的。并且代码都添加了统计的功能,上面的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(墙外)方案。
2 |
<textarea style="display:none"> |
3 |
<script type="text/javascript" src="http://gg.5173.com/adpolestar/5173/ |
4 |
;ap=2EBE5681_1BA3_4663_FA3F_E73D2B83FBDC;ct=js;pu=5173;/?"></script> |
延迟加载script并重写document.write,下面是代码实现:
02 |
* 重写document.write实现无阻塞加载script |
03 |
* @param { Dom Object } textarea元素 |
05 |
var loadScript = function( elem ){ |
06 |
var url = elem.value.match( /src="([\s\S]*?)"/i )[1], |
07 |
parent = elem.parentNode, |
08 |
// 缓存原生的document.write |
09 |
docWrite = document.write, |
11 |
script = document.createElement( 'script' ), |
12 |
head = document.head || |
13 |
document.getElementsByTagName( 'head' )[0] || |
14 |
document.documentElement; |
17 |
document.write = function( text ){ |
18 |
parent.innerHTML = text; |
21 |
script.type = 'text/javascript'; |
26 |
script.onreadystatechange = function( e ){ |
27 |
e = e || window.event; |
28 |
if( !script.readyState || |
29 |
/loaded|complete/.test(script.readyState) || |
33 |
// 恢复原生的document.write |
34 |
document.write = docWrite; |
35 |
head.removeChild( script ); |
45 |
script.onreadystatechange = null; |
51 |
head.insertBefore( script, head.firstChild ); |
图片延迟加载的增强版
实现了无阻塞式的延迟加载javascript广告代码,能否进一步优化?如果广告没在首屏出现,能否像通常的图片的延迟加载一样来进行延迟加载?答案是肯定的。对我之前写的图片延迟加载的小插件进行扩展,将原来的图片加载方式(替换src)改成上面的loadScript方式加载就可以实现。当然,仅仅是这样的修改还是会有问题的。如果有多个图片,并且loadScript是同时进行的,而document.write又是全局的方法,保不准在加载A的时候不影响到B,必须让它们一个个的按顺序加载,加载完A之后才能加载B。
队列控制
为了让javascript广告代码按顺序加载就需要一个队列来控制加载。于是又有了下面这段简单的队列控制代码:
03 |
var queue = function( data ){ |
04 |
loadQueue.push( data ); |
05 |
if( loadQueue[0] !== 'runing' ){ |
10 |
var dequeue = function(){ |
11 |
var fn = loadQueue.shift(); |
12 |
if( fn === 'runing' ){ |
13 |
fn = loadQueue.shift(); |
17 |
loadQueue.unshift( 'runing' ); |
图片延迟加载插件的使用说明:http://stylechen.com/imglazyload2.html
图片延迟加载的增强版插件下载地址:http://stylechen.com/wp-content/uploads/download/imglazyload.zip
- 关于JavaScript是否会阻塞图片加载
<?php //1.js.php sleep(5); file_put_contents("tmp.txt", __FILE__.'->'.__LINE__.' -&g ...
- 转:JS线程和JS阻塞页面加载的问题
前几日写了一篇文章,介绍了js阻塞页面加载的问题.当时是通过例子来验证的.今天,我介绍一下浏览器内核,从原理上介绍一下js阻塞页面加载的原因. 浏览器的内核是多线程的,它们在内核制控下相互配合以保持同 ...
- PHP + JavaScript + Ajax 实现无刷新页面加载效果
数据源工厂 Json生成方式1 Json生成方式2 数据搬运工 数据加工师 转换类型 加工展示 结果展示 初始页面 点击按钮之后 总结 今天这个实验的思路就是实现一个无刷新的页面加载效果.具体的思路是 ...
- js 利用canvas + flv.js实现视频流 截屏 、本地下载功能实现,兼容火狐,谷歌;canvas截屏跨域问题,无音频视频流加载不显示问题
项目:物联网监控项目----后台视频流管理(前端实现视频截屏功能) 本文就不同视频源分情况展示: 1 本地视频(项目同目录视频)截屏(canvas.getContext("2d).drawI ...
- jquery的 $(function(){ }) = $(document).ready(function(){ }) ,及页面的加载顺序
document.ready和onload的区别:一.JavaScript文档加载完成事件页面加载完成有两种事件一是ready,表示文档结构已经加载完成(不包含图片等非文字媒体文件) 二.是onloa ...
- php+ajax实现无刷新动态加载数据技术
我们浏览有些网页的时候,当拉动浏览器的滚动条时到页底时,页面会继续自动加载更多内容供用户浏览.这种技术我暂且称它为滚屏加载技术.我们发现很多网站用到这种技术,必应图片搜索.新浪微博.QQ空间等将该技术 ...
- 探真无阻塞加载javascript脚本技术,我们会发现很多意想不到的秘密
下面的图片是我使用firefox和chrome浏览百度首页时候记录的http请求 下面是firefox: 下面是chrome: 在浏览百度首页前我都将浏览器的缓存全部清理掉,让这个场景最接近第一次访问 ...
- 通过分析iframe和无阻塞脚本关系能让我们更懂iframe
在我上篇文章里,我提到一种使用iframe完成无阻塞脚本加载的方式,因为我对iframe的偏见很大,所以上篇文章里我没有展开讨论这个问题. 文章发表后有位网友问了我这样一个问题,下面是他问题的原文,如 ...
- 无阻塞加载和defer、async
无阻塞加载 把js放在head里,浏览器是怎么去执行它的呢,是按顺序加载还是并行加载呢?在旧的浏览器下,都是按照先后顺序来加载的,这就保证了加载的js依赖不会发生问题.但是少部分新的浏览器已经开始允许 ...
随机推荐
- react中iconfont如何使用
一.配置 this.state={ tabs:[ { path:"/home", icon:"\ue628", name:"首页", }, ...
- 清晰详细、可测量、可达到、目标导向、有时间限定,SMART目标定制原则
设定目标的时候需要考虑的问题,可以对已经设定的目标进行完善 S 目标是清晰的,明确的 M 目标可以衡量的,可以用来评估的 A 目标是可以达到的,但是达到的过程有难度 R 目标导向,设定的目标对大目标具 ...
- 【特别篇】不为人知的U盘秘密
U盘是我们代码爱好者的必要东西,方便于我们更好的拷文件,使用一些已经配置好的东西,比如说:小编经常会将linux系统放进去,平时就可以随时用了. But 你的U盘真的正常吗?你了解多少? 关于U盘 ...
- ios 创建sdk与demo同一个工程
思路摘要: 步骤1:创建一个文件夹用来放该项目 步骤2:设置工程工作区间 步骤3: 创建广告sdk项目 步骤4:创建广告sdkDemo项目 步骤5:配置一些文件 步骤6:将sdk导入到demo中进行 ...
- Jmeter 常用函数(12)- 详解 __machineName
如果你想查看更多 Jmeter 常用函数可以在这篇文章找找哦 https://www.cnblogs.com/poloyy/p/13291704.html 作用 返回机器(电脑)名称 语法格式 ${_ ...
- C++ Templates (Part I 基本概念 The Basics)
C++ 模板 (C++ Templates) 目录 C++ 模板 (C++ Templates) 第一部分 基本概念 (The Basics) 第一部分章节目录 参考资料 第一部分 基本概念 (The ...
- Mybatis_day1
mybatis框架的引入: JDBC里面 对功能实现的进一步封装,可以按照以下方式操作 Student s = new Student(id,name); util.save(s); ORM: obj ...
- Linux环境下没有权限操作文件或目录
linux下有超级用户(root)和普通用户,普通用户不能直接操作没有权限的目录,如果出现了没有权限的提示,可以尝试用su命令解决. 比如: #mkdir aaa 我要创建一个aaa的文件夹,没有操作 ...
- Solon详解(五)- Solon扩展机制之Solon Plugin
Solon 中也有一种非常解耦的扩展机制:Solon Plugin.这种扩展机制和Spring Factories很像,和SPI也很像. 一.Solon 中的扩展机制 在Solon的扩展插件加载机制, ...
- parallel stream-不能随便使用
前言 java8除了新增stream,还提供了parallel stream-多线程版的stream,parallel stream的优势是:充分利用多线程,提高程序运行效率,但是正确的使用并不简单, ...