在前端页面中,一般建议尽量合并静态资源图片、JavaScript 或 CSS 代码,减小页面请求数和资源请求消耗,这样能够缩短页面首次访问的用户等待时间。经过构建工具合并雪碧图、CSS、JavaScript 文件等都是为了减小 HTTP 资源请求次数。另外也要尽可能避免重复的资源,防止增长多余请求。javascript
除了减小 HTTP 资源请求次数,也要尽可能减少每一个 HTTP 请求的大小。如减小不必的图片、JavaScript、CSS 及 HTML 代码,对文件进行压缩优化,或者使用 gzip 压缩传输内容等均可以用来减少文件大小,缩短网络传输等待时延。前面咱们使用构建工具来压缩静态图片资源以及移除代码中的注释并压缩,目的都是为了减少 HTTP 请求的大小。css
<style>
或 <script>
标签直接引入在 HTML 文件中引用外部资源能够有效利用浏览器的静态资源缓存,但有时候在移动端页面 CSS 或 JavaScript 比较简单的状况下为了减小请求,也会将 CSS 或 JavaScript 直接写到 HTML 里面,具体要根据 CSS 或 JavaScript 文件的大小和业务的场景来分析。若是 CSS 或 JavaScript 文件内容较多,业务逻辑较复杂,建议放到外部文件引入。html
<link rel="stylesheet" href="//cdn.domain.com/path/main.css" >
前端
...
java
<script src="//cdn.domain.com/path/main.js"></script>
web
当 <link>
标签的 href 属性为空,或 <script>
、 <img>
、 <iframe>
标签的 src 属性为空时,浏览器在渲染的过程当中仍会将 href 属性或 src 属性中的空内容进行加载,直至加载失败,这样就阻塞了页面中其余资源的下载进程,并且最终加载到的内容是无效的,所以要尽可能避免。ajax
<!--不推荐-->
编程
<img src="" alt="photo" >
后端
<a href="">点击连接</a>
跨域
为 HTML 内容设置 Cache-Control 或 Expires 能够将 HTML 内容缓存起来,避免频繁向服务器端发送请求。前面讲到,在页面 Cache-Control 或 Expires 头部有效时,浏览器将直接从缓存中读取内容,不向服务器端发送请求。
<meta http-equiv="Cache-Control" content="max-age=7200">
<meta http-equiv="Expires" content="Mon,20Jul201623:00:00GMT">
合理设置 Etag 和 Last-Modified 使用浏览器缓存,对于未修改的文件,静态资源服务器会向浏览器端返回 304,让浏览器从缓存中读取文件,减小 Web 资源下载的带宽消耗并下降服务器负载。
<meta http-equiv="last-modified" content="Sun,05 Nov 2017 13:45:57 GMT">
页面每次重定向都会延长页面内容返回的等待延时,一次重定向大约须要 200 毫秒不等的时间开销(无缓存),为了保证用户尽快看到页面内容,要尽可能避免页面重定向。
浏览器在同一时刻向同一个域名请求文件的并行下载数是有限的,所以能够利用多个域名的主机来存放不一样的静态资源,增大页面加载时资源的并行下载数,缩短页面资源加载的时间。一般根据多个域名来分别存储 JavaScript、CSS 和图片文件。
<link rel="stylesheet" href="//cdn1.domain.com/path/main.css" >
...
<script src="//cdn2.domain.com/path/main.js"></script>
若是条件容许,能够利用 CDN 网络加快同一个地理区域内重复静态资源文件的响应下载速度,缩短资源请求时间。
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>
对于返回内容相同的请求,不必每次都直接从服务端拉取,合理使用 AJAX 缓存能加快 AJAX 响应速度并减轻服务器压力。
$.ajax({
url : url,
type : 'get',
cache : true, //推荐使用缓存
data : {},
success (){//...},
error (){//...}
});
使用 XMLHttpRequest 时,浏览器中的 POST 方法会发起两次 TCP 数据包传输,首先发送文件头,而后发送 HTTP 正文数据。而使用 GET 时只发送头部,因此在拉取服务端数据时使用 GET 请求效率更高。
$.ajax({
url : url,
type : 'get', //推荐使用get完成请求
data : {},
success (){//...},
error(){//...}
});
HTTP 请求一般默认带上浏览器端的 Cookie 一块儿发送给服务器,因此在非必要的状况下,要尽可能减小 Cookie 来减少 HTTP 请求的大小。对于静态资源,尽可能使用不一样的域名来存放,由于 Cookie 默认是不能跨域的,这样就作到了不一样域名下静态资源请求的 Cookie 隔离。
有利于 favicon.ico 的重复加载,由于通常一个 Web 应用的 favicon.ico 是不多改变的。
异步的 JavaScript 资源不会阻塞文档解析,因此容许在浏览器中优先渲染页面,延后加载脚本执行。例如 JavaScript 的引用能够以下设置,也可使用模块化加载机制来实现。
<script src="main.js" defer></script>
<script src="main.js" async></script>
使用 async 时,加载和渲染后续文档元素的过程和 main.js 的加载与执行是并行的。使用 defer 时,加载后续文档元素的过程和 main.js 的加载是并行的,可是 main.js 的执行要在页面全部元素解析完成以后才开始执行。
对于页面中加载时间过长的 CSS 或 JavaScript 文件,须要进行合理拆分或延后加载,保证关键路径的资源能快速加载完成。
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" >
通常推荐将全部 CSS 资源尽早指定在 HTML 文档 <head>
中,这样浏览器能够优先下载 CSS 并尽早完成页面渲染。
JavaScript 资源放到 HTML 文档底部能够防止 JavaScript 的加载和解析执行对页面渲染形成阻塞。因为 JavaScript 资源默认是解析阻塞的,除非被标记为异步或者经过其余的异步方式加载,不然会阻塞 HTML DOM 解析和 CSS 渲染的过程。
在加载大量的图片元素时,尽可能预先限定图片的尺寸大小,不然在图片加载过程当中会更新图片的排版信息,产生大量的重排
在 HTML 中直接缩放图片会致使页面内容的重排重绘,此时可能会使页面中的其余操做产生卡顿,所以要尽可能减小在页面中直接进行图片缩放。
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="图片" >
CSS 解析匹配到 渲染树的过程是从右到左的逆向匹配,在选择器末尾添加通配符至少会增长一倍多计算量。
直接使用惟一的类名便可最大限度的提高渲染引擎绘制渲染树等效率
JS 直接操做 DOM 极容易引发页面的重排
尽可能使用 CSS3 的 translate、scale 属性代替 top、left 和 height、width,避免大量的重排计算
<table>
、 <iframe>
<table>
内容的渲染是将 table 的 DOM 渲染树所有生成完并一次性绘制到页面上的,因此在长表格渲染时很耗性能,应该尽可能避免使用它,能够考虑使用列表元素 <ul>
代替。尽可能使用异步的方式动态添加 iframe,由于 iframe 内资源的下载进程会阻塞父页面静态资源的下载与 CSS 及 HTML DOM 的解析。
长时间运行的 JavaScript 会阻塞浏览器构建 DOM 树、DOM 渲染树、渲染页面。因此,任何与页面初次渲染无关的逻辑功能都应该延迟加载执行,这和 JavaScript 资源的异步加载思路是一致的。
CSS 表达式或 CSS 滤镜的解析渲染速度是比较慢的,在有其余解决方案的状况下应该尽可能避免使用。
//不推荐
.opacity{
filter : progid : DXImageTransform.Microsoft.Alpha( opacity = 50 );
}
相对于桌面端浏览器,移动端 Web 浏览器上有一些较为明显的特色:设备屏幕较小、新特性兼容性较好、支持一些较新的 HTML5 和 CSS3 特性、须要与 Native 应用交互等。但移动端浏览器可用的 CPU 计算资源和网络资源极为有限,所以要作好移动端 Web 上的优化每每须要作更多的事情。首先,在移动端 Web 的前端页面渲染中,桌面浏览器端上的优化规则一样适用,此外针对移动端也要作一些极致的优化来达到更好的效果。须要注意的是,并非移动端的优化原则在桌面浏览器端就不适用,而是因为兼容性和差别性的缘由,一些优化原则在移动端更具表明性。
为了进一步提高页面加载速度,能够考虑将页面的数据请求尽量提早,避免在 JavaScript 加载完成后才去请求数据。一般数据请求是页面内容渲染中关键路径最长的部分,并且不能并行,因此若是能将数据请求提早,能够极大程度上缩短页面内容的渲染完成时间。
因为移动端网络速度相对较慢,网络资源有限,所以为了尽快完成页面内容的加载,须要保证首屏加载资源最小化,非首屏内容使用滚动的方式异步加载。通常推荐移动端页面首屏数据展现延时最长不超过 3 秒。目前中国联通 3G 的网络速度为 338KB/s(2.71Mb/s),因此推荐首屏全部资源大小不超过 1014KB,即大约不超过 1MB。
在移动端资源加载中,尽可能保证 JavaScript 资源并行加载,主要指的是模块化 JavaScript 资源的异步加载,例如 AMD 的异步模块,使用并行的加载方式可以缩短多个文件资源的加载时间。
一般为了在 HTML 加载完成时能使浏览器中有基本的样式,须要将页面渲染时必备的 CSS 和 JavaScript 经过 <script>
或 <style>
内联到页面中,避免页面 HTML 载入完成到页面内容展现这段过程当中页面出现空白。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>样例</title>
<meta >
<style>
/*必备的首屏CSS*/
html,body{
margin:0;
padding:0;
background-color:#ccc;
}
</style>
</head>
<body>
</body>
</html>
设置文件资源的 DNS 预解析,让浏览器提早解析获取静态资源的主机 IP,避免等到请求时才发起 DNS 解析请求。一般在移动端 HTML 中能够采用以下方式完成。
<!--cdn域名预解析-->
<meta http-equiv="x-dns-prefetch-control" content="on" >
<link rel="dns-prefetch" href="//cdn.domain.com" >
对于移动端首屏加载后可能会被使用的资源,须要在首屏完成加载后尽快进行加载,保证在用户须要浏览时已经加载完成,这时候若是再去异步请求就显得很慢。
一般状况下,咱们认为 TCP 网络传输的最大传输单元(Maximum Transmission Unit,MTU)为 1500B,即一个 RTT(Round-Trip Time,网络请求往返时间)内能够传输的数据量最大为 1500 字节。所以,在先后端分离的开发模式中,尽可能保证页面的 HTML 内容在 1KB 之内,这样整个 HTML 的内容请求就能够在一个 RTT 内请求完成,最大限度地提升 HTML 载入速度。
除了上面说到的使用 Cache-Control、Expires、Etag 和 Last-Modified 来设置 HTTP 缓存外,在移动端还可使用 localStorage 等来保存 AJAX 返回的数据,或者使用 localStorage 保存 CSS 或 JavaScript 静态资源内容,实现移动端的离线应用,尽量减小网络请求,保证静态资源内容的快速加载。
对于移动端或 Hybrid 应用,能够设置离线文件或离线包机制让静态资源请求从本地读取,加快资源载入速度,并实现离线更新。关于这块内容,咱们会在后面的章节中重点讲解。
AMP HTML 能够做为优化前端页面性能的一个解决方案,使用 AMP Component 中的元素来代替原始的页面元素进行直接渲染。
<!--不推荐-->
<video width="400" height="300" src="http://www.domain.com/videos/myvideo.mp4"
poster="path/poster.jpg">
<div fallback>
<p>Your browser doesn’t support HTML5 video</p>
</div>
<source type="video/mp4" src="foo.mp4">
<source type="video/webm" src="foo.webm">
</video>
<!--推荐-->
<amp-video width="400" height="300" src="http://www.domain.com/videos/myvideo.mp4"
poster="path/poster.jpg">
<div fallback>
<p>Your browser doesn’t support HTML5 video</p>
</div>
<source type="video/mp4" src="foo.mp4">
<source type="video/webm" src="foo.webm">
</amp-video>
PWA(Progressive Web Apps)是 Google 提出的用前沿的 Web 技术为网页提供 App 般使用体验的一系列方案。
在移动端,一般要保证页面中一切用到的图片都是通过压缩优化处理的,而不是以原图的形式直接使用的,由于那样很消耗流量,并且加载时间更长。
在页面使用的背景图片很少且较小的状况下,能够将图片转化成 base64 编码嵌入到 HTML 页面或 CSS 文件中,这样能够减小页面的 HTTP 请求数。须要注意的是,要保证图片较小,通常图片大小超过 2KB 就不推荐使用 base64 嵌入显示了。
.class-name{
background-image : url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAALCAMAAABxsOwqAAAAYFBMVEWnxwusyQukxQudwQyZvgyhxAyfwgyxzAsUHQGOuA0aJAERGAFIXwSTugyEqgtqhghQZgUwQQIpOQKbuguVtQuKrAuCowp2kQlheghTbQZHWQU7SwVAVgQ6TgQlLwMeKwFOemyQAAAAVElEQVQI1y3JVRaAIAAF0UconXbvf5ei8HfPDIQQhBAAFE10iKig3SLRNN4SP/p+N08VC0YnfIlNWtqIkhg/TPYbCvhqdHAWRXPZSp3g3CWZvVLXC6OJA3ukv0AaAAAAAElFTkSuQmCC');
}
使用具备较高压缩比格式的图片,如 webp(须要设计降级兼容方案)等。在同等图片画质的状况下,高压缩比格式的图片体积更小,可以更快完成文件传输,节省网络流量。
<img src="//cdn.domain.com/path/photo.webp" alt="webp格式图片" >
为了保证页面内容的最小化,加速页面的渲染,尽量节省移动端网络流量,页面中的图片资源推荐使用懒加载实现,在页面滚动时动态载入图片。
<img data-src="//cdn.domain.com/path/photo.jpg" alt="懒加载图片" >
在介绍响应式的章节中咱们了解到,针对不一样的移动端屏幕尺寸和分辨率,输出不一样大小的图片或背景图能保证在用户体验不下降的前提下节省网络流量,加快部分机型的图片加载速度,这在移动端很是值得推荐。
在页面中尽量使用 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");
}
加载的单张图片通常建议不超过 30KB,避免大图片加载时间长而阻塞页面其余资源的下载,所以推荐在 10KB 之内。若是用户上传的图片过大,建议设置告警系统,帮助咱们观察了解整个网站的图片流量状况,作出进一步的改善。
对于一些「永远」不会变的图片可使用强缓存的方式缓存在用户的浏览器上。
选择器选择页面 DOM 元素时尽可能使用 id 选择器,由于 id 选择器速度最快。
对于须要重复使用的 DOM 对象,要优先设置缓存变量,避免每次使用时都要从整个 DOM 树中从新查找。
//不推荐
$('#mod.active').remove('active');
$('#mod.not-active').addClass('active');
//推荐
let $mod=$('#mod');
$mod.find('.active').remove('active');
$mod.find('.not-active').addClass('active');
使用事件代理能够避免对每一个元素都进行绑定,而且能够避免出现内存泄露及须要动态添加元素的事件绑定问题,因此尽可能不要直接使用事件绑定。
//不推荐
$('.btn').on('click',function(e){
console.log(this);
});
//推荐
$('body').on('click','.btn',function(e){
console.log(this);
});
因为移动端屏幕的设计, touchstart 事件和 click 事件触发时间之间存在 300 毫秒的延时,因此在页面中没有实现 touchmove 滚动处理的状况下,可使用 touchstart 事件来代替元素的 click 事件,加快页面点击的响应速度,提升用户体验。但同时咱们也要注意页面重叠元素 touch 动做的点击穿透问题。
//不推荐
$('body').on('click','.btn',function(e){
console.log(this);
});
//推荐
$('body').on('touchstart','.btn',function(e){
console.log(this);
});
须要对 touchmove、scroll 这类可能连续触发回调的事件设置事件节流,例如设置每隔 16ms(60 帧的帧间隔为 16.7ms,所以能够合理地设置为 16ms )才进行一次事件处理,避免频繁的事件调用致使移动端页面卡顿。
//不推荐
$('.scroller').on('touchmove','.btn',function(e){
console.log(this);
});
//推荐
$('.scroller').on('touchmove','.btn',function(e){
let self=this;
setTimeout(function(){
console.log(self);
},16);
});
这些都是一些基础的安全脚本编写问题,尽量使用较高效率的特性来完成这些操做,避免不规范或不安全的写法。
ECMAScript6+ 必定程度上更加安全高效,并且部分特性执行速度更快,也是将来规范的须要,因此推荐使用 ECMAScript6+ 的新特性来完成后面的开发。
通常认为,在移动端设置 Viewport 能够加速页面的渲染,同时能够避免缩放致使页面重排重绘。在移动端固定 Viewport 设置的方法以下。
<!--设置viewport不缩放-->
<meta >
页面的重排重绘很耗性能,因此必定要尽量减小页面的重排重绘,例如页面图片大小变化、元素位置变化等这些状况都会致使重排重绘。
使用 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);
选择 Canvas 或 requestAnimationFrame 等更高效的动画实现方式,尽可能避免使用 setTimeout、setInterval 等方式来直接处理连续动画。
部分状况下能够考虑使用 SVG 代替图片实现动画,由于使用 SVG 格式内容更小,并且 SVG DOM 结构方便调整。
在 DOM 渲染树生成后的布局渲染阶段,使用 float 的元素布局计算比较耗性能,因此尽可能减小 float 的使用,推荐使用固定布局或 flex-box 弹性布局的方式来实现页面元素布局。
过多的 font-size 声明会增长字体的大小计算,并且也没有必要的。
脚本容错能够避免「非正常环境」的执行错误影响页面的加载和不相关功能的使用
在条件容许的状况下能够考虑使用 SPDY 协议来进行文件资源传输,利用链接复用加快传输过程,缩短资源加载时间。HTTP2 在将来也是能够考虑尝试的。
使用后端数据渲染的方式能够加快页面内容的渲染展现,避免空白页面的出现,同时能够解决移动端页面 SEO 的问题。若是条件容许,后端数据渲染是一个很不错的实践思路。后面的章节会详细介绍后端数据渲染的相关内容。
能够尝试使用 NativeView 的 MNV* 开发模式来避免 HTML DOM 性能慢的问题,目前使用 MNV* 的开发模式已经能够将页面内容渲染体验作到接近客户端 Native 应用的体验了。但须要避免 js Framework 和 native Framework 的频繁交互。
本篇内容是在微信公众号上边看到的,保存到这里但愿更多关注这一块的人能够看到。