浅谈前端性能优化(移动端)

上一篇讲了PC端的部分:前端性能优化(PC端),这次继续说移动端的。相对于PC端的,移动web浏览器上有一些明显的特点:设备的屏幕小、新特性兼容性较好、支持一些比较新的HTML5和CSS3、需要与Native应用交互等。但移动端可用的CPU资源和网络资源极为有限,因此要做好移动端web上的优化往往需要考虑做更多的事情。首先在移动web的前端页面渲染中,PC的优化规则同样适用,此外针对浏览器也要做一些更细节的优化达到更好的效果。需要注意的是,并不是移动端的优化在PC端不适用,而是由于兼容性的原因,一些优化规则在移动端更具有代表性,所以也是为什么我把DNS预解析,离线缓存,HTTP2协议,GPU加速等东西放到这部分来讲...

和上部分一样,只是提供索引,涉及的知识点比较多请自行搜索

网络加载类

1. 首屏数据请求提前,避免JavaScript文件加载后才请求渲染

为了进一步提示页面加载速度,可以考虑将页面的数据请求尽可能提前,避免在JavaScript文件加载完成后才去请求数据。通常数据请求是页面内容渲染中关键路径最长的部分,而且不能并行,所以如果数据请求能提前的话,可以极大程度上缩短页面内容的渲染完成时间。

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

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

3. 模块化资源并行下载

主要指模块化JavaScript资源的异步加载,例如AMD的异步模块,使用并行的加载方式能够缩短多个文件资源的加载时间。

4. inline首屏必备的CSS和JavaScript

通常为了在HTML加载完成时能使浏览器中有基本的样式,需要将页面渲染时必备的CSS和JS通过script或style的方式内联到页面中,避免页面HTML载入完成到页面内容展示这段过程中页面出现空白

5. meta dns prefetch设置DNS预解析

设置文件资源的DNS预解析,能让浏览器提前解析获取静态资源的主机IP,避免等到请求的时候才发起DNS解析。

<!-- cdn域名预解析 -->
<meta http-equiv='x-dns-prefetch-control' content='on'>
<link rel="dns-prefetch" href="//x.autoimg.cn">

6. 资源预加载

首屏加载完成后可能会使用的资源,我们可以用 link标签声明特定文件的预加载

<link rel='subresource' href='main.css'>

<link rel='prefetch' href='secondary.js'>

注意:只有可缓存的资源才进行预加载,否则浪费资源!

7. Pre render预渲染

预渲染意味着我们提前加载好用户即将访问的下一个页面,否则进行预渲染这个页面将浪费资源,慎用!

<link rel='prerender' href='//j.autohome.com.cn'>

8. 合理利用MTU策略

通常情况下,TCP网络传输的最大传输单元(MTU)为1500B,即一个RTT(Round-Trip Time,网络请求返回时间)内可以传输的数据量最大为1500字节(为什么以太网mtu值被设定为1500 - 知乎)。因此在前后端分离的开发模式中,尽量保证页面的HTML内容在1KB以内,这样整个HTML内容的请求就可以在一个RTT内完成,最大限度的提高了HTML载入速度

缓存

1. 合理利用浏览器缓存

除了上一节说到的Cache-Control、Expires、Etag和Last-Modified来设置HTTP缓存外,在移动端还可以使用localstorage等来保存ajax返回的数据,或者使用localstorage保存CSS或JS等静态资源,实现移动端的离线应用,尽可能的减少网络请求,保证静态资源内容的快速加载。

2. 静态资源离线方案

对于移动端或者混合应用,可以设置离线文件或离线包机制让静态资源请求从本地读取,加快资源载入速度,并实现离线更新。这块推荐叶小钗大神的前端优化带来的思考,浅谈前端工程化 可以挑着看。离线资源这块东西太多了,以后有时间单独拿出来写

3. 尝试使用 AMP HTML

AMP HTML 可以作为优化前端页面性能的一个解决方案,使用AMP Component中的元素来代替原始页面元素进行直接渲染 [译]关于谷歌的AMP,你需要知道这些。

图片类

1. 图片压缩处理

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

2. 使用较小的图片,合理使用base64内嵌图片

在页面使用的背景图片不多且比较小的情况下,可以把图片转成base64编码嵌入到html页面或者CSS文件中,这样可以减少页面的HTTP请求数。需要注意的是,要保证图片较小,一般超过5kb的就不推荐base64嵌入显示了(前端开发中,使用base64图片的弊端是什么? - 知乎

3. 使用更高压缩比格式的图片

使用具有较高压缩比格式的图片,如webp等。在同等图片画质的情况下,高压缩比格式的图片体积更小,能够更快的完成文件传输,节省网站流量。

![](//x.autoimg.cn/path/photo.webp)

4. 图片懒加载

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

5. 使用Media Query 或者 srcset 根据不同屏幕加载不同大小的图片

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

6. 使用iconfont代替图片图标

iconfont体积较小而且是矢量图,因此缩放不会失真,还可以方便修改图片大小和呈现的颜色,但是需要注意iconfont引用不同webfont格式会有兼容问题。

7. 定义图片大小限制

加载单张图片不建议超过30KB,避免大图片加载时间过长而阻塞页面其他资源的下载。如果用户上传的图片过大,建议设置限制。

脚本类

1. 尽量使用id选择器

选择页面DOM元素时尽量使用id选择器,因为id选择器速度最快

2. 合理的缓存dom对象

对于需要重复使用的dom对象,要优先设置缓存变量,避免每次使用时都要从整个dom树重新查找。

// 不推荐
$("#mod .active").removeClass('active');
$("#mod .not-active").addClass("active");

// 推荐
const $mod = $("#mod");
$mod.find(".active").removeClass("active")
$mod.find(".not-active").addClass("active")

jq 上有很多优化建议,详情搜索JQ 优化

3. 页面元素尽量使用事件代理,避免事件直接绑定

使用事件代理可以避免对每个元素都进行绑定。并且可以避免出现内存泄漏以及需要动态添加元素的事件绑定问题

// 不推荐
$(".btn").click( _ => console.log("hello") )

// 推荐
$(document).on("click", ".btn", _ => console.log("world"))

4. 使用touch代理click

由于移动端屏幕的设计,touch事件和click事件触发之间存在300ms延迟,所以在页面没有touchmove实现滚动处理的情况,可以用touchstart代替元素的click事件,加快页面点击的响应速度,提高用户体验。但同时也需要注意页面重叠元素touch动作的点透问题。

// 不推荐
$("body").on("click",".btn",function(){ console.log(this) });

// 推荐
$("body").on("tap",".btn",function(){ console.log(this) });
// tap为zepto用touch事件封装的

5. 避免touchmove,scroll等连续事件处理

需要对这类高频触发回调的事件设置函数节流(throttle | debounce),避免频繁的事件调用导致移动端页面卡顿

6. 避免使用eval、with,使用join代替连接符+,推荐使用ES6的模板字符串

基本的安全脚本编写问题,尽可能使用高效率的特性来完成这些操作,避免不规范或者不安全的写法。

7. 尽量使用ES6+的特性来编程

ES6+在一定程度上更高效,在chrome59版本对ES6做了深度优化之后,很多特性速度提升了80%左右,这也是未来规范的需要。ES8前段时间也已经落地了,如果你还没有掌握ES6语法的话,抓紧时间学吧...

渲染类

1. 使用viewport固定屏幕渲染,可以加速页面渲染内容

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

// 利用meta标签对viewport进行控制
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">

2. 避免各种形式重排(reflow)重绘(redraw)

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

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

使用CSS3动画可以设置transform: translateZ(0)来开启移动设备浏览器的GPU图形处理加速。这里安利一波京东凹凸实验室,讲的挺好的,GPU加速是什么

4. 合理使用canvas和requestAnimationFrame

选择canvas或者requestAnimationFrame等更高效的动画实现方式,避免使用settimeout、setInterval等方式直接处理连续动画

5. SVG代替图片

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

6. 不滥用float

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

7. 不滥用web字体或过多的font-size声明

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

架构协议

1. 尝试使用SPDY和HTTP2

在条件允许的情况下可以考虑使用SPDY协议来进行文件资源传输,利用连接复用加快传输过程,缩短资源加载时间。HTTP2在未来也一定会成为主流的

2. 使用后端数据渲染

SSR( Server Side Rendering,服务端渲染)的方式可以加速页面内容的渲染展示,避免空白页面的出现,同时可以解决页面SEO的问题。条件允许的话,SSR是一个很好的实践思路。百度SSP单页式应用性能优化实践React 同构实践与思考

3. 使用Native View代替DOM的性能劣势

可以尝试使用Native View的MNV* 开发模式来避免HTML DOM性能慢的问题,目前使用MNV* 的开发模式已经可以将页面内容渲染体验做到接近客户端Native应用的体验了。


关于页面优化的常用技术手段和思路主要包括以上这些,有部分遗漏欢迎补充。大家可以根据需要将这些方法应用到自己的项目中去,想全部做到几乎是不可能的,但做到用户可以接受的程度还是很容易的。

软件工程没有银弹,在我们做到了极致优化的同时也需要付出很大的代价,这也是前端优化的一个问题。理论上这些优化都可以实现,但是我们也要懂得权衡,优化提升了用户体验,使数据加载更快,但是项目代码却可能打乱,异步内容要拆分出来,首屏雪碧图可能要拆分2个或更多,项目代码维护成本成倍增加,项目结构也可能变得混乱。任何一部分优化都可以做得很深入,但不一定都值得。在优化的同时考虑性价比,这才是我们作为一名前端工程师处理前端优化时该具有的正确思维。

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

推荐阅读更多精彩内容

  • 网络加载类 首屏数据请求提前,避免JavaScript文件加载后才请求渲染为了进一步提示页面加载速度,可以考虑将页...
    fangdown阅读 709评论 0 1
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,506评论 25 707
  • 围绕前端的性能多如牛毛,涉及到方方面面,以我我们将围绕PC浏览器和移动端浏览器的优化策略进行罗列注意,是罗列不是展...
    流动码文阅读 674评论 0 0
  • 前言 前端的工作并不仅仅是实现「视觉&交互稿」,想要开发一个高性能易维护的「完美」站点并未易事,针对前端的性能优化...
    木羽zwwill阅读 625评论 0 4
  • 2015年春,从包头去成陵的路上路过响沙湾,小徐说:“在响沙湾,从沙丘上往下滑,沙子会发出轰隆隆的声音”。 ...
    丫头利贞阅读 705评论 0 1