
c4df580d526304bdfcfe7f955cd14e73.ppt
- Количество слайдов: 55
网站性能,刻不容缓!! 三大因素: CSS、IMAGES、JS 主讲人:侯彪
• CSS也有性能开销 • 华丽的外衣--IMAGES • JS优化几则 • 杂谈---DOM的加载也有SEO的技巧
CSS也有性能开销 • 网站性能一说让多数的人第一时间想起的是javascript,但对于一个 WEB来说同样重要的CSS呢?你会考虑到他的性能开销吗? • ul#my_list > li{color: #f 00} • 理解一下CSS选择符的概念
CSS也有性能开销 在前辈们的指点下,关于CSS的最佳性能实践大致总结了如下几点: ① 把样式表放在<head>标签中以提升页面的逐步渲染速度。 ② 不要在IE中使用CSS Expression,因为他会被执行到很多次,你想 知道是多少吗?好的,以万为单位,甚至可以搞死你的IE! ③ 避免或杜绝使用行内样式,因为这会增加下载页面的大小,并搞乱 你的CSS权重。
怎么样这些很容易理解吧。不过…… 以上几点已经不能满足我们追求性能的野心了。于是更多的CSS性能 规则开始展现他们的力量!
CSS也有性能开销 • ID选择符 #toc{margin-left: 20 px} • 类选择符. chapter{font-weight: bold} • 类型选择符 a{text-decoration: none} • 相邻兄弟选择符 h 1 + #toc{margin-top: 40 px} • 子选择 #toc > li{font-weight: bold} • 后代选择符 #toc a{color: #333} • 通配选择符 *{font-family: Arial} • 属性选择符 [href="#index"]{font-style: italic} • 伪类和伪元素 a: hover{text: decoration: underline}
CSS也有性能开销 最右边优先!!! #toc > li{font-weight: bold} 浏览器并不是从左到右的顺序来解析CSS选择符,所以,看看上面这个 本以为很高效的选择符,浏览器先要遍历DOM中所有的li标签,并确定 他的父级元素为#toc。 #toc a{color: #333} 看看这个 岂不是更糟糕!
CSS也有性能开销 知道了选择符的匹配顺序,我们便有了如下的更具体的优化法则! ①避免使用通配规则 * ②不要限定ID选择符 div#wrap ③不要限定类选择符 li. ele to. list_ele ④让规则越具体越好 ol li a to. list_link ⑤避免使用后代选择符 ul li ⑥避免使用子选择符 ul > li > a ⑦质疑子选择符的所有用途 尽可能使用具体的类 ⑧依靠继承
华丽的外衣--IMAGES • 搞清楚你要处理的图片类型 • 图形 VS 图像(照片)
华丽的外衣--IMAGES 图形: 一般来说,网站的LOGO,草图,手稿图和部分ICON图标都属于图形, 这些通常由连续的线条或其他尖锐的颜色过渡,颜色数量相对较少。
华丽的外衣--IMAGES 图像(照片): 百万数量级的颜色,包含平滑的颜色过渡和渐变,比如网站的KV轮播图, 数码相机拍出来的产品图。
华丽的外衣--IMAGES
华丽的外衣--IMAGES
华丽的外衣--IMAGES
华丽的外衣--IMAGES • 三种不同的图片格式 • JPEG GIF PNG(此处只考虑PNG 8) • 相关的系统知识这里不再阐述,有兴趣的自己上 百度GOOGLE一下 • 以下介绍重点的属性!
华丽的外衣--IMAGES JPEG: 有损:它是一种有损的格式,用户可以设置自定义质量级别,这个级别 决定了有多少图像信息会被抛弃。级别从0 -100,但即便是 100也同样会 有一定程度的质量损耗。 当我们要对一个图像反复编辑时,比如随时都会往里边继续加新图的 CSS精灵,最好使用无损的格式来保存中间结果,然后在最终结果的时 候存为JPEG格式,否则你将在每次保存为JPEG的时候都损耗一些质量。
华丽的外衣--IMAGES JPEG: 但也有少数操作是无损的: ①以 90的倍数进行旋转的时候 ②裁剪 ③水平翻转或垂直翻转 ④从标准模式切换到渐进模式 反之亦然 ⑤编辑图像的元数据 此格式不支持透明和动画
华丽的外衣--IMAGES GIF: GIF是无损的,也就是说你可以打开任意一个GIF文件,做一些修改,保 存关闭时不会损失任何质量。 透明,允许一个二进制透明,每个像素要么完全透明 要么完全不透明 这 就意味着他不支持alpha透明。取而代之的是,调色板中的某个颜色可以 被标记为表示透明,而透明像素则会被分配为这个颜色值,所以,如果 你为GIF设置了透明像素,那么就会消耗一个调色板条目。
华丽的外衣--IMAGES GIF: 动画,GIF支持“逐帧动画”。应用最广的当属LOADING 256色限制。 逐行扫描,当生成一个GIF文件时,会使用一个压缩算法LZW来减小文 件的大小,压缩GIF文件时,会从上到下一行一行的对像素进行扫描,这 种情况下,当图像在水平方向有很多重复颜色时,可以获得更好的压缩 效果。如下图:
华丽的外衣--IMAGES 1. 77 KB
华丽的外衣--IMAGES 3. 84 KB
华丽的外衣--IMAGES PNG: 为了弥补GIF文件的缺点,并规避LZW算法的专利问题(2004年已经过 了保护期)PNG文件诞生!你可以使用PNG 8代替不需要动画的GIF并用 PNG 24或 32来代替JPEG! PNG是无损的图像格式。多次编辑不会降低其质量,这使得采用PNG格 式来存储中间格式非常合适。比如我们网站的品牌旗舰馆的LOGO就是 用PNG 8来保存的,每次有新品牌的时候直接在PNG上操作,存储完毕 不会有任何的消耗,如果是JPEG那保存几次就完了。如下图:
华丽的外衣--IMAGES
华丽的外衣--IMAGES 今天又添加了新的品牌 使用PNG无损直接在原图上进行添加
华丽的外衣--IMAGES PNG: 透明。PNG 8支持和GIF一样的二进制透明,PNG 24支持alpha透明 逐行扫描。和GIF格式一样,但是压缩比更高!如下图
华丽的外衣--IMAGES 2. 14 KB
华丽的外衣--IMAGES 就图像格式而言,GIF通常用于显示图形,JPEG更适合显示图片,而 PNG则两者都适合。 和GIF相比: 用PNG来代替GIF(不带动画)会更好,文件大小也更小,并且具备除 动画以外的所有GIF特性,所以应该尽量以PNG 8代替GIF。 有一个例外就是颜色数很少的小图像,这时GIF的压缩比可能更高一些, 但是这样的小图片应该被放在了CSS精灵中,因为HTTP的请求增加已经 远远超过节省的那点带宽,而且用PNG来保存CSS精灵可以获得更高的 压缩比。
华丽的外衣--IMAGES 和JPEG相比: 当图像中的颜色超过256时,需要使用真彩色图像格式---PNG 24或JPEG。 JPEG的压缩比更高,而且一般来说JPEG也是照片存储的实际标准。但由 于JPEG是有损的而且在清晰的颜色过渡周围会有大色块,因此以下2种 情况更适合PNG
华丽的外衣--IMAGES 和JPEG相比: 当图像的颜色略超过256种,可以在不损耗任何可见质量的前提下,将 图像转换为PNG 8,虽然有时存储为PNG 8会使得颜色数量减少,但是有 时就算本身有1000种颜色,当你存储为 256种颜色的时候也看不出什么 特别明显的变化。如下图
华丽的外衣--IMAGES JPEG 80品质 190 KB
华丽的外衣--IMAGES JPEG 100品质 351 KB
华丽的外衣--IMAGES PNG 8 114 KB
华丽的外衣--IMAGES 和JPEG相比: 当图片很容易因为压缩产生大色块并且大色块变得不可接受时。如下图
华丽的外衣--IMAGES
JS优化几则 • 4种数据存储位置 • 局部变量最快 • 循环 • JS与DOM那扯不断理还乱的关系
JS优化几则 • 4种数据存储位置 • 直接量 数字 字符串 boolen 对象 数组 函数 正则 null undefined • 变量 var. . . • 数组元素 数字为索引 • 对象成员 字符串为索引 • 直接量和局部变量的访问速度快于后边 2个 • FF 3是个例外,他优化了数组项的存取,但是通常的建议是,如果在乎 速度 那么尽量使用直接量或局部变量 减少数组项和对象成员的使用。
JS优化几则 局部变量最快 每个JS函数都是表示为一个对象,更确切的说是function对象的一个实例,function 对象同其他对象一样,拥有可以编程访问的属性,和一些列不能通过代码仅供JS引擎 存取的内部属性。其中一个内部属性是【scope】 内部属性【scope】包含了一个 函数被创建的作用域中 对象的集合,这个集合被称 为函数的作用域链,它决定哪些数据能被函数访问。当一个函数创建后,它的作用域 链会被 创建此函数的作用域中 可访问的数据对象 所填充。 function add(a, b){ var sum = a + b; return sum; } 函数add创建时,他的作用域链中填入了一个单独的可变对象,这个全局对象表示所 有全局范围定义的变量。包含WINDOW, DOCUMENT, NAVIGATOR等等全局对象。
JS优化几则 局部变量最快 下面开始执行 var num = add(10, 20); 执行此函数会创建一个称为 运行期上下文 的内部对象。一个运行期上下文定义了一个函数 执行时的环境。函数每次执行时对应的执行期上下文都是独一无二的,所以多次调用同一 个函数就会导致创建多个运行期上下文。当函数执行完毕,对应的运行期上下文就被销毁。 每个运行期上下文都有自己的作用域链,用于标识符解析。当运行期上下文被创建时,它 的作用域链初始化为当前运行函数的[scope]属性中所包含的对象。这些值按照他们出现在 函数中的顺序,被复制到运行期上下文的作用域链中。这个过程一旦OK,一个被称为 活 动对象 的新对象就为运行期上下文创建好了。活动对象作为函数运行期的可变对象,包含 了所有局部变量,命名参数,参数集合 以及 this。然后此对象被推入作用域链的前端。当 运行期上下文被销毁,活动对象也随之销毁。
JS优化几则 局部变量最快 在函数执行过程中,每遇到一个变量,都会经历一次标识符解析过程以决定从哪 里获取或存储数据。该过程搜索运行期上下文的作用域链,查找同名的表示符。 搜索过程从作用域链顶部开始,也就是当前运行函数的活动对象。如果找到了, 就使用这个标识符对应的变量;如果没找到,继续搜索作用域链中的下一个对象。 搜索过程会持续进行,直到标识符被找到,或者没有可用于搜索的对象为止,这 种情况下标识符被认定是为定义的。is not defined 。函数执行过程中,每个标 识符都要经历这样的搜索过程。正是这个搜索过程影响着他的性能! 如果名字相同的2个变量存在于作用域链的不同部分,那么标识符就是遍历作用 域链时最先找到的那个,也可以说,第一个找到的遮蔽了第二个。
JS优化几则 局部变量最快 在运行期上下文的作用域链中,一个标识符所在的位置越深,它的读写 速度也就越慢。SO 函数中读取局部变量总是最快的,而全局变量是最 慢的,因为全局的总是存在于运行期上下文作用域链的最末端! 一个好的经验法则就是,如果一个跨作用域的值在函数中被引用一次以 上,那么就把它存储到局部变量里。 临时改变作用域链 with与try catch 但是不推荐使用,除非你的项目实 在有需求。
JS优化几则 局部变量最快 说了以上这么多 就是想总结 2个字!!那就是
JS优化几则 局部变量最快
JS优化几则 循环 着重介绍for while循环 先来了解下2个循环的表现 看下边代码及运行时间
JS优化几则 循环
JS优化几则 循环 总结就是 在乎先后顺序 用for ++ 不在乎的话用for --
JS优化几则 循环 其他优化法则 减少迭代的 作量,很明显,如果一次循环迭代要花很长时间去执行,那么多次循环需要 花更多时间,一个提升循环整体速度的好方法是限制循环中耗时操作的数量。 for(var i = 0; i < items. length; i++){ //do something; } 上述循环中看似很正常,但是有很严重的性能问题!每次运行循环体时都会产生如下操作: ①一次控制条件中的属性查找(items. length) ②一次控制条件中的数值大小比较(i < items. length) ③一次控制条件结果是否为true的比较(i < items. length == true) ④一次自增操作
JS优化几则 循环 前面我们说过 读取局部变量是最快的,这个循环体的每次运行运行都要查找 items. length 这样做很耗时,因为这个值在循环过程中是不变 的仅供比较,所以我们把它传递到局部变量会更快也更合情合理。如下: for(var i = 0, l = items. length; i < l; i++){ //do something } 重写后的循环只在循环运行前对长度进行一次属性查找,这使得控制条件可直接 读取局部变量,所以速度更快。快多少?自己测试,肯定高于你的预期!
JS优化几则 循环 另一个方法就是在 顺序不是很重要的情况下 可以使用倒序循环 比如循环为每个DOM元素 add. Event. Listener。倒序循环是编程语言中一种通用的优化方法。 for(var i = items. length; i--; ){ //do something } 现在每个控制条件只是简单的与0比较。控制条件与true值比较,任何非零数会自动转换为true, 而零值等同于false。实际上控制条件从2次比较(迭代数少于总数吗?是否为true?)减少到 1 次(它是处儿吗?)。这样就更进一步提高了循环速度。通过这 2个很不起眼的小办法就可以看 出 循环速度比最初的提高了50%以上! 对比原始版本 现在每次运行循环体时只需要如下几步 ①一次控制条件的比较(i == true) ②一次减法操作(i--)
JS优化几则 JS与DOM那扯不断理还乱的关系 用JS脚本来操作DOM的代价很昂贵,它是富WEB应用中最常见的性能瓶颈。关 于JS与DOM的关系一说,微软有个很好的比喻,把DOM与JS各自想象为一个岛 屿,他们之间用高速桥连接,JS每次访问DOM都要途径这座桥,并交纳过路费, 访问DOM的次数越多,付出的代价越昂贵,因此,要尽可能的减少过桥的次数。 访问DOM的代价已经这么昂贵 那就更不用说修改DOM了,但是我们以往的以 后的项目又不可完全避免产生这样的过路费,所以有必要掌握以下的常识!
JS优化几则 1. 避免在循环体中对DOM元素反复操作! for( var i = 0; i < 10; i++){ document. get. Element. By. Id("a"). inner. HTML += i; } 这段简单的代码有很严重的性能问题!每次循环该元素都被访问 2次,1次读取 inner. HTML内容,1次重写它。 转变! var content = ""; for(var i = 0; i < 10; i++){ content += i; } document. get. Element. By. Id("a"). inner. HTML = content; 插一句 inner. HTML对比document. create. Element 性能相差无几,在最新版的webkit 浏览器中 inner. HTML略慢 其他情况下建议用inner. HTML
JS优化几则 2. 重绘重排都是代价昂贵的操作,他们会导致WEB应用程序和UI反应迟钝,因 此应该尽量减少这类过程的发生。 当DOM的变化影响了元素的几何属性-widht height border,浏览器需要重 新计算元素的几何属性,同样其他元素的几何属性和位置也会因此受到影响。浏 览器会使渲染树中受到影响的部分失效,并重新构造渲染树。这个过程就是重排 (Reflow)。完成重排后浏览器会重新绘制受影响的部分到屏幕中,该过程为 重绘(Repaint) 并不是所有的DOM变化都会影响几何属性。例如改变一个元素的 background-color,这种情况下只会发生一次重绘而不需要重排。因为元素的 布局并没有改变。 以下情况会触发重排:
JS优化几则 1. 添加删除可见的DOM元素 2. 元素位置改变 3. 元素尺寸改变 border-width margin padding width height 4. 内容改变,文字行数变化 图片大小尺寸变化 5. 页面渲染器初始化 6. 浏览器窗口尺寸改变resize(function(){})
JS优化几则 3. 如何最大程度的减少重排和重绘 首先。使元素脱离文档流 其次。对其应用多重改变 最后。把元素带回文档中 该过程会触发两次重排 第一步和第三步,如果你忽略这 2个步骤,那么你在第二步里的每一个修改操 作触发一次重排。 三种方法可以使DOM脱离文档 1. 隐藏元素,应用修改,重新显示 display: none display: block 2. 使用文档片段,在当前DOM之外构建一个子树,再把它拷贝回文档。 document. create. Document. Fragment() 3. 将原始元素拷贝到一个脱离文档的节点中,修改副本,完成后再替换原始元素。 clone. Node(true) replace. Child(clone, old)
JS优化几则 当然JS的深度优化绝对要比我所介绍的这几个多的太多了。更多的优化 经验也要视项目的实际情况,当然了,既然我们已经知道了一些可以优 化并且值得优化的东西那就应该在书写的过程中严格要求自己,避免在 代码一行一行添加的时候为自己的日后维护带来麻烦。
THANK YOU!
c4df580d526304bdfcfe7f955cd14e73.ppt