【第一季第四期】JavaScript Optimization

Preview:

DESCRIPTION

 

Citation preview

页 面 性 能 优 化

-- 博玉

PM

俺们开发了一个新系统,杠杠滴 ~~

他的功能就像瑞士军刀一样,应有尽有!

这么好的系统,我们先用用!

半个月后 ···

这样的系统我才不想用呢

需求方

为什么!我们熬了整整 3 个月啊 ~

开发 A

因为它很 慢 !!!

慢 ?!

这是为什么呢?

1. 前端慢?

2. 后台响应时间过长?

3. 网络速度慢?

慢可能的几个原因

4. 用户机器太烂 !

我们没有错,责任全在你们

ued 。

搞个破系统还赖在我们身上,

我呸!

开发 前端

只能在 ie 内核下用,火狐下要加 fiddlerHook

真相只有一个!

我承认,这个慢的问题全在前端

~~~

-- 《高性能网站建设指南》

1. 尽可能的减少 HTTP 的请求数

2. 使用 CDN ( Content Delivery Network )

3. 添加 Expires 头 ( 或者 Cache-control )

4. Gzip 组件

5. 将 CSS 样式放在页面的上方

6. 将脚本移动到底部(包括内联的)

7. 避免使用 CSS 中的 Expressions

8. 将 JavaScript 和 CSS 独立成外部文件

9. 减少 DNS 查询

10. 压缩 JavaScript 和 CSS ( 包括内联的 )

11. 避免重定向

12. 移除重复的脚本

13. 配置实体标签( ETags )

14. 使 AJAX 缓存

这些很实用,但是对于淘宝,对于运营支撑,还不够!

运营支撑页面特点

1. 页面偏向 web2.0 ,大部前分都是 web app 应用,要求页面既炫又快。

2. 页面 js 量大, dom 操作频繁。

3. 开发和前端同时都参与端代码编写,没有一个良好的规范。

常见情况

1. 用户感觉慢

2. js 、 css 阻塞问题

3. DOM 操作

4. Js 代码优化

5. web2.0 之痛

1. 用户感觉慢

1. 用户感觉慢

什么是慢,多少才算慢?

一个页面从请求到能看见在 2s 以内。

所见即所得

1. 用户感觉慢

真的是系统慢?

1. 用户感觉慢

可能是感官上慢!

1. 用户感觉慢

总结

1. 在页面加载完成后尽量保证用户所看见的是最终页面效果。

2. 不要对页面进行用户意料之外的操作

2.Js css 阻塞

2.Js 阻塞

1. 浏览器在下载 js 的时候发生了什么事?

2. 内联 js ,外联 js ,头部 js 有什么区别?

脚本会阻塞下载位于它之后的资源,包括图片, css , iframe

内联 js 和 head 部分 js 会阻塞整个页面渲染

外联 js 会阻塞位于它之后的元素渲染

2.Js 阻塞

莫非我一代天骄命丧于

此?!

2.Js 阻塞

放心我们有 js 无阻塞下载技术!

2.Js 阻塞

1.XHR Eval

2.XHR 注入

3.Script in Iframe

4.Script DOM Element

5.Script Defer

6.Document write Script Tag

Js 无阻塞下载的几种方式

异步请求代码段,然后 eval 方法执行

异步请求代码段,然后 var s = document.createElement(‘script’); s.text = xhrObj.responseText;

在 iframe 中存放 js ,来实现页面资源并行下载

通过创建 script 标签,然后设置 src 属性,异步请求数据,同 getScript 原理一样

利用标签的 defer 属性实现资源后续加载

在 HTML 页面内使用 document.write <script src=""> . 仅在 IE 有效 .

2.Js 阻塞

技术 并行下载 跨域 现成代码 忙指示器 确保顺序 大小字节

Normal Script Src

( IE8 、 Saf4)

是 是IE 、 Saf4 ( F

F 、 Chr )IE 、 Saf4 ( FF 、 Chr 、 op

~50

XHR Eval IE, FF, Saf, Chr, Op 否 否 Saf, Chr - ~500

XHR 注入 IE, FF, Saf, Chr, Op 否 是 Saf, Chr - ~500

Script in Iframe

IE, FF, Saf, Chr, Op 否 否 IE, FF, Saf, Chr - ~50

Script DOM Element

IE, FF, Saf, Chr, Op 是 是 FF, Saf, Chr FF, Op ~200

Script Defer IE, Saf4, Chr2, FF3.1+ 是 是 IE, FF, Saf, Chr,

OpIE, FF, Saf, Chr,

Op ~50

Document.write Script Tag

IE, Saf4, Chr2, Op 是 是 IE, FF, Saf, Chr,

OpIE, FF, Saf, Chr,

Op ~100

2.Js 阻塞

技术 状态栏 进度条 图标 光标 阻塞渲染 阻塞onload

Normal Script Src FF,Saf,Chr IE,FF,Saf IE,FF,Saf,Chr FF,Chr IE,FF,Saf,Chr,O

pIE,FF,Saf,Chr,Op

XHR Eval Saf, Chr Saf Saf,Chr Saf,Chr -- --

XHR 注入 Saf, Chr, Saf Saf,Chr Saf,Chr -- --

Script in Iframe IE, FF, Saf, Chr FF,Saf IE,FF,Saf,Chr FF,Chr -- IE,FF,Saf,Chr,O

p

Script DOM Element FF, Saf, Chr FF,Saf FF,Saf,Chr FF,Chr -- FF,Saf,Chr

Script Defer FF, Saf, Chr FF,Saf FF,Saf,Chr FF,Chr,Op FF,Saf,Chr,Op IE,FF,Saf,Chr

Document.write Script Tag FF, Saf, Chr IE,FF,Saf IE,FF,Saf,Chr FF,Chr,Op IE,FF,Saf,Chr,O

pIE,FF,Saf,CHr,Op

2.Js 阻塞

如果 js 太多执行需要很长时间,怎么办?

让执行的块切成很多小块并使用 setTimeout(function(){},0)

2.Css 阻塞

Css 阻塞?!

2.Css 阻塞

狄卿,你有什么见解。

2.Css 阻塞

以我多年断案经验来看,这桩命案应该是 js引

起的!

2.Css 阻塞

我命你为钦差,专办此案,登基大典前必须破案。

2.Css 阻塞

<head > <title > js test </title > <link type ="text/css" rel ="stylesheet" href ="http://69.64.92.205/Css/Home3.css"/> </head > <body > <img src ="http://www.blogjava.net/images/logo.gif" /><br/> <img src ="http://csdnimg.cn/www/images/csdnindex_piclogo.gif" /> </body >

2.Css 阻塞

<head > <title > js test </title > <link type ="text/css" rel ="stylesheet" href ="http://69.64.92.205/Css/Home3.css"/> <script type ="text/javascript"> function a(){}</script></head > <body > <img src ="http://www.blogjava.net/images/logo.gif" /><br/> <img src ="http://csdnimg.cn/www/images/csdnindex_piclogo.gif" /> </body >

2.Css 阻塞

因为浏览器会维持 html 中 css 和 js 的顺序,样式表必须在嵌入的 JS 执行前先加载、解析完。而嵌入的 JS会阻塞后面的资源加载,所以就会出现上面 CSS 阻塞下载的情况。

所以如果需要页面先行请将 js 放在 head 部分请放在 css 之前

总结

1. 尽量不要使用内嵌 js

2.根据情况将 js 放在页面底部,或者使用无阻塞加载 js

3. 如果 js 需要放在 head 部分,请放在 css 前

3. DOM 操作

3. DOM 操作

GetElementById getElementsByClassName

其实作为代码本生,GetElementById 和getElementsByClassName

并没有错

我并没有错,错的是整个社会!

3. DOM 操作

GetElementById 和 getElementsByClassName滥用导致 dom 操作过多,导致页面变慢。

3. DOM 操作

GetElementById 核心代码

3. DOM 操作

GetElementsByClass 核心代码

3. DOM 操作

GetElementsBy 核心代码

3. DOM 操作

使用 getElemntsBy 方法将所需要的节点一次性找出来放在一个引用中,只对 dom 进行一次遍历

var refers = {};(Function(){ var btn = refers.btn = {}; function getButton(node){ switch (true) { case DOM.hasClass(node,’add’): btn.addBtn = node; break; case DOM.hasClass(tg,’delete’): btn.deleteBtn = node; break; } } DOM.getElementsBy(getButton,’input’,’’);})();

3. DOM 操作

3. DOM 操作

reflow 和 repaint

3. DOM 操作

reflow

repaint

对于 DOM结构中的各个元素都有自己的盒子(模型),这些都需要浏览器根据各种样式(浏览器的、开发人员定义的等)来计算并根据计算结果将元素放到它该出现的位置,这个过程称之为 reflow 。

当各种盒子的位置、大小以及其他属性,例如颜色、字体大小等都确定下来后,浏览器于是便把这些元素都按照各自的特性绘制了一遍,于是页面的内容出现了,这个过程称之为 repaint 。

3. DOM 操作

导致 reflow 和 repaint 的因素

1. 改变窗囗大小

2. 改变文字大小

3. 添加 /删除样式表

4. 内容的改变,如用户在输入框中敲字

5. 激活伪类,如 :hover (IE里是一个兄弟结点的伪类被激活 )

6. 操作 class属性

7. 脚本操作 DOM

8. 计算 offsetWidth 和 offsetHeight

9. 设置 style属性

3. DOM 操作

reflow 和 repaint 是不可避免的,只能将 reflow 对性能的影响减到最小。

3. DOM 操作

避免 reflow 和 repaint 的方法

1.   尽可能限制 reflow 的影响范围。 以上面的代码为例,要改变 p 的样式, class 不要加在 div 上,通过父级元素影响子元素不好。 最好直接加在 p 上。

2 通过设置 class 方式改变样式 通过设置 style属性改变结点样式的话,每设置一次都会导致一次 reflow 。所以最好通过设置 class 的方式。

3  实现元素的动画,它的 position 属性应当设为 fixed 或 absolute ,这样不会影响其它元素的布局。

4  权衡速度的平滑。 比如实现一个动画,以 1 个像素为单位移动这样最平滑,但 reflow 就会过于频繁, CPU 很快就会被完全占用。如果以 3 个像素为单位移动就会好很多。

5 不要使用 tables 布局 不要用 tables布局的另一个原因就是 tables 中某个元素一旦触发 reflow 就会导致 table 里所有的其它元素 reflow 。在适合用 table 的场合,可以设置 table-layout 为 auto 或 fixed , 这样可以让 table 一行一行的渲染,这种做法也是为了限制 reflow 的影响范围。

6   不要使用 css 表达式 如果 css里有 expression ,每次都会重新计算一遍。

总结

在环境允许的情况下尽可能地想办法减少 dom 节点的操作,尽量避免页面 reflow 和 repaint 。

4. Js 代码优化

4. Js 代码优化

大家一起来找茬

4. Js 代码优化开胃菜:

function firstExample(){ var a = ‘test1’; var b = ‘test2’; var c = ‘test3’;

return b;}

alert(firstExample());

4. Js 代码优化

function firstExample(){ var a = ‘test1’; var b = ‘test2’; var c = ‘test3’;

return b;}

alert(firstExample());

开胃菜:

4. Js 代码优化

function firstExample(){ var a = ‘test1’, b = ‘test2’, c = ‘test3’;

return b;}

alert(firstExample());

开胃菜:

4. Js 代码优化

精简代码,更少的代码往往更快。

开胃菜:

4. Js 代码优化

咦?这样也行?!

4. Js 代码优化

没错!咱们完的就是极限!

4. Js 代码优化

var people = { man : [‘李雷’ ,‘tom’], woman : [woman1 : ‘韩梅梅’ ,woman2 : ‘lucy’]};

function getWomanName(){ var names = ‘’; for(var I = 0;I < people.woman.length;I++){ names += people.woman[i]; } return names; }

getWomanName();

例 1 :

4. Js 代码优化

var people = { man : [‘李雷’ ,‘tom’], woman : [woman1 : ‘韩梅梅’ ,woman2 : ‘lucy’]};

function getWomanName(){ var names = ‘’; for(var I = 0;I < people.woman.length;I++){ names += people.woman[i]; } return names; }

getWomanName();

例 1 :

4. Js 代码优化

var people = { man : [‘李雷’ ,‘tom’], woman : [woman1 : ‘韩梅梅’ ,woman2 : ‘lucy’]};

function getWomanName(){ var names = ‘’, woman = people.woman; for(var I = 0,len = woman.length;I < len;I++){ names += woman[i]; } return names; }

getWomanName();

例 1 :

4. Js 代码优化

利用减少作用域链查找等 js 自身语言特性,优化 js 速度。

例 1 :

4. Js 代码优化

function getUrl(index){ var url1 = ‘XXXXX’, url2 = ‘XXXXX’, url3 = ‘XXXXX’,

url = ‘’; if(index == 1){ url = url1; }else if(index == 2){ url = url2; }else if(index == 3){ url = url3; }

location.href = url;}

例 2 :

4. Js 代码优化

function getUrl(index){ var url1 = ‘XXXXX’, url2 = ‘XXXXX’, url3 = ‘XXXXX’,

url = ‘’; if(index == 1){ url = url1; }else if(index == 2){ url = url2; }else if(index == 3){ url = url3; }

location.href = url;}

例 2 :

4. Js 代码优化

function getUrl(index){ var url = [‘XXXXX’, ‘XXXXX’, ‘XXXXX’];

location.href = url[index];}

例 2 :

4. Js 代码优化

在算法上提高 js 性能

例 2 :

4. Js 代码优化

<ul> <li class = 'J_List'>a</li> <li class = 'J_List'>b</li> <li class = 'J_List'>c</li> </ul>

<script>var list = DOM.getElementsByClassName('J_List','li');Event.on(list,'click',function(e){ var obj = Event.getTarget(e); alert(obj.innerHTML);})

</script>

例 3 :

4. Js 代码优化

<ul> <li class = 'J_List'>a</li> <li class = 'J_List'>b</li> <li class = 'J_List'>c</li> </ul>

<script>var list = DOM.getElementsByClassName('J_List','li');Event.on(list,'click',function(e){ var obj = Event.getTarget(e); alert(obj.innerHTML);})

</script>

例 3 :

4. Js 代码优化

<ul id=‘J_List’> <li>a</li> <li>b</li> <li>c</li> </ul>

<script>var list = DOM.getElementById(‘J_List’);Event.on(list,'click',function(e){ var obj = Event.getTarget(e);

if(obj.tagName == ‘li’) alert(obj.innerHTML);})

</script>

例 3 :

4. Js 代码优化

利用事件冒泡等浏览器特性减少 DOM 操作。

例 3 :

4. Js 代码优化

Js 代码优化顺序

5.Web 2.0 之痛

5.Web 2.0 之痛

Web2.0 的广泛使用让很多开发人员对开始沉迷于页面效果,迷信前端技术,将很多解析,渲染任务未加考虑放到前端处理,导致页面越来越慢。

5.Web 2.0 之痛

1. 是否非用 web2.0 不可?

2. 是否每个页面都需要页面先行?

5.Web 2.0 之痛

优化大部分是以个权衡的过程。

针对场景合理运用技术才能整体上让页面速度有个提升。

祝大家早日修得正果…

Recommended