SlideShare a Scribd company logo
Lazyload实践口碑网吴天豪
Introduce 吴天豪口碑网-UED-前端开发工程师大三爱折腾博客: www.f2es.com
关于交流会主动分享分享没有大小一个困扰你很久的问题一个五分钟的小发现一个好的提高开发效率的工具一份好的开发经验
Lazyload直译:惰性加载一般我们都会叫它做“延迟加载”http://en.wikipedia.org/wiki/Lazy_loading
http://docs.kissyui.com/kissy/docs/datalazyload/index.htmlhttp://www.appelsiini.net/projects/lazyloadhttp://developer.yahoo.com/yui/imageloader/
Why lazyloadStart soonerStop waiting
一般我们会用于加载js加载html块
延迟加载jshttp://book.douban.com/subject/5362856/http://book.douban.com/subject/4719162/
Total_Speed = Time_to_Download + Time_to_parse + Time_to_execute(evaluation)
Js-其实是一个老话题了为什么要延迟加载js当浏览器下载执行js时,页面的下载和渲染处于等待状态为什么停滞?大家思考一下1.当页面一边渲染html和css,一边下载并执行脚本,what will happen?脚本操作的元素可能根本就还没有渲染出来
如果我们的脚本放在页面的顶部,比如head里面,或者把脚本在页面中间,页面会等待脚本下载和执行这在页面生存周期中是必要的,因为脚本执行过程中可能会修改页面内容
组织脚本脚本放到页面底部合并URL (minify)因为http请求会带来额外的性能消耗,因此下载单个100k的文件比下载4个25k的文件要快。无阻塞的脚本异步加载js文件
动态加载脚本方式:XHR动态脚本DeferAsync…….
文件之间的依赖关系执行顺序并行下载
介绍一个比较少见的方式Script in iframe页面中的iframe和其他元素是并行加载的,这样就可以无阻塞的加载script脚本存在跨域问题
动态脚本能很好的处理脚本之间的依赖关系
监听js是否加载并准备就绪Firefox,Opera,Chrome,Safari 3+script.onloadiescript.readystatechangescript.readyState  === “loaded”  script.readyState === “complete”
LoadScript(“jQuery.js”, function(){	$(function(){		//jQuery code	}; }
不过…文件一多…loadScript(“a.js”, function(){loadScript(“b.js”, function(){loadScript(“c.js”, function(){loadScript(“d.js”, function(){				alert(“哎呀我擦,终于加载好了”);			}		}	}}
这样看起来就舒服多了Load([“a.js”, “b.js”, “c.js”, “d.js”] , function(){	//do something });
这样就更好了Load(“d.js”, function(){	//do something})“d.js” 依赖于[“a.js”, “b.js”, “c.js”]
豆瓣dohttp://site.douban.com/widget/notes/22456/note/87598595/
n.onload = n.onreadystatechange = function () {    if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') {        _loaded[this.getAttribute('src')] = true;        if (cb) {cb(this.getAttribute('src'), context);        }        //防止ie6的内存泄漏问题n.onload = n.onreadystatechange = null;    }};
加载单个文件的处理。接受五个参数:url, type(文件类型), charset(编码), cb(要对应执行的方法), context(执行上下文环境)
Do.add('common', {path: 'http://img3.douban.com/js/site/packed_common0.js', type: 'js'});Do.add('common-eventhandler', {path: 'http://img3.douban.com/js/site/packed_common_eventhandler0.js', type: 'js', requires: ['common']});Do('common', 'common-eventhandler');
问题依然存在:下载a.js -> 执行a.js回调 -> 下载b.js -> 执行b.js的回调-> 下载c.js -> 执行c.js的回调-> 下载d.js -> 执行d.js的回调不能做到并行下载….
在chrome和safari里,通过动态script加载的脚本并不会按照插入的顺序执行,而是哪个先加载好哪个执行That’s pretty bad!
那么在chrome/safari里,可以插入一个<script type=“text/cache” src=“#”>来实现,type=“text/cache”的脚本下载好后会缓存并触发onload,但不会执行。之后再插入script type=“text/javascript”,因为这个时候脚本都已经下载好,所以插入的顺序就是执行的顺序了
模块化和组件化Css
多一次插入就多浪费一次资源使用这个方法实属无奈
模块化和组件化Css
最后,统一的解决方案同域文件用xmlhttprequest请求过来这时,脚本是以字符串的形式传递过来的var s = document.createElement('script'); s.text = xhrObj.responseText;head.appendChild(s);
这种方法避开了evil eval,并且和DOM Script一样,可以按顺序加载js文件,当然,不会阻塞后续资源的加载。更为重要的是,在所有浏览器下,这种方法都不会阻止渲染和onload事件,体现了XMLHTTPRequest异步请求的本色。
跨域的脚本Firefox/opera里可以用动态 Script DOM element ,完美地实现并行下载和顺序执行对于 Safari/Chrome/IE ,无法保证顺序执行,通过插入一个 <script type=“text/cache” src=“#”> 来实现。
defer和async的区别Defer 延迟Async异步
关于defer<script src=" " defer></script>加上 defer 等于在页面完全在入后再执行脚本,相当于 window.onload,但应用上比 window.onload更灵活告诉浏览器这段脚本不需要立即执行,从而做到异步加载,不阻塞其他资源下载在window.onload处理之前执行defer的脚本
Defer的水很深…http://msdn.microsoft.com/en-us/library/ms533719(VS.85).aspxhttps://developer.mozilla.org/En/HTML/Element/Script#attr-defer都没有涉及执行顺序的问题…
defer在ie下能保持执行顺序,无论哪个先下载好---《高性能网站建设进阶指南》35页测试结果很怪异…http://www.websiteoptimization.com/speed/tweak/defer/动态插入的脚本,即使设置defer,依然不能保证执行顺序
<head><script defer>  	 alert(3);</script><script> 	 alert(1);</script></head><body><script defer>  	 alert(4);</script><script> 	 alert(2);</script><script>window.onload = function(){  	  alert(5);  }</script></body>http://stevesouders.com/cuzillion/?ex=10017&title=IE+Ensure+Order+Excution
Html5 asyncThis Boolean attribute is set to indicate that the browser should, if possible, execute the script asynchronously. If the script cannot be executed asynchronously, or the browser doesn’t support this attribute, the script is executed synchronously (and loading the content blocks until the script finishes running).加了这个属性就意味这该脚本的执行不会影响页面的加载
区别
回到根源Reduce(减少文件大小)Defer(延迟)Go Async(异步)Be Lazy(懒加载)Bite Size(真的需要 JS 吗)
更好的了解script标签https://developer.mozilla.org/En/HTML/Element/Scripthttp://msdn.microsoft.com/en-us/library/ms535892(VS.85).aspx
Html lazyload对html片段进行延迟加载极大地减少页面渲染时间同时解决了图片加载的问题
实践Sina微博Twitter淘宝商城等等
思路1.正常渲染一屏多一点大小的页面2.把剩下的html代码放到一个容器中,这时不会解析,以文本的形式存在3.随着用户进行的页面滚动操作逐步渲染页面4.为开发人员提供相应操作的接口
1.容器的选择textareanoscript你会选择哪个?
容器要求内部的元素全部以文本或者文本节点的形式解析可以可判断位置访问内部的文本
Textarea应用:淘宝商城其实,挺好,貌似没有什么大问题,我们需要的基本功能都已经实现了
noscript在开启脚本的情况下,元素本身可以获取,但是不含占位属性,比如offsetTop,offsetLeft,或者height,width之类的在IE789下,内部的文本节点是不可访问的或者说在浏览器在开启脚本的情况下渲染好之后就把内部的文本删除了,No dom, no data
看起来textarea对noscript有着压倒性的优势
是么?
你希望那些不开启脚本的用户就没法使用你的产品了么?
在口碑网上一次调查时,不开启脚本的访问用户占0.5%到1%,不是一个小数目
页面的优化和可用性不应该是两个不同的走向
noscript解决方案对于noscript的占位属性丢失获取到noscript元素,并在外层套一个textarea元素,textarea元素用visibility:hidden隐藏为什么不用display:none?之后,判断noscript元素是否在视口内的任务就顺利移交给了textarea为什么不用别的元素?比如div之类的这里就涉及到了文本转义的问题
noscript解决方案对于IE789对noscript内部元素的处理感谢stackoverflow,有位老兄也在研究这个问题使用iframe来引入noscript元素,然后用ajax动态请求iframe的html代码,因为这部分代码实际上已经在用户浏览的页面上了拿到完整的html之后用正则把每个noscript内部的文本切割到一个数组里
<iframe class="k2-display-none" src="?noscript=true"></iframe>我们可以这样发一个请求Y.io("?noscript=true", cfg);o.responseText就是含有当前页面noscript标签的html字符串
坚持noscript为了提高页面的可访问性
还有问题开发人员的脚本和一些元素有依赖关系如果元素没有加载就执行脚本会导致脚本报错让开发人员在每次获取元素之前都先判断元素是否存在不靠谱,并且脚本并不能直接知道元素到底加载好了米
把脚本的初始化放到对应的html块里?好处,脚本会随着元素的加载执行好吧,这让页面的维护变的非常困难,脚本东一段西一段的
自定义事件我们创建一个自定义事件,这个事件的目的就是在某个html块加载好的时候发出一个广播,让脚本知道所要操作的元素已经加载好。脚本绑定这个事件。
自定义事件Y. publish(evt_type, opts)在Y.EventTarget. _yuievt.events里存储Y. fire( evt_type )触发绑定的回调事件队列
再具体一点添加自定义事件Y.pulish("lazyloadReady:" + i, {          type : "lazyloadReady:" + i,          preventable : false});
触发事件ev = "lazyloadReady:" + (i + 1);Y.fire(ev);
绑定事件Y.on("lazyloadReady:1" , function(){     alert("第一个模块加载完成");});暂时使用了页面上noscript标签的序号作为事件名…还在考虑更好的方法
创建iframe元素带来的开销是其他元素的1~2数量级频繁的字符串操作,性能上有待提高…
看看kissy怎么做的dataLazyload.addCallback(el, fn) 表示当 el 即将出现时,触发 fn具体实现我觉得应该是类似的,有兴趣的可以看看源代码的实现
QA
谢谢

More Related Content

PDF
Node.js 入門 - 前端工程開發實務訓練
PPTX
从无阻塞并行脚本加载(Lab.js)到浏览器消息模型
PPT
从无阻塞并行脚本加载(Lab.js)到浏览器消息模型
PDF
Windows 8.1 app 研習營三小時
PPTX
Img lazy-load
PDF
前端工程師與室內裝修師傅的相似之處-twMVC#16
PDF
輕鬆上手Asp.net web api 2.1-twMVC#14
PDF
从无阻塞并行脚本加载(Lab.js)到浏览器消息模型
Node.js 入門 - 前端工程開發實務訓練
从无阻塞并行脚本加载(Lab.js)到浏览器消息模型
从无阻塞并行脚本加载(Lab.js)到浏览器消息模型
Windows 8.1 app 研習營三小時
Img lazy-load
前端工程師與室內裝修師傅的相似之處-twMVC#16
輕鬆上手Asp.net web api 2.1-twMVC#14
从无阻塞并行脚本加载(Lab.js)到浏览器消息模型

What's hot (19)

PDF
跟著 geerlingguy 大神
一起測試 Ansible Roles
PDF
開發的效能與效率-twMVC#15
PDF
twMVC#21 | 你所不知道的 Visual Studio
PPTX
MVC實戰分享 分頁與排序相關技巧-tw mvc#13
PDF
twMVC#33聊聊如何自建 Facebook {廣告} 服務 with API
PPT
Javascript stacktrace
PDF
twMVC#23 | 一個Mobile App開發、維護與改版的愛恨之路
PDF
Continuous Delivery Workshop with Ansible x GitLab CI (5th)
PDF
twMVC#29 -Learning Machine Learning with Movie Recommendation
PDF
twMVC#20 | ASP.NET MVC View 開發技巧小錦囊
PDF
MakerBoard: MT7688 Emulator
PDF
Java script 全面逆襲!使用 node.js 打造桌面環境!
PDF
twMVC#19 | 微信公眾平台申請與wechat api 開發血淚史
PDF
App house
PDF
HTML5 Web workers
PDF
twMVC#24 | 開發團隊的敏捷之路(未完成)
PPTX
twMVC#31網站上線了然後呢
PDF
專案分層架構 twMVC#18
PPTX
ASP.NET MVC 善用網路資源快速完打造網站
跟著 geerlingguy 大神
一起測試 Ansible Roles
開發的效能與效率-twMVC#15
twMVC#21 | 你所不知道的 Visual Studio
MVC實戰分享 分頁與排序相關技巧-tw mvc#13
twMVC#33聊聊如何自建 Facebook {廣告} 服務 with API
Javascript stacktrace
twMVC#23 | 一個Mobile App開發、維護與改版的愛恨之路
Continuous Delivery Workshop with Ansible x GitLab CI (5th)
twMVC#29 -Learning Machine Learning with Movie Recommendation
twMVC#20 | ASP.NET MVC View 開發技巧小錦囊
MakerBoard: MT7688 Emulator
Java script 全面逆襲!使用 node.js 打造桌面環境!
twMVC#19 | 微信公眾平台申請與wechat api 開發血淚史
App house
HTML5 Web workers
twMVC#24 | 開發團隊的敏捷之路(未完成)
twMVC#31網站上線了然後呢
專案分層架構 twMVC#18
ASP.NET MVC 善用網路資源快速完打造網站
Ad

Viewers also liked (14)

PPTX
Sara's presentation (3)
PPTX
Technology K- 12 in the classroom
PPTX
前端基础知识回顾
PPTX
Music video presentation
PPTX
Lazyload实践
PPS
Pps ghiray 11 09 10
PPTX
Wasting energy
PPS
Noti ghiray
PDF
Game live broadcast
PPS
Pps ghiray 01 10 10
PDF
MDB Firm Overview
PDF
새로운 앱 수익 모델과 광고
DOCX
Affordable House and lot for sale Alexandra (Murang bahay at Lupa)
DOCX
Affordable House and lot For Sale Montefaro (Murang Bahay at LUpa)
Sara's presentation (3)
Technology K- 12 in the classroom
前端基础知识回顾
Music video presentation
Lazyload实践
Pps ghiray 11 09 10
Wasting energy
Noti ghiray
Game live broadcast
Pps ghiray 01 10 10
MDB Firm Overview
새로운 앱 수익 모델과 광고
Affordable House and lot for sale Alexandra (Murang bahay at Lupa)
Affordable House and lot For Sale Montefaro (Murang Bahay at LUpa)
Ad

Similar to 模块化和组件化Css (20)

PDF
拆分初始化负载
PDF
2012 java two-desktop-appliction-using-j-ruby-with-swt
 
PDF
Proud Plone on Cloud
PDF
NodeJS基礎教學&簡介
PPT
高性能网站最佳实践
PPTX
Docker Compose
PDF
Presta shop 1.6 详细安装指南
PDF
Performance 入門 - 前端工程開發實務訓練
PPTX
如何利用 www.webpagetest.org 進行網頁效能分析與改進建議 (真實案例)
PPTX
Phalcon2014 Startup
PPT
Html5
PPT
互联网创业服务器运维工具集
PPTX
广告前端代码优化
PPT
Flash ria usability 刘轩飞
PPT
Flash RIA Usability
PDF
Flutter實作概述 | GDSC NYCU
PPTX
Inline Script
PDF
Php可调试团队开发环境配置
PDF
Php可调试团队开发环境配置
PPTX
张所勇:前端开发工具推荐
拆分初始化负载
2012 java two-desktop-appliction-using-j-ruby-with-swt
 
Proud Plone on Cloud
NodeJS基礎教學&簡介
高性能网站最佳实践
Docker Compose
Presta shop 1.6 详细安装指南
Performance 入門 - 前端工程開發實務訓練
如何利用 www.webpagetest.org 進行網頁效能分析與改進建議 (真實案例)
Phalcon2014 Startup
Html5
互联网创业服务器运维工具集
广告前端代码优化
Flash ria usability 刘轩飞
Flash RIA Usability
Flutter實作概述 | GDSC NYCU
Inline Script
Php可调试团队开发环境配置
Php可调试团队开发环境配置
张所勇:前端开发工具推荐

模块化和组件化Css