转载请说明出处  http://blog.csdn.net/typename/article/details/38358765  powered  by miechal zhao. 

背景:

       Link Prefetching  是 HTML 5的一个标准, 最早是由Mozilla 发布的一个互联网标准草案,link prefetching 现在是 W3C和WHATWG关于HTML 5中的一部分。网页可以嵌入 prefetching 标记,当浏览器加载完当前页面即结束加载网页,在浏览器闲置的时候会触发prefetching 标记的link,浏览器会在后台静默prefeching指定的documents, 并存储在cache中。 当用户访问到prefetched  documents时, cache中的内容会迅速被使用,加速网页展现。

触发Prefetch 语法:

 prefetch cmcm 

HTTP link 语法:
Link: ; rel=prefetch

HTML meta tag:   具体格式制定在 RFC 5988 Section 5

浏览器如何Prefetching & Web Developer Prefetching时机:

       前面提到过浏览器会在闲置的时机进行prefetching,Firefox在Mosilla1.2中使用nsIWebProgressListener API,我们可以注册顶层的nsIWebProgress 对象,通过这个我们可以接收到document start & stop 通知,我们可以取上次stop的document和下次document start 的近视闲置值作为一段时间间隔. 当onLoad 触发处理顶层document 时基本会触发上一次document stop通知, 这是我们开始prefetch 请求时机。 如果一个subframe 包含prefetching 标记,浏览器prefetching 不会立即开始而是直到top-most frame 及其所有的子frame 完成加载才会被触发。     prefetching 是否适合你的站点取决于yourself.下面有几个建议: (1).当一些列的页面只是slideshow,加载前后1-3个页面(前提是这些页面并不是大页面) (2).在整个网站至始至终预加载大多数图片 (3).prefetching 你网站的搜索结果页

下面我们一起来看一下我们困惑的场景:

1.当用户点击一个正在Prefetching的link 浏览器是如何做处理的?       当用户点击或者初始化页面加载, link prefetching 会停止并且所有的prefetch的操作会被丢弃。如果已经prefetch        document 是下载的一部分,那这部分document会被存储在cache中提供给服务器发送一个“Accept-Ranges:bytes"请     求报头使用。这个请求报头会被webservers在触发静态内容生成。当用户实时访问一个已经prefetched document,保   留部分 document 会被使用 HTTP byte-range 请求提取。 2.当用户在后台下载时,link prefetching 会抢带宽吗?      yes and no. 如果你使用Mozilla浏览器下载, link prefetching 会被delayed直到后台所有下载完成。举例来说:你打  开几个tab加载网页包含prefetching标记,Mozilla会等待所有tab的页面加载完成后才会记性prefetch 请求。当你使用其  他  应用程序使用带宽,那么 prefetch会和其他应用程序竞争。这是个问题浏览器会有待改进,这里我们自己浏览器也  会进  行相应改进,比如在网络闲置情况下才进行prefetch。

使用prefetch的限制与开关:

1. 只有http,https才能使用prefetch, ftp协议不支持prefetch。 2. 只有html的 link标签支持 prefetch , 等其他标签不支持。 3. 你可以通过js代码关闭prefetch 
user_pref("network.prefetch", false);
但是有个问题是目前虽然提供这个选项,但是大多数浏览器对这个选项支持是有问题的,换句话说即使开启这个选项,也有可能prefetching。 4.测试你的浏览器是否支持prefetching Test Prefetching

Link Prefetching 性能测试

测试环境: 小米2: CM Browser Android 4.1.1系统
site/page load time enable Prefetching none prefetching improve(%)
www.cmcm.com 6367 9470 35%
www.taobao.com 871 1112 13%

08-03 17:18:41.299: E/Timer(20970): pageStarted   http://www.cmcm.com/08-03 17:18:41.399: E/Timer(20970): pageFinished  http://www.cmcm.com/08-03 17:18:41.419: E/Timer(20970): pageStarted   http://www.cmcm.com/en-us/08-03 17:18:47.675: E/Timer(20970): pageFinished  http://www.cmcm.com/en-us/636708-03 17:20:07.631: E/Timer(21417): pageStarted   http://www.cmcm.com/08-03 17:20:08.862: E/Timer(21417): pageFinished  http://www.cmcm.com/08-03 17:20:08.882: E/Timer(21417): pageStarted   http://www.cmcm.com/en-us/08-03 17:20:17.371: E/Timer(21417): pageFinished  http://www.cmcm.com/en-us/9740-----------------------------------------------------------------------------------------------08-03 20:57:55.765: E/Timer(26875): pageStarted   http://www.taobao.com/08-03 20:57:55.805: E/Timer(26875): pageStarted   http://m.taobao.com/?sprefer=sypc0008-03 20:57:56.877: E/Timer(26875): pageFinished  http://m.taobao.com/?sprefer=sypc00111208-03 21:00:45.817: E/Timer(27666): pageStarted   http://www.taobao.com/08-03 21:00:45.867: E/Timer(27666): pageStarted   http://m.taobao.com/?sprefer=sypc0008-03 21:00:46.688: E/Timer(27666): pageFinished  http://m.taobao.com/?sprefer=sypc00871

通过我们自己的浏览器测试开启prefetching可以提高显著提高页面的加载速度。

Link Prefetching 在Webkit中实现

在webkit中通过宏LINK_PREFETCH来控制是否支持这个选项。如果我们使用webkit内核不需要这项功能,我们可以通过这个宏disable link prefetch, 这个宏的位置是在 webKit/Source/JavaScriptCore/wtf/Platform.h:#define ENABLE_LINK_PREFETCH 1 下面我们一起看一下link prefetch在webkit当中涉及模块有哪些. (1).webkit 中的HTML parser (2).webkit 中的loader Prefetch parser/loader 实现交互图如下:
void HTMLLinkElement::parseMappedAttribute(Attribute* attr){    if (attr->name() == relAttr) {        tokenizeRelAttribute(attr->value(), m_relAttribute);        process();    } else if (attr->name() == hrefAttr) {        m_url = document()->completeURL(stripLeadingAndTrailingHTMLSpaces(attr->value()));        process();    } else if (attr->name() == typeAttr) {        m_type = attr->value();        process();    } else if (attr->name() == mediaAttr) {        m_media = attr->value().string().lower();        process();    } else if (attr->name() == disabledAttr)        setDisabledState(!attr->isNull());    else if (attr->name() == onbeforeloadAttr)        setAttributeEventListener(eventNames().beforeloadEvent, createAttributeEventListener(this, attr));#if ENABLE(LINK_PREFETCH)    else if (attr->name() == onloadAttr)        setAttributeEventListener(eventNames().loadEvent, createAttributeEventListener(this, attr));    else if (attr->name() == onerrorAttr)        setAttributeEventListener(eventNames().errorEvent, createAttributeEventListener(this, attr));#endif    else {        if (attr->name() == titleAttr && m_sheet)            m_sheet->setTitle(attr->value());        HTMLElement::parseMappedAttribute(attr);    }}

void HTMLLinkElement::tokenizeRelAttribute(const AtomicString& rel, RelAttribute& relAttribute){...#if ENABLE(LINK_PREFETCH)            else if (equalIgnoringCase(*it, "prefetch"))              relAttribute.m_isLinkPrefetch = true;            else if (equalIgnoringCase(*it, "subresource"))              relAttribute.m_isLinkSubresource = true;#endif...}

void HTMLLinkElement::process(){   ...#if ENABLE(LINK_PREFETCH)    if ((m_relAttribute.m_isLinkPrefetch || m_relAttribute.m_isLinkSubresource) && m_url.isValid() && document()->frame()) {        if (!checkBeforeLoadEvent())            return;        ResourceLoadPriority priority = ResourceLoadPriorityUnresolved;        if (m_relAttribute.m_isLinkSubresource)            priority = ResourceLoadPriorityLow;        m_cachedLinkResource = document()->cachedResourceLoader()->requestLinkResource(m_url, priority);        if (m_cachedLinkResource)            m_cachedLinkResource->addClient(this);    }#endif   ...  }


    解析网页html的过程中触发parseMappedAttribute方法解析HTMLLink相关的节点,在tokenizeRelAttribute实现中会解析prefetch标签并设置标记.process方法请求加载prefetch link 相关资源, 并且将任务添加到CacheResource中, 当CachedResource返回可以加载resource时, 会通知HTMLLinkElement.cpp中 notifyFinished, notifyFinished会启动一个timer进行资源加载。
转载请说明出处, 谢谢!  欢迎共同探讨. http://blog.csdn.net/typename/article/details/38358765  powered  by miechal zhao. 




更多相关文章

  1. Google Search Widget
  2. OkHttpClient加载图片给DisposableObserver,CompositeDisposable
  3. Android中Activity布局及其加载
  4. Android:异步加载网络资源
  5. Android中使用fresco加载图片
  6. (4.1.2.5)Android(安卓)屏幕旋转 处理 AsyncTask 和 ProgressDialo
  7. Android应用程序的入口Activity
  8. android 加载图片方式
  9. Android(安卓)GridView 异步加载图片

随机推荐

  1. ANDROID GRIDVIEW 点击某个位置获取某个
  2. ubuntu 不是 识别 android 设备 解决方法
  3. android圆角dialog,并限制宽度和高度
  4. Android4.1 Rotation 小结
  5. android传感器类别
  6. android 软键盘自动弹出和关闭
  7. Android(安卓)EditText达到SearchView的
  8. 高德地图-Android-逆地理转换:经纬度转换
  9. android 圆角背景和通过menu键功能弹出po
  10. android MD5加密(二)