前端性能优化原理

网络加载类

1. 减少HTTP资源请求次数

在前端页面中,通常建议尽可能合并静态资源图片、JavaScript和CSS代码,减少页面请求数和资源请求消耗,这样可以缩短页面首次访问的用户等待时间。通过构建工具合并雪碧图、CSS、JavaScript文件等都是为了减少HTTP资源请求次数。另外也要尽量避免重复的资源,防止增加多余请求。

2. 减小HTTP请求大小

除了减少HTTP资源请求次数,也要尽量减小每个HTTP请求的大小。如减少没必要的图片、JavaScript、CSS及HTML代码,对文件进行压缩优化,或者使用gzip压缩传输内容等都可以用来减小文件大小,缩短网络传输等待时延。

3. 将CSS或JavaScript放到外部文件中,避免使用<style><script>标签直接引入

在HTML文件中引用外部资源可以有效利用浏览器的静态资源缓存,但有时候在移动端页面CSS或JavaScript比较简单的情况下为了减少请求,也会将CSS或JavaScript直接写到HTML里面,具体要根据CSS或JavaScript文件的大小和业务的场景来分析。如果CSS或JavaScript文件内容较多,业务逻辑较复杂,建议放到外部文件引入。

4. 避免页面中空的hrefsrc

<link>标签的href属性为空,或<script><img><iframe>标签的src属性为空时,浏览器在渲染的过程中仍会将href属性或src属性中的空内容进行加载,直至加载失败,这样就阻塞了页面中其他资源的下载进程,而且最终加载到的内容是无效的,因此要尽量避免。

5. 为HTML指定Cache-ControlExpires

为HTML内容设置Cache-ControlExpires可以将HTML内容缓存起来,避免频繁向服务器端发送请求。在页面Cache-ControlExpires头部有效时,浏览器将直接从缓存中读取内容,不向服务器端发送请求。

<meta http-equiv="Cache-Control" content="max-age=7200">
<meta http-equiv="Expires" content="Mon,20Jul201623:00:00GMT">
6. 合理设置EtagLast-Modified

合理设置EtagLast-Modified使用浏览器缓存,对于未修改的文件,静态资源服务器会向浏览器端返回304,让浏览器从缓存中读取文件,减少Web资源下载的带宽消耗并降低服务器负载。

<meta http-equiv="last-modified" content="Sun,05 Nov 2017 13:45:57 GMT">
7. 减少页面重定向

页面每次重定向都会延长页面内容返回的等待延时,一次重定向大约需要200毫秒不等的时间开销(无缓存),为了保证用户尽快看到页面内容,要尽量避免页面重定向。

8. 使用静态资源分域存放来增加下载并行数

浏览器在同一时刻向同一个域名请求文件的并行下载数是有限的,因此可以利用多个域名的主机来存放不同的静态资源,增大页面加载时资源的并行下载数,缩短页面资源加载的时间。通常根据多个域名来分别存储JavaScript、CSS和图片文件。

<link rel="stylesheet" href="//cdn1.domain.com/path/main.css" >
<script src="//cdn2.domain.com/path/main.js"></script>
9. 使用静态资源CDN来存储文件

如果条件允许,可以利用CDN网络加快同一个地理区域内重复静态资源文件的响应下载速度,缩短资源请求时间。

10. 使用CDN Combo下载传输内容

CDN Combo是在CDN服务器端将多个文件请求打包成一个文件的形式来返回的技术,这样可以实现HTTP连接传输的一次性复用,减少浏览器的HTTP请求数,加快资源下载速度。例如同一个域名CDN服务器上的a.js,b.js,c.js就可以按如下方式在一个请求中下载。

<script src="//cdn.domain.com/path/a.js,b.js,c.js"></script>
11. 使用可缓存的AJAX

对于返回内容相同的请求,没必要每次都直接从服务端拉取,合理使用AJAX缓存能加快AJAX响应速度并减轻服务器压力。

$.ajax({
    url : url,
    type : 'get',
    cache : true, //推荐使用缓存
    data : {},
    success (){//...},
    error (){//...}
});
12. 使用GET来完成AJAX请求

使用XMLHttpRequest时,浏览器中的POST方法会发起两次TCP数据包传输,首先发送文件头,然后发送HTTP正文数据。而使用GET时只发送头部,所以在拉取服务端数据时使用GET请求效率更高。

$.ajax({
    url : url,
    type : 'get', //推荐使用get完成请求
    data : {},
    success (){//...},
    error(){//...}
});
13. 减少Cookie的大小并进行Cookie隔离

HTTP请求通常默认带上浏览器端的Cookie一起发送给服务器,所以在非必要的情况下,要尽量减少Cookie来减小HTTP请求的大小。对于静态资源,尽量使用不同的域名来存放,因为Cookie默认是不能跨域的,这样就做到了不同域名下静态资源请求的Cookie隔离。

14. 缩小favicon.ico并缓存

有利于favicon.ico的重复加载,因为一般一个Web应用的favicon.ico是很少改变的。

15. 推荐使用异步JavaScript资源

异步的JavaScript资源不会阻塞文档解析,所以允许在浏览器中优先渲染页面,延后加载脚本执行。例如JavaScript的引用可以如下设置,也可以使用模块化加载机制来实现。

<script src="main.js" defer></script>
<script src="main.js" async></script>

使用async时,加载和渲染后续文档元素的过程和main.js的加载与执行是并行的。使用defer时,加载后续文档元素的过程和main.js的加载是并行的,但是main.js的执行要在页面所有元素解析完成之后才开始执行。

16. 消除阻塞渲染的CSS及JavaScript

对于页面中加载时间过长的CSS或JavaScript文件,需要进行合理拆分或延后加载,保证关键路径的资源能快速加载完成。

17. 避免使用CSS import引用加载CSS

CSS中的@import可以从另一个样式文件中引入样式,但应该避免这种用法,因为这样会增加 CSS 资源加载的关键路径长度,带有@import的CSS样式需要在CSS文件串行解析到@import时才会加载另外的CSS文件,大大延后CSS渲染完成的时间。

<!--不推荐-->
<style>
    @import "path/main.css";
</style>

<!--推荐-->
<link rel="stylesheet" href="//cdn1.domain.com/path/main.css" >
18. meta dns prefetch设置DNS预解析

设置文件资源的DNS预解析,让浏览器提前解析获取静态资源的主机IP,避免等到请求时才发起DNS解析请求。通常在移动端HTML中可以采用如下方式完成。

<!--cdn域名预解析-->
<meta http-equiv="x-dns-prefetch-control" content="on" >
<link rel="dns-prefetch" href="//cdn.domain.com" >
19. 资源预加载

对于移动端首屏加载后可能会被使用的资源,需要在首屏完成加载后尽快进行加载,保证在用户需要浏览时已经加载完成,这时候如果再去异步请求就显得很慢。

20. 首屏加载和按需加载,非首屏内容滚屏加载,保证首屏内容最小化

由于移动端网络速度相对较慢,网络资源有限,因此为了尽快完成页面内容的加载,需要保证首屏加载资源最小化,非首屏内容使用滚动的方式异步加载。一般推荐移动端页面首屏数据展示延时最长不超过3秒。推荐首屏所有资源大小不超过 1014KB,即大约不超过 1MB。

页面渲染类

1. 把CSS资源引用放到HTML文件顶部

一般推荐将所有CSS资源尽早指定在HTML文档<head>中,这样浏览器可以优先下载CSS并尽早完成页面渲染。

2. JavaScript资源引用放到HTML文件底部

JavaScript资源放到HTML文档底部可以防止JavaScript的加载和解析执行对页面渲染造成阻塞。由于JavaScript资源默认是解析阻塞的,除非被标记为异步或者通过其他的异步方式加载,否则会阻塞HTML DOM解析和CSS渲染的过程。

3. 尽量预先设定图片等大小

在加载大量的图片元素时,尽量预先限定图片的尺寸大小,否则在图片加载过程中会更新图片的排版信息,产生大量的重排

4. 不要在HTML中直接缩放图片

在HTML中直接缩放图片会导致页面内容的重排重绘,此时可能会使页面中的其他操作产生卡顿,因此要尽量减少在页面中直接进行图片缩放。

5. 减少DOM元素数量和深度

HTML中标签元素越多,标签的层级越深,浏览器解析DOM并绘制到浏览器中所花的时间就越长,所以应尽可能保持DOM元素简洁和层级较少。

<!--不推荐-->
<div>
    <span>
        <a href="javascript:void(0);">
            <img src="./path/photo.jpg" alt="图片">
        </a>
    </span>
</div>

<!--推荐-->
<img src="./path/photo.jpg" alt="图片" >
6. 尽量避免在选择器末尾添加通配符

CSS解析匹配到渲染树的过程是从右到左的逆向匹配,在选择器末尾添加通配符至少会增加一倍多计算量。

7. 减少使用关系型样式表的写法

直接使用唯一的类名即可最大限度的提升渲染引擎绘制渲染树等效率

8. 尽量减少使用JS动画

JS直接操作DOM极容易引起页面的重排

9. CSS 动画使用translatescale代替top、height

尽量使用CSS3的translate、scale属性代替top、leftheight、width,避免大量的重排计算

10. 尽量避免使用<table><iframe>

<table>内容的渲染是将table的DOM渲染树全部生成完并一次性绘制到页面上的,所以在长表格渲染时很耗性能,应该尽量避免使用它,可以考虑使用列表元素<ul>代替。尽量使用异步的方式动态添加iframe,因为iframe内资源的下载进程会阻塞父页面静态资源的下载与CSS及HTML DOM的解析。

11. 避免运行耗时的JavaScript

长时间运行的JavaScript会阻塞浏览器构建DOM树、DOM渲染树、渲染页面。所以,任何与页面初次渲染无关的逻辑功能都应该延迟加载执行,这和JavaScript资源的异步加载思路是一致的。

12. 避免使用CSS表达式或CSS滤镜

CSS表达式或CSS滤镜的解析渲染速度是比较慢的,在有其他解决方案的情况下应该尽量避免使用。

//不推荐
.opacity{
    filter : progid : DXImageTransform.Microsoft.Alpha( opacity = 50 );
}
13. 使用Viewport固定屏幕渲染,可以加速页面渲染内容

一般认为,在移动端设置Viewport可以加速页面的渲染,同时可以避免缩放导致页面重排重绘。在移动端固定Viewport设置的方法如下。

<!--设置viewport不缩放-->
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
14. 避免各种形式重排重绘

页面的重排重绘很耗性能,所以一定要尽可能减少页面的重排重绘,例如页面图片大小变化、元素位置变化等这些情况都会导致重排重绘。

15. 使用CSS3动画,开启GPU加速

使用CSS3动画时可以设置transform:translateZ(0)来开启移动设备浏览器的GPU图形处理加速,让动画过程更加流畅,但需要注意的是,在Native WebView下GPU加速有几率产生 App Crash。

-webkit-transform:translateZ(0);
    -ms-transform:translateZ(0);
     -o-transform:translateZ(0);
        transform:translateZ(0);
16. 合理使用CanvasrequestAnimationFrame

选择CanvasrequestAnimationFrame等更高效的动画实现方式,尽量避免使用setTimeoutsetInterval等方式来直接处理连续动画。

17. SVG代替图片

部分情况下可以考虑使用SVG代替图片实现动画,因为使用SVG格式内容更小,而且SVG DOM结构方便调整。

6. 不滥用float

在DOM渲染树生成后的布局渲染阶段,使用float的元素布局计算比较耗性能,所以尽量减少float的使用,推荐使用固定布局或flex-box弹性布局的方式来实现页面元素布局。

18. 不滥用web字体或过多font-size

声明过多的font-size声明会增加字体的大小计算,而且也没有必要的。

19. 做好脚本容错

脚本容错可以避免「非正常环境」的执行错误影响页面的加载和不相关功能的使用。

图片类

1. 图片压缩处理

在移动端,通常要保证页面中一切用到的图片都是经过压缩优化处理的,而不是以原图的形式直接使用的,因为那样很消耗流量,而且加载时间更长。

2. 使用较小的图片

合理使用base64内嵌图片在页面使用的背景图片不多且较小的情况下,可以将图片转化成base64编码嵌入到HTML页面或CSS文件中,这样可以减少页面的HTTP请求数。需要注意的是,要保证图片较小,一般图片大小超过2KB就不推荐使用base64嵌入显示了。

.class-name{
    background-image : url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAALCAMAAABxsOwqAAAAYFBMVEWnxwusyQukxQudwQyZvgyhxAyfwgyxzAsUHQGOuA0aJAERGAFIXwSTugyEqgtqhghQZgUwQQIpOQKbuguVtQuKrAuCowp2kQlheghTbQZHWQU7SwVAVgQ6TgQlLwMeKwFOemyQAAAAVElEQVQI1y3JVRaAIAAF0UconXbvf5ei8HfPDIQQhBAAFE10iKig3SLRNN4SP/p+N08VC0YnfIlNWtqIkhg/TPYbCvhqdHAWRXPZSp3g3CWZvVLXC6OJA3ukv0AaAAAAAElFTkSuQmCC');
}
3. 使用更高压缩比格式的图片

使用具有较高压缩比格式的图片,如webp(需要设计降级兼容方案)等。在同等图片画质的情况下,高压缩比格式的图片体积更小,能够更快完成文件传输,节省网络流量。

<img src="//cdn.domain.com/path/photo.webp" alt="webp格式图片" >
4. 图片懒加载

为了保证页面内容的最小化,加速页面的渲染,尽可能节省移动端网络流量,页面中的图片资源推荐使用懒加载实现,在页面滚动时动态载入图片。

<img data-src="//cdn.domain.com/path/photo.jpg" alt="懒加载图片" >
5. 使用MediaQuerysrcset根据不同屏幕加载不同大小图片

针对不同的移动端屏幕尺寸和分辨率,输出不同大小的图片或背景图能保证在用户体验不降低的前提下节省网络流量,加快部分机型的图片加载速度,这在移动端非常值得推荐。

6. 使用iconfont代替图片图标

在页面中尽可能使用iconfont来代替图片图标,这样做的好处有以下几个:

  • 使用iconfont体积较小,而且是矢量图,因此缩放时不会失真;
  • 可以方便地修改图片大小尺寸和呈现颜色。

但是需要注意的是,iconfont引用不同webfont格式时的兼容性写法,根据经验推荐尽量按照以下顺序书写,否则不容易兼容到所有的浏览器上。

@font-face{
    font-family:iconfont;
    src:url("./iconfont.eot");
    src:url("./iconfont.eot?#iefix")  format("eot"),
        url("./iconfont.woff")  format("woff"),
        url("./iconfont.ttf")  format("truetype");
}
7. 定义图片大小限制

加载的单张图片一般建议不超过30KB,避免大图片加载时间长而阻塞页面其他资源的下载,因此推荐在10KB以内。如果用户上传的图片过大,建议设置告警系统,帮助我们观察了解整个网站的图片流量情况,做出进一步的改善。

8. 强缓存策略

对于一些「永远」不会变的图片可以使用强缓存的方式缓存在用户的浏览器上。

架构协议类

1. 使用后端数据渲染

使用后端数据渲染的方式可以加快页面内容的渲染展示,避免空白页面的出现,同时可以解决移动端页面SEO的问题。如果条件允许,后端数据渲染是一个很不错的实践思路。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343