大流量网站性能优化:一步一步打造一个适合自己的BigRender插件(转)

news/2024/5/9 14:30:46/文章来源:https://blog.csdn.net/weixin_33863087/article/details/94690666

BigRender

当一个网站越来越庞大,加载速度越来越慢的时候,开发者们不得不对其进行优化,谁愿意访问一个需要等待 10 秒,20 秒才能出现的网页呢?

常见的也是相对简单易行的一个优化方案是 图片的延迟加载。一个庞大的页面,有时我们并不会滚动去看下面的内容,这样就浪费了非首屏部分的渲染,而这些无用的渲染,不仅包括图片,还包括其他的 DOM 元素,甚至一些 js/css(某些js/css 是根据模块请求的,比如一些 ajax),理论上,每增加一个 DOM,都会增加渲染的时间。有没有办法能使得 HTML、js、css 都能按需加载呢?答案是肯定的,这就是本文要讲的 BigRender。

业界有很多 BigRender 在生产环境中的案例,比如 新浪,美团,途牛旅行网,360网址导航,淘宝商品详情页 等等。查看它们的源代码(ctrl+u),ctrl+f 搜索 textarea 关键字,很容易可以看到一些被 textarea 标签包裹的 HTML 代码。

比如途牛:

而这些被 textarea 标签包裹的 HTML 代码,只是 textarea 的 value 值,并没有渲染到 DOM 树上。没错,BigRender 通常就是用 textarea 标签包裹 HTML 代码(js/css),当作其 value 值,等到合适的时机(通常当 textarea 标签出现或者即将出现在用户视野时)将 textarea 中的 HTML 代码取出,用 innerHTML 动态插入到 DOM 树中,如有必要,取出 js/css 代码(正则),动态执行它们。(是不是和图片的延迟加载很相似?)

玉伯指出:

页面下载完毕后,要经过 Tokenization — Tree Construction — Rendering. 要让首屏尽快出来,得给浏览器减轻渲染首屏的工作量。可以从两方面入手:1. 减少 DOM 节点数。节点数越少,意味着 Tokenization, Rendering 等操作耗费的时间越少。(对于典型的淘宝商品详情页,经测试发现,每增加一个 DOM 节点,会导致首屏渲染时间延迟约 0.5ms.)2. 减少脚本执行时间。脚本执行和 UI Update 共享一个 thread, 脚本耗的时间越少,UI Update 就能越发提前。

为什么是用 textarea 标签存放大块 HTML 内容?还是可以看下玉伯的 这篇文章。淘宝的 kissy 就内置了 DataLazyload 组件。(插播:美团详情页还有用到 script 标签做 BigRender 优化,详情请见下面的 "其他" 一节)

接下去就来一步一步实现一个适合自己的 BigRender 插件,我希望可以延迟加载 HTML 元素、js 以及 css。

T.datalazyload

仿照 jQuery 的写法我定义了一个全局对象 T,将延迟加载的实现代码封装在了 T.datalazyload 对象中,将需要延迟加载的代码 "包裹" 在 textarea 标签中,设置其 visibility 属性为 hidden,并赋予该标签一个特殊的类名(为了做事件监听),比如叫做 "datalazyload"。为了方便,我规定每个做 bigrender 优化的 textarea 的父节点都只有一个子孩子(即该 textarea 元素),这一点非常重要必须遵守,因为后面代码有针对此的特殊处理。(注意要设置好父节点的高度宽度,和 dom 渲染后的高度宽度保持一致)

一些 HTML/js/css 代码都可以包裹在 textarea 标签中,例如:

<textarea class="datalazyload" style="visibility: hidden;"> <script type="text/javascript"> alert("I am lazyload zone!"); </script> <style type="text/css"> .main {margin: 0 auto; text-align: center; padding-top: 200px; width:1000px; height:1000px; border:5px black dashed;} .second {margin: 0 auto; width:1000px; height:200px; border: 5px purple dotted; padding-top: 100px; text-align: center;} </style> <div class="second"> <h1>我是延迟加载的部分!</h1> </div> </textarea>

init

给 T.datalazyload 对象定义一个 init() 方法,初始化页面时监听 scroll、resize 以及移动端的 touchmove 事件,当触发这些事件时,回调函数内判断延迟加载部分是否已经出现在视口。

init: function(config) {var cls = config.cls;this.threshold = config.threshold ? config.threshold : 0; this.els = Array.prototype.slice.call(T.getElementsByClassName(cls)); this.fn = this.pollTextareas.bind(this); this.fn(); T.addEvent(window, "scroll", this.fn); T.addEvent(window, "resize", this.fn); T.addEvent(doc.body, "touchMove", this.fn); }

config 是配置参数,其 cls 属性表示需要延迟加载的 textarea 的类名,threshold 为阈值,单位 px,表示当 textarea 距离视口多少像素时,进行预加载。

将需要延迟加载的元素存入一个数组(this.els),(某 textarea 元素)后续一旦完成加载随即在数组中删除该元素。事件监听的回调函数为 pollTextarea() 方法。

pollTextarea

pollTextareas: function() {// 需延迟加载的元素已经全部加载完if (!this.els.length) { T.removeEvent(window, "scroll", this.fn); T.removeEvent(window, "resize", this.fn); T.removeEvent(doc.body, "touchMove", this.fn); return; } // 判断是否需要加载 for (var i = this.els.length; i--; ) { var ele = this.els[i]; if (!this.inView(ele)) continue; this.insert(ele); this.els.splice(i, 1); } }

这个方法的作用是判断需要延迟加载的元素是否已经在视口,如果是,则进行加载(触发 insert 方法),并且在数组中删除该元素;如果数组为空,则表明需要延迟加载的部分都已经加载完,移除事件监听,整个延迟加载结束。

insert

接下去看 insert 方法。inert 方法的参数是需要延迟加载的 textarea 元素,很显然,我们需要解析的代码全在 textarea.innerHTML 中。我们用 extractCode 方法取出其中的 js/css 代码,然后将 js/css 过滤掉,这样剩下的就全是 HTML 代码了,将其插入 DOM 中(这正是前文说的 "每个 textarea 的父节点都只有一个子孩子" 的原因,可以直接用父节点 innerHTML 操作),如果有 loading 效果,一般在父节点加个 loading 类,移除即可。最后再动态执行 js 脚本,插入 css 样式。

insert: function(ele) {var parent = ele.parentNode, txt = this.decodeHTML(ele.innerHTML) , matchStyles = this.extractCode(txt, true) , matchScripts = this.extractCode(txt); parent.innerHTML = txt .replace(new RegExp("<script[^>]*>([\\S\\s]*?)</script\\s*>", "img"), "") .replace(new RegExp("<style[^>]*>([\\S\\s]*?)</style\\s*>", "img"), ""); if (matchStyles.length) for (var i = matchStyles.length; i --;) this.evalStyles(matchStyles[i]); // 如果延迟部分需要做 loading 效果 parent.className = parent.className.replace("loading", ""); if (matchScripts.length) for (var i = 0, len = matchScripts.length; i < len; i++) this.evalScripts(matchScripts[i]); },

extractCode

我们通过正则将 js 和 css 标签部分取出:

extractCode: function(str, isStyle) {var cata = isStyle ? "style" : "script" , scriptFragment = "<" + cata + "[^>]*>([\\S\\s]*?)</" + cata + "\\s*>" , matchAll = new RegExp(scriptFragment, "img") , matchOne = new RegExp(scriptFragment, "im") , matchResults = str.match(matchAll) || [] , ret = []; for (var i = 0, len = matchResults.length; i < len; i++) { var temp = (matchResults[i].match(matchOne) || [ "", "" ])[1]; temp && ret.push(temp); } return ret; }

成功地将 script 以及 style 标签内的内容提取了出来,巧妙地用了正则中的子表达式。

evalScripts/evalStyles

脚本执行,样式渲染。

evalScripts: function(code) {var head = doc.getElementsByTagName("head")[0] , js = doc.createElement("script"); js.text = code; head.insertBefore(js, head.firstChild); head.removeChild(js); }, evalStyles: function(code) { var head = doc.getElementsByTagName("head")[0] , css = doc.createElement("style"); css.type = "text/css"; try { css.appendChild(doc.createTextNode(code)); } catch (e) { css.styleSheet.cssText = code; } head.appendChild(css); }

优缺点 & 适用场景

简单讲讲 BigRender 优化的优缺点,以及适用场景。

优点很明显,因为减少了首屏 DOM 的渲染,所以能加快首屏加载的速度,并且能分块加载 js/css,非常适用于一些模块区分度很高的网站(个人觉得大型网站的模块区分度普遍越来越高了)。

缺点是需要更改 DOM 结构(DOM 节点的替换和渲染),可能会引起一些重排和重绘。一些没有开启 js 功能的用户将看不到延迟加载的内容(可以用 noscript 标签给出一个善意提醒)。最大的缺点可能是不利于 SEO,一些依赖于 SEO 的网站可能需要在 SEO 上下点功夫了,比如美团。

关于 SEO,可以看下 http://www.seoqx.com/lynx 这个网站,能模拟搜索引擎蜘蛛对网站的爬取情况。美团对于 BigRender 以及 SEO 解决方案 [美团网案例]改善BigRender技术导致的SEO问题

bigrender 通过减少 DOM 节点,加快首屏的渲染,但是,它也是有额外的性能损耗的,渲染前textarea 里面的 html 代码,在服务端把 html 代码保存在隐藏的 textarea 里面,所以在服务端会把 html 代码转义:尖括号等都被转义了,这个会增加服务器的压力;而且,这个改造只是前端的渲染,服务器依旧是一次计算所有的数据,输出所有的数据,这一点没有得到提高。

一般来说,使用都是后端拼接成 html 字符串,然后塞入 textarea 标签中,吐给前端。

demo

如果要做一个完整的 BigRender demo,可能比较复杂,还要涉及到后端。

之前学习 lazyload 时做过一个图片的延迟加载 demo,see http://hanzichi.github.io/cnblogs/2016/Feb/picture-lazyload/。因为 BigRender 是 lazyload 的加强版,所以简单地做了个 BigRender 版本的图片延迟加载 http://hanzichi.github.io/cnblogs/2016/Mar/bigrender/,实现的具体代码可以 check bigrender.js。求 star,求 fork~

其他

除了首页部分用了 textarea 做 BigRender 优化外,美团还用到了 script 标签做优化。比如 这个商品详情页

给 script 标签设置个非 "text/javascript" 的 type,可以下载这段 js,但不执行,这种做法似曾相识,在 labjs 中看到过。

更多可以参考 前端优化三续:用script存放html代码来减少DOM节点数

Read More

  • 淘宝详情页的 BigRender 优化与存放大块 HTML 内容的最佳方式(推荐!!如果被Q了可以 看这里)
  • 前端优化:BigRender的textarea延迟渲染和关于LABjs的实践
  • lazyload延迟加载组件
  • KISSY懒加载data lazyload 的应用
  • kissy datalazyload.js 源码
  • kissy DataLazyload API
  • kissy DataLazyload demos

http://www.cnblogs.com/zichi/p/5252629.html

转载于:https://www.cnblogs.com/softidea/p/5308477.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_746828.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

运行Silverlight3 的网站弹出 IE 安全确认框

问题贴&#xff1a;http://social.microsoft.com/Forums/zh-CN/partnercndevsilverlight/thread/b2a133a3-05ab-4698-ba91-2db6a5e1d736 Q: 程序用Silverlight3写的!但是客户端安装了 Silverlight4, 有时候会弹出下面确认框. 如果在安装Silverlight3的客户端访问则不会出现上面…

Python的scrapy之爬取boss直聘网站

在我们的项目中&#xff0c;单单分析一个51job网站的工作职位可能爬取结果不太理想&#xff0c;所以我又爬取了boss直聘网的工作&#xff0c;不过boss直聘的网站一次只能展示300个职位&#xff0c;所以我们一次也只能爬取300个职位。 jobbossspider.py: # -*- coding: utf-8 -*…

ASP.NET网站部署问题集

这几天为了给客户演示我们的项目&#xff0c;发现原来程度在开发环境和部署环境中还不太一样&#xff0c;原本在开发环境中程度运行的好好的&#xff0c;而部署后装在服务器则可能产生不少的错误。因此记录下所遇到的问题&#xff0c;方便以后查询同时也希望能帮遇到相关问题的…

多屏设备网站设计

2019独角兽企业重金招聘Python工程师标准>>> 解决方案&#xff1a; 不同域名 为不同设备屏幕编写代码 相同域名 判断设备类型选择不同的视图 自适应网页设计 转载于:https://my.oschina.net/u/190049/blog/173248

一个在线学习正则表达式的网站

今天发现了一个不错的网站regexr.com&#xff0c;可以在线学习正则表达式。 如图&#xff0c;网站左边包含了常用的正则表达式&#xff0c;我们可以随时参考&#xff0c;右边是一些示例文字&#xff0c;英文段落、电话号码、网址、电子邮箱地址等都有。网站上面可以输入正则表达…

瞬时响应:网站的高性能架构

原文地址&#xff1a;http://blog.csdn.net/taochangchang/article/details/14105327 什么叫高性能的网站&#xff1f; CDN全称Content Delivery Network&#xff0c;即内容分发网络。腾讯提供的CDN服务与一般意义上的CDN服务是一样的&#xff0c;旨在将网站的静态内容发布到最…

云瓣影音网站微信端(已开源)

随着该项目的发布到线上(小打小闹)&#xff0c;即将又要开启另一段崭新的旅程。强迫自己停下来写写所学所得&#xff0c;个人认为总结和分享是一种很棒的学习方式。那让我们先来瞧瞧项目长的什么样。如果着急要源码的朋友&#xff0c;可以下拉到最后~~ 微信端部分展现 从微信端…

jitter 如何优化网络_网络推广如何做好网站SEO优化

网络推广做好网站整站SEO优化的方式有很多&#xff0c;如何才能做好SEO优化&#xff1f;一、定位网站关键词SEO给一个网站刚开始做优化的时候&#xff0c;不是立马就设置关键词&#xff0c;而是先分析该网站主要是做什么产品/服务。知道网站的目的是做什么&#xff0c;是卖产品…

如何把自己的网站部署在网上_新手如何自己建网站?

在当前&#xff0c;生活上很多事情已经和互联网息息相关了&#xff0c;每个我们都会网上浏览各种网站&#xff0c;新闻网站看新闻&#xff0c;购物网站在线购买&#xff0c;视频网站可以看视频&#xff0c;各种类型的网站基本都会有&#xff0c;企业建网站为了宣传和提供服务&a…

移动建站平台

搜狐快站是一个很不错的移动建站平台&#xff0c;而且很多功能现在都免费了。这个消息&#xff0c;对于我们这些草根创业者来说&#xff0c;无疑是天上掉了一个大馅饼砸到了我们的头上。既然馅饼掉到了俺们的头上了&#xff0c;咱们就吃了吧。对于搜狐快站&#xff0c;我就不和…

网站刷关键词_百度关键词指数怎样刷,怎么样刷关键词的权重?重庆百度快照排名...

我们在做网站优化的时候&#xff0c;通常会去看关键词的百度指数&#xff0c;选择那些有指数的关键词来重点优化。虽然原则上百度指数是自然形成的&#xff0c;但是我们通过某些方式&#xff0c;也能够有效的刷百度指数。本文重点给大家介绍下百度关键词指数怎样刷&#xff0c;…

unbantu下安装mysql_「ubuntu安装mysql」五:在Ubuntu 16.04下安装MySQL - seo实验室

ubuntu安装mysql1&#xff0c;首先执行下面三条命令&#xff1a;执行第一条命令&#xff1a;sudo apt-get install mysql-server如下图&#xff1a;输入 y &#xff0c;下载安装时会出现要求设置密码的界面&#xff1a;输入自己想设置的密码&#xff0c;之后再次输入确认密码。…

关注经典:CSS Awards 获奖网站作品赏析《第一季》

每天都有很多新的网站推出&#xff0c;其中不乏一些设计极其优秀的作品。这个系列的文章&#xff0c;我为大家挑选了2012年赢得 CSS Awards 大奖的50个最佳网站。这些鼓舞人心的网站作品代表了网页设计的最高水平&#xff0c;相信你可以得到很大的启发。 您可能感兴趣的相关文章…

ios图片放大之后如何不模糊_几个图片处理的网站

图片来源 &#xff1a;http://pexels.com在制作PPT时候我们会常常遇到以下的问题&#xff1a;问题1&#xff1a;有了一张原图&#xff0c;想找一张像素更高的图片&#xff1b;问题2&#xff1a;使用的图片像素太低、尺寸太小、模糊等&#xff1b;问题3&#xff1a;使用的图片太…

node mysql 搭建博客_用Node ejs模板 和Mysql搭建一个 个人博客网站基础

koa2-blog本项目是采用koa2框架制作的开源blog系统如果对您有帮助&#xff0c;您可以点右上角 "Star" 支持一下 谢谢&#xff01; ^_^如果你觉得对你有帮助&#xff0c;可以点击folk&#xff0c;或者follow一下&#xff0c;我会不定时跟新一些有趣的东西.~~~ 0.0koa2…

微软推出一个非常有趣的网站—— How-old.net 看照片猜年龄!

周末休闲一下啊&#xff01;&#xff01;微软推出一个非常有趣的网站—— How-old.net 看照片猜年龄&#xff01;这是由微软机器学习团队的工程师们开发的一个“年龄测试”的新玩意&#xff0c;通过图像脸部识别和大数据分析&#xff0c;可以快速识别出照片中的人的性别和年龄&…

电子商务网站-数据库设计

转载 陈小龙哈 2015-07-22 13:58:39 评论(0) 496人阅读 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104…

9个免费的矢量图网站

寻找一些特别的&#xff0c;为众所不知的矢量图网站不是一件容易的事情&#xff0c;又要高质量&#xff0c;又要免费使用&#xff0c;尽管鱼和熊掌不能兼得&#xff0c;但是谁叫我们碰到了互联网时代呢&#xff0c;谁叫我们知道一句台词&#xff1a;一切皆有可能呢&#xff01;…

网页SEO

2019独角兽企业重金招聘Python工程师标准>>> 1.SEO简介&#xff1a;Search Engine Optimization 。 2.内容上的SEO: a):网站标题、关键字、描述 . b)网站内容优化 c):Robot.txt文件 d)添加外部链接 3.编码上的SEO.(网站结构布局优化&#xff0c;网页代码优化)…

解决方案下显示的网站名称被追加编号的问题解决方法

问题描述 只看标题 大家是不是觉得有点不知所以&#xff1f;好吧&#xff0c;直接上图&#xff0c;大家请往下看。 如图中所示&#xff0c;我用VS2012编辑器添加一个解决方案[TestSolution],接着我先添加一个网站[Test],然后因为路径选择不对&#xff0c;就把站点文件删除重建&…