前端性能优化总结(一)-js、css优化

JavaScript010

前端性能优化总结(一)-js、css优化,第1张

移动互联网时代,用户对于网页的打开速度要求越来越高。首屏作为直面用户的第一屏,其重要性不言而喻。优化用户体验更是我们前端开发非常需要 focus 的东西之一。

从用户的角度而言,当打开一个网页,往往关心的是从输入完网页地址后到最后展现完整页面这个过程需要的时间,这个时间越短,用户体验越好。所以作为网页的开发者,就从输入url到页面渲染呈现这个过程中去提升网页的性能。

所以输入URL后发生了什么呢?在浏览器中输入url会经历域名解析、建立TCP连接、发送http请求、资源解析等步骤。

http缓存优化是网页性能优化的重要一环,这一部分我会在后续笔记中做一个详细总结,所以本文暂不多做详细整理。本文主要从网页渲染过程、网页交互以及Vue应用优化三个角度对性能优化做一个小结。

首先谈谈拿到服务端资源后浏览器渲染的流程:

关键渲染路径是浏览器将 HTML、CSS、JavaScript 转换为在屏幕上呈现的像素内容所经历的一系列步骤。也就是我们刚刚提到的的的浏览器渲染流程。

为尽快完成首次渲染,我们需要最大限度减小以下三种可变因素:

首先,DOM 和 CSSOM 通常是并行构建的,所以 CSS 加载不会阻塞 DOM 的解析。

然而,由于 Render Tree 是依赖于 DOM Tree 和 CSSOM Tree 的,

所以他必须等待到 CSSOM Tree 构建完成,也就是 CSS 资源加载完成(或者 CSS 资源加载失败)后,才能开始渲染。因此,CSS 加载会阻塞 Dom 的渲染。

由此可见,对于 CSSOM 缩小、压缩以及缓存同样重要,我们可以从这方面考虑去优化。

当浏览器遇到 script 标记时,会阻止解析器继续操作,直到 CSSOM 构建完毕,JavaScript 才会运行并继续完成 DOM 构建过程。

当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility 等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。

回流(Reflow)

当 Render Tree 中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流。

有时即使仅仅回流一个单一的元素,它的父元素以及任何跟随它的元素也会产生回流。现代浏览器会对频繁的回流或重绘操作进行优化:浏览器会维护一个队列,把所有引起回流和重绘的操作放入队列中,如果队列中的任务数量或者时间间隔达到一个阈值的,浏览器就会将队列清空,进行一次批处理,这样可以把多次回流和重绘变成一次。

当你访问以下属性或方法时,浏览器会立刻清空队列:

因为队列中可能会有影响到这些属性或方法返回值的操作,即使你希望获取的信息与队列中操作引发的改变无关,浏览器也会强行清空队列,确保你拿到的值是最精确的。

避免频繁操作样式,最好一次性重写 style 属性,或者将样式列表定义为 class 并一次性更改 class 属性。

避免频繁操作 DOM,创建一个 documentFragment,在它上面应用所有 DOM 操作,最后再把它添加到文档中。

也可以先为元素设置 display: none,操作结束后再把它显示出来。因为在 display 属性为 none 的元素上进行的 DOM 操作不会引发回流和重绘。

避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。

对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。

图片懒加载在一些图片密集型的网站中运用比较多,通过图片懒加载可以让一些不可视的图片不去加载,避免一次性加载过多的图片导致请求阻塞(浏览器一般对同一域名下的并发请求的连接数有限制),这样就可以提高网站的加载速度,提高用户体验。

将页面中的img标签src指向一张小图片或者src为空,然后定义data-src(这个属性可以自定义命名,我才用data-src)属性指向真实的图片。src指向一张默认的图片,否则当src为空时也会向服务器发送一次请求。可以指向loading的地址。注意,图片要指定宽高。

当载入页面时,先把可视区域内的img标签的data-src属性值负给src,然后监听滚动事件,把用户即将看到的图片加载。这样便实现了懒加载。

事件委托其实就是利用JS事件冒泡机制把原本需要绑定在子元素的响应事件(click、keydown……)委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡。

优点:

例如有一个列表需要绑定点击事件,每一个列表项的点击都需要返回不同的结果。

传统写法:

传统方法会利用for循环遍历列表为每一个列表元素绑定点击事件,当列表中元素数量非常庞大时,需要绑定大量的点击事件,这种方式就会产生性能问题。这种情况下利用事件委托就能很好的解决这个问题。

改用事件委托:

输入搜索时,可以用防抖debounce等优化方式,减少http请求;

这里以滚动条事件举例:防抖函数 onscroll 结束时触发一次,延迟执行

节流函数:只允许一个函数在N秒内执行一次。滚动条调用接口时,可以用节流throttle等优化方式,减少http请求;

下面还是一个简单的滚动条事件节流函数:节流函数 onscroll 时,每隔一段时间触发一次,像水滴一样

参考链接: https://zhuanlan.zhihu.com/p/113864878?from_voters_page=true

一、 让代码简洁:一些简略的表达方式也会产生很好的优化

eg:x=x+1在不影响功能的情况下可以简写为x++

二、 变量名方法名尽量在不影响语意的情况下简单。(可以选择首字母命名)

eg:定义数组的长度可以取名为:ArrLen而不需要取为ArrayLength。

三、 关于JS的循环,循环是一种常用的流程控制。

JS提供了三种循环:for()、while()、for(in)。在这三种循环中for(in)的效率最差,因为它需要查询Hash键,因此应尽量少用for(in)循环,for()、while()循环的性能基本持平。当然,推荐使用for循环,如果循环变量递增或递减,不要单独对循环变量赋值,而应该使用嵌套的++或–运算符。

四、 如果需要遍历数组,应该先缓存数组长度,将数组长度放入局部变量中,避免多次查询数组长度。

因为我们常常要根据字符串、数组的长度进行循环,而通常这个长度是不变的,比如每次查询a.length,就要额外进行一个操作,而预先把var len=a.length,则就少了一次查询。

五、 尽量选用局部变量而不是全局变量。

局部变量的访问速度要比全局变量的访问速度更快,因为全局变量其实是window对象的成员,而局部变量是放在函数的栈里的。

六、 尽量少使用eval。

每次使用eval需要消耗大量时间,这时候使用JS所支持的闭包可以实现函数模板。

七、 减少对象查找

因为JavaScript的解释性,所以a.b.c.d.e,需要进行至少4次查询操作,先检查a再检查a中的b,再检查b中的c,如此往下。所以如果这样的表达式重复出现,只要可能,应该尽量少出现这样的表达式,可以利用局部变量,把它放入一个临时的地方进行查询。

八、 字符串连接。

如果是追加字符串,最好使用s+=anotherStr操作,而不是要使用s=s+anotherStr。

如果要连接多个字符串,应该少使用+=,如s+=as+=bs+=c应该写成s+=a + b + c;

而如果是收集字符串,比如多次对同一个字符串进行+=操作的话,最好使用一个缓存。怎么用呢?使用JavaScript数组来收集,最后使用join方法连接起来,如下

var buf = new Array()for(var i = 0i <100i++){ buf.push(i.toString())}var all = buf.join("")

九、 类型转换

1. 把数字转换成字符串,应用"" + 1,虽然看起来比较丑一点,但事实上这个效率是最高的,性能上来说:("" +) >String() >.toString() >new String()

尽量使用编译时就能使用的内部操作要比运行时使用的用户操作要快。

String()属于内部函数,所以速度很快,而.toString()要查询原型中的函数,所以速度逊色一些,new String()用于返回一个精确的副本。

2. 浮点数转换成整型,这个更容易出错,很多人喜欢使用parseInt(),其实parseInt()是用于将字符串转换成数字,而不是浮点数和整型之间的转换,我们应该使用Math.floor()或者Math.round()。Math是内部对象,所以Math.floor()其实并没有多少查询方法和调用的时间,速度是最快的。

3. 对于自定义的对象,如果定义了toString()方法来进行类型转换的话,推荐显式调用toString(),因为内部的操作在尝试所有可能性之后,会尝试对象的toString()方法尝试能否转化为String,所以直接调用这个方法效率会更高

十、 尽量作用JSON格式来创建对象,而不是var obj=new Object()方法。

因为前者是直接复制,而后者需要调用构造器,因而前者的性能更好。

十一、 当需要使用数组时,也尽量使用JSON格式的语法,

使用JSON格式的语法即直接使用如下语法定义数组:[parrm,param,param...],而不是采用new Array(parrm,param,param...)这种语法。因为使用JSON格式的语法是引擎直接解释的。而后者则需要调用Array的构造器。

十二、 对字符串进行循环操作,例如替换、查找,就使用正则表达式。

因为JS的循环速度比较慢,而正则表达式的操作是用C写成的API,性能比较好。

十三、 插入HTML

很多人喜欢在JavaScript中使用document.write来给页面生成内容。事实上这样的效率较低,如果需要直接插入HTML,可以找一个容器元素,比如指定一个div或者span,并设置他们的innerHTML来将自己的HTML代码插入到页面中。

十四、 对象查询

使用[“”]查询要比.items()更快

十五、 定时器

如果针对的是不断运行的代码,不应该使用setTimeout,而应该是用setInterval。setTimeout每次要重新设置一个定时器。

十六、 尽量减少DOM调用

在Web开发中,JavaScript的一个很重要的作用就是对DOM进行操作。可是对DOM的操作是非常昂贵的,因为这会导致浏览器执行回流 (reflow)操作。我们应该尽可能的减少DOM操作。

网站代码优化,去掉网站多余的代码,以减少网站的大小,提高网站的加载速度和用户体验。

网站代码优化是站长必须要掌握的基本技能,这关系到搜索引擎蜘蛛是否会对网站感兴趣,冗长无用的代码会让蜘蛛很难理解,增加蜘蛛抓取网站的难度,同时,网页的精简还关系到网站的加载速度,对用户体验至关重要。网站代码优化主要从一下几个方面进行优化。

1、HEAD部分代码规范化

2、使用DIV+CSS布局网页

一些网站会使用外部文件,将css和js放在外部文件中,页面html中只要放一样代码调用就可以了,有时候我们去查看的一些源文件代码,会看到很多css代码以及javasript代码,将javascript放置在网站页面的html文件中的最前面,而真正能用到得一些文字部分这被推倒了html的后面,这种代码都需要精简。

3、CSS优化

CSS是页面效果呈现中非常重要的组成部分,它包括颜色、大小尺寸、背景和字体等。写CSS很简单很容易,但是要想写出精炼的CSS代码还是有很多技巧的。

(1)、CSS位置

CSS说明如果出现在网站之后,页面需要重新渲染,打开速度受到影响,所有css定义代码的位置要放到网站之前。

(2)、css sprite技术

网站上的一些图片可以采用css sprite技术进行合并,减少加载请求次数,从而提高网页的加载速度。

(3)、CSS代码优化

通过对css代码属性的简写、移除多余的结构(frameworks)和重设(resets)等一系列的方法和技巧来简化css代码,减小css文件的大小。

(4)、尽量不要使用内嵌式CSS

内嵌式CSS分为两种,一是在head区域的普通内嵌式二是在标签内出现的行内内嵌式CSS,无论是何种内嵌CSS方式结果都会提升页面的体积,对此,我们可以尽量使用外调式的CSS来为站点页面的体积瘦身。

4、JS优化

JS优化与其他语言的优化也仍然有相同之处,JS优化的关键,仍然是要把精力放在最关键的地方,也就是瓶颈上,一般来说,瓶颈总是出现在大规模循环的地方,这倒不是说循环本身有性能问题,而是循环会迅速放大可能存在的性能问题。

(1)、JS位置

网页代码中对js进行优化的时候,建议将JS放在页面最后,这样可以加快页面打开速度。

(2)、合并JS

合并相同域名下的js,通过减少网络连接次数从而提高网页的打开速度。

(3)、LazyLoad(延迟加载)技术

Lazy

Load是一个用JavaScript编写的jQuery插件,它可以延迟加载长页面中的图片,在浏览器可视区域外的图片不会被载入,直到用户将页面滚动到它们所在的位置

(4)、JS代码外部的调用

我们知道当前的搜索引擎还是不能够识别JS代码的,倘若在网站中出现大批量的js代码网站在收录上就会出现困难,而我们要做的就是将用到Javascript代码用外部调用的形式放在网站中,这样可以简化搜索引擎的工作,也不会在无形中衍生出无效代码累及网站。

不仅如此,可以采用外部调用的还有css代码,建站之初可以将网站的文字、颜色定义在css代码文件中,尽量不要在页面代码内出现过多的样式代码。

(5)、降低页面对于JS的依赖性

现在来说,JS对于搜索引擎并不不友好,虽然有消息称搜索引擎不会对JS有厌恶的情绪,但是多一事不如少一事,虽然JS可以制作出很多的效果,但是网页中大量的JS将影响蜘蛛对页面的抓取和增加网页体积,尤其是页面的关键位置如导航栏,尽量采用DIV+CSS的设计方法。

5、TABLE标签的缩减

table标签是现在大多数上线网站中最为常见的代码形式,原因根本在于table在建立网站时比较快捷,但是这也就影响了网站的后期优化。

相对于div+css布局的精简代码网站来说,它的占位比较大,所以,在建站时候,尽量是少用表格,即便是要使用表格时,嵌套式表格也要尽量少用,以免产生冗杂代码

那么,现在的网站用什么做呢?很多程序员第一想法就是采用CSS去做,采用CSS去排版,这种做法呢,就使页面中的表格大大的降低了,但是,网站也不能没有表格,有些事必须使用到得,使用表格本身没什么,但是有很多网站都采用嵌套表格,一般这样的表格形式会给网站产生大量的垃圾代码,并且这些垃圾代码都是没有任何用处的代码,这一类代码也是我们网站需要精简的代码之一。

6、代码注释省略

很多程序人员在编写代码是都习惯在别人看不懂的地方给出一段注释,这些代码往往是为了几个程序员之间的协同工作,对于外人以及搜索引擎来说没有任何用处,相反还会给搜索引擎蜘蛛带来一定的困扰。

打开页面代码我们经常会看到一些注释代码,这是程序员为了表明代码意义而做的注释,其实这些打开不必,因为对于搜索引擎而言,它们是不存在任何意义的,只是会增加了页面代码的容量,这样对于网站不会有什么利处,不如直接省略。

7、清除页面中多余的代码

有的网站以为制作者的代码书写习惯问题,页面会有很多空格代码,比如:空格代码、style和font重复定义的代码,不要小看这些体积很小的代码,积攒多了,也会使我们的网站异常的臃肿。

很多网站都是采用的DIV+CSS,在CSS中定义了文字的字体,颜色,以及页面的排版,但是在网站的其他地方还用了以style以及font来再次定义字体字体,这些代码完全没有必要重复定义,属于可以精简的代码。

8、将html控制方式转换为CSS控制

很多网页设计者习惯在标签内对内容进行控制,比如img标签里通过width和height来控制图片的大小,尽量将这些代码转换成外调式的CSS,使网页代码更加的瘦身。

9、缓存静态资源

通过设置浏览器缓存,将css、js等不太经常更新的文件缓存在浏览器端,这样同一访客再次访问网站的时候,浏览器就可以从浏览器的缓存中获取css、js等,而不必每次都从服务器读取,这样在一定程度上加快了网站的打开速度,又可以节约服务器流量。

10、网页压缩技术

对于网页压缩而言,相信各位站长都比较熟悉,主要是启用服务器Gzip,对页面Gzip压缩,减少元素的体积,从而减少数据的传输,进而提高网页的加载速度,这个功能需要服务器的支持,GZIP压缩一般能对网页进行30%-80%的压缩,是最重要的一种优化效果。

总之,通过代码优化来起到网站优化作用的方式还有很多,在这只是随意的说了其中比较常见的而已。