图片 13

的移动页面优化方案,网页加速特技之

AMP,来自 Google 的移动页面优化方案

2015/10/12 · HTML5 ·
AMP

原文出处:
imququ(@屈光宇)   

Web 性能优化(Web Performance
Optimization,WPO)是一个老生常谈的话题,我也写过很多关于「性能优化」的文章。最近
Google 某个团队推出了一项名为 Accelerated Mobile
Pages(AMP)的技术,号称能大大加快移动端页面呈现速度,提高整体体验。本文就带大家认识一下这项新技术。

 

前端性能优化 —— 移动端浏览器优化策略

2018/01/14 · 基础技术 ·
移动端

原文出处: ouven   

  相对于桌面端浏览器,移动端Web浏览器上有一些较为明显的特点:设备屏幕较小、新特性兼容性较好、支持一些较新的HTML5和CSS3特性、需要与Native应用交互等。但移动端浏览器可用的CPU计算资源和网络资源极为有限,因此要做好移动端Web上的优化往往需要做更多的事情。首先,在移动端Web的前端页面渲染中,桌面浏览器端上的优化规则同样适用,此外针对移动端也要做一些极致的优化来达到更好的效果。需要注意的是,并不是移动端的优化原则在桌面浏览器端就不适用,而是由于兼容性和差异性的原因,一些优化原则在移动端更具代表性。

AMP 介绍

Accelerated Mobile
Pages(官网、GitHub),直译成中文是「加速的移动页面」的意思。根据官方说明,AMP
在 Speed
Index(首屏展现时间平均值)测试中,性能有
15% ~ 85% 的提升,测试是在模拟 3G 网络环境并模拟 Nexus 5
的条件下完成(详情)。

AMP
如何让页面性能大幅提升暂且搁置一边,先来看看它是什么。根据官网文档得知,AMP
主要由 AMP HTML、AMP Runtime 以及 AMP Components 三部分组成。

据统计,40%的人会放弃使用加载时间超过3秒的网站。对于加载慢的页面我也是没耐心等待的,同类型网站那么多,为什么不选择加载速度更快体验更好的呢。为了解决网页加载慢的问题,Google联合数十家技术机构和企业等推出了移动网页加速项目(Accelerated
Mobile Pages, AMP)。

一、网络加载类

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

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

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

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

3.模块化资源并行下载

在移动端资源加载中,尽量保证JavaScript资源并行加载,主要指的是模块化JavaScript资源的异步加载,例如AMD的异步模块,使用并行的加载方式能够缩短多个文件资源的加载时间。

4.inline首屏必备的CSS和JavaScript

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

JavaScript

<!DOCTYPE html> <html lang=”en”> <head> <meta
charset=”UTF-8″> <title>样例</title> <meta
name=”viewport” content=”width=device-width,minimum-scale=1.0,
maximum-scale=1.0,user-scalable=no”> <style> /* 必备的首屏CSS
*/ html, body{ margin: 0; padding: 0; background-color: #ccc; }
</style> </head> <body> </body>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>样例</title>
    <meta name="viewport" content="width=device-width,minimum-scale=1.0, maximum-scale=1.0,user-scalable=no">
    <style>
    /* 必备的首屏CSS */
    html, body{
        margin: 0;
        padding: 0;
        background-color: #ccc;
    }
    </style>
</head>
<body>
</body>

5.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”>

1
2
3
<!– cdn域名预解析 –>
<meta http-equiv="x-dns-prefetch-control" content="on">
<link rel="dns-prefetch" href="//cdn.domain.com">

6.资源预加载

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

7.合理利用MTU策略

通常情况下,我们认为TCP网络传输的最大传输单元(Maximum Transmission
Unit,MTU)为1500B,即网络一个RTT(Round-Trip
Time,网络请求往返时间)时间内可以传输的数据量最大为1500字节。因此,在前后端分离的开发模式中,尽量保证页面的HTML内容在1KB以内,这样整个HTML的内容请求就可以在一个RTT时间内请求完成,最大限度地提高HTML载入速度。

AMP HTML

AMP HTML 是 HTML 的子集,在 AMP HTML
中只允许使用有限的标签。例如 <body><article> 这些标签可以直接使用,没有任何限制;有些标签允许有限制的使用,例如 <meta> 标签不能使用 http-equiv 属性;而像 <img><audio> 这样的标签需要替换为 <amp-img><amp-audio> 等
AMP Components;更多的标签如 <frame><form> 不允许使用。

完整说明可以查看官网的 AMP HTML
格式文档。以下是该文档中的
AMP HTML 示例:

XHTML

<html> <head> <meta charset=”utf-8″>
<title>Sample document</title> <link rel=”canonical”
href=”./regular-html-version.html”> <meta name=”viewport”
content=”width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,minimal-ui”>
<style amp-custom> h1 {color: red} </style> <script
type=”application/ld+json”> { “@context”: “”,
“@type”: “NewsArticle”, “headline”: “Article headline”, “image”: [
“thumbnail1.jpg” ], “datePublished”: “2015-02-05T08:00:00+08:00″ }
</script> <script async custom-element=”amp-carousel”
src=”;
<style>body {opacity:
0}</style><noscript><style>body {opacity:
1}</style></noscript> <script async
src=”; </head>
<body> <h1>Sample document</h1> <p> Some text
<amp-img src=sample.jpg width=300 height=300></amp-img>
</p> <amp-ad width=300 height=250 type=”a9″
data-aax_size=”300×250″ data-aax_pubname=”test123″
data-aax_src=”302″> </amp-ad> </body> </html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<html>
<head>
  <meta charset="utf-8">
  <title>Sample document</title>
  <link rel="canonical" href="./regular-html-version.html">
  <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,minimal-ui">
  <style amp-custom>
    h1 {color: red}
  </style>
  <script type="application/ld+json">
  {
    "@context": "http://schema.org",
    "@type": "NewsArticle",
    "headline": "Article headline",
    "image": [
      "thumbnail1.jpg"
    ],
    "datePublished": "2015-02-05T08:00:00+08:00"
  }
  </script>
  <script async custom-element="amp-carousel" src="https://cdn.ampproject.org/v0/amp-carousel-0.1.js"></script>
  <style>body {opacity: 0}</style><noscript><style>body {opacity: 1}</style></noscript>
  <script async src="https://cdn.ampproject.org/v0.js"></script>
</head>
<body>
<h1>Sample document</h1>
<p>
  Some text
  <amp-img src=sample.jpg width=300 height=300></amp-img>
</p>
<amp-ad width=300 height=250
    type="a9"
    data-aax_size="300×250"
    data-aax_pubname="test123"
    data-aax_src="302">
</amp-ad>
</body>
</html>

可以看出,AMP HTML 与普通 HTML
并没有什么太大区别,上面这段代码可以直接存为 .html 文件,并在浏览器中正常运行。下面简单列举一些格式上的要求:

  • DTD 必须是: <!doctype html>
  • 顶层标签必须包含 AMP
    属性,如:<html ⚡> 或 <html amp>(让其他程序能方便地识别出这是
    AMP HTML);
  • 必须在 HEAD
    区域中放置 <link rel="canonical" href="$SOME_URL" /> 标签,用来指定该文档普通版本的
    URL;如果只有一个版本,使用当前 URL
    即可(告诉搜索引擎,这是同一个页面不同的版本,否则可能会被判作弊);
  • 必须将 <meta charset="utf-8"> 放置在 HEAD
    区域最开始的位置(实际上,普通 HTML 也应该这么做);
  • 必须在 HEAD 区域包含这个
    ViewPort:<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,minimal-ui">
  • 必须将 <script async src="https://cdn.ampproject.org/v0.js"></script> 作为
    HEAD 区域最后的元素;
  • 必须在 HEAD
    区域包含以下代码:<style>body {opacity: 0}</style><noscript><style>body {opacity: 1}</style></noscript>

据AMP官网统计目前已有很多新闻类网站和科技类网站开始使用AMP,包括Wordpress、YouTube、Twitter、LinkedIn、BBC等。

二、缓存类

1.合理利用浏览器缓存

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

2.静态资源离线方案

对于移动端或Hybrid应用,可以设置离线文件或离线包机制让静态资源请求从本地读取,加快资源载入速度,并实现离线更新。关于这块内容,我们会在后面的章节中重点讲解。

3.尝试使用AMP HTML

AMP HTML可以作为优化前端页面性能的一个解决方案,使用AMP
Component中的元素来代替原始的页面元素进行直接渲染。

JavaScript

<!– 不推荐 –> <video width=”400″ height=”300″
src=””
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=””
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>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!– 不推荐 –>
<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>

三、图片类

1.图片压缩处理

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

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

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

.class-name { background-image:
url(‘data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAALCAMAAABxsOwqAAAAYFBMVEWnxwusyQukxQudwQyZvgyhxAyfwgyxzAsUHQGOuA0aJAERGAFIXwSTugyEqgtqhghQZgUwQQIpOQKbuguVtQuKrAuCowp2kQlheghTbQZHWQU7SwVAVgQ6TgQlLwMeKwFOemyQAAAAVElEQVQI1y3JVRaAIAAF0UconXbvf5ei8HfPDIQQhBAAFE10iKig3SLRNN4SP/p+N08VC0YnfIlNWtqIkhg/TPYbCvhqdHAWRXPZSp3g3CWZvVLXC6OJA3ukv0AaAAAAAElFTkSuQmCC’);
}

1
2
3
.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格式图片”/>

1
  <img src="//cdn.domain.com/path/photo.webp" alt="webp格式图片"/>

4.图片懒加载

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

<img data-src=”//cdn.domain.com/path/photo.jpg” alt=”懒加载图片”
/>

1
  <img data-src="//cdn.domain.com/path/photo.jpg" alt="懒加载图片" />

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

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

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”); }

1
2
3
4
5
6
7
@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以内。如果用户上传的图片过大,建议设置告警系统,帮助我们观察了解整个网站的图片流量情况,做出进一步的改善。

AMP Runtime

在上面的 AMP HTML 代码中,HEAD 区域最后外链引入的 JS 就是 AMP
Runtime。AMP Runtime 提供对自定义元素(Custom
Elements)的支持,负责协调资源的加载时机和优先级,以及提供验证器等调试功能。

访问 AMP HTML 时,在 URL
最后追加 #development=1 会开启开发者模式。这时 AMP Runtime
会自动加载验证器,并在控制台显示本页不符合 AMP 规范的位置信息。

不明觉厉,接下来让我们一起来揭开AMP神秘的面纱吧。

四、脚本类

1.尽量使用id选择器

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

2.合理缓存DOM对象

对于需要重复使用的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’);

1
2
3
4
5
6
7
8
// 不推荐
$(‘#mod .active’).remove(‘active’);
$(‘#mod .not-active’).addClass(‘active’);
 
// 推荐
let $mod = $(‘#mod’);
$mod.find(‘.active’).remove(‘active’);
$mod.find(‘.not-active’).addClass(‘active’);

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

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

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

1
2
3
4
5
6
7
8
9
// 不推荐
$(‘.btn’).on(‘click’, function(e){
    console.log(this);
});
 
// 推荐
$(‘body’).on(‘click’, ‘.btn’, function(e){
    console.log(this);
});

4.使用touchstart代替click

由于移动端屏幕的设计,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); });

1
2
3
4
5
6
7
8
9
// 不推荐
$(‘body’).on(‘click’, ‘.btn’, function(e){
    console.log(this);
});
 
// 推荐
$(‘body’).on(‘touchstart’, ‘.btn’, function(e){
    console.log(this);
});

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

需要对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); });

1
2
3
4
5
6
7
8
9
10
11
12
// 不推荐
$(‘.scroller’).on(‘touchmove’, ‘.btn’, function(e){
    console.log(this);
});
 
// 推荐
$(‘.scroller’).on(‘touchmove’, ‘.btn’, function(e){
    let self = this;
    setTimeout(function(){
        console.log(self);
    }, 16);
});

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

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

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

ECMAScript
6+一定程度上更加安全高效,而且部分特性执行速度更快,也是未来规范的需要,所以推荐使用ECMAScript
6+的新特性来完成后面的开发。

AMP Components

AMP Components 是使用浏览器自定义元素(Custom
Elements)实现的组件,用来替换 HTML
中默认的 <img> 和 <video> 等标签,用来实现对资源的自定义加载策略;它也用于实现一些复杂的交互效果,如图片轮播。AMP
Components 分为两类:

1)内置组件,包括:amp-img、amp-audio、amp-anim、amp-ad、amp-pixel、amp-video,在
AMP HTML 引入了 AMP Runtime 之后,这些内置组件就可以直接使用。

2)扩展组件,包括:amp-carousel、amp-lightbox、amp-iframe、amp-instagram、amp-twitter、amp-youtube。要使用扩展组件,需要在
AMP HTML 中引入该组件对应的文件。例如要使用 amp-carousel
就必须引入以下文件(必须要有 async 和 custom-element 属性):

JavaScript

<script async custom-element=”amp-carousel”
src=”;

1
<script async custom-element="amp-carousel" src="https://cdn.ampproject.org/v0/amp-carousel-0.1.js"></script>

这里有一个按照 AMP HTML
规范编写的页面,大家可以直接用浏览器打开查看:AMP
示例(注:为了保证国内打开速度,我把
AMP JS 托管在了本地,实际上这么做并不符合规范)。

一、什么是AMP?

Accelerated Mobile Pages
(AMP)直译过来就是在移动设备上快速加载的网页。它是由 Google
发起的一个开源项目,主要目的是缩短静态内容的渲染时间从而有效提升网站的加载速度。

那么问题来了,AMP的加载速度到底有多快?

根据 Google 官方说明,AMP 在模拟 Nexus 5 并模拟 3G
网络的测试情况下,首屏展现速度有 15% ~ 85% 的提升。

图片 1

这么NB,让我们来看看AMP到底什么鬼。。。

AMP主要由三个部分组成:

五、渲染类

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

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

<!– 设置viewport不缩放 –> <meta name=”viewport”
content=”width=device-width, initial-scale=1.0, maximum-scale=1.0,
user-scalable=no”/>

1
2
<!– 设置viewport不缩放 –>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>

2.避免各种形式重排重绘

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

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

使用CSS3动画时可以设置transform:
translateZ(0)来开启移动设备浏览器的GPU图形处理加速,让动画过程更加流畅。

-webkit-transform: translateZ(0); -ms-transform: translateZ(0);
-o-transform: translateZ(0); transform: translateZ(0);

1
2
3
4
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
-o-transform: translateZ(0);
transform: translateZ(0);

4.合理使用Canvas和requestAnimationFrame

选择Canvas或requestAnimationFrame等更高效的动画实现方式,尽量避免使用setTimeout、setInterval等方式来直接处理连续动画。

5.SVG代替图片

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

6.不滥用float

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

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

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

AMP 剖析

1.AMP HTML

1).AMP HTML 规范*

AMP HTML 在 HTML 的基础上加了一些使用限制,并且添加了AMP自定义的组件。

AMP 禁用部分 HTML 标签如<frame><form><input> 等。

部分 HTML 标签必须使用 AMP
自定义的组件来替换如 <img> 、 <video> 用 <amp-img> 、 <amp-video>替换。

AMP在HTML基础上也提供一些扩展组件,如 <amp-carousel> 、 <amp-iframe><amp-youtube>等,但是使用扩展组件时必须引入相应的JS文件。

一个简单的 AMP HTML 示例:

图片 2

将上面的代码保存为 .html
文件,在浏览器中就可以正常运行,从这个示例可以看出,AMP HTML
的写法和HTML差不多,但是又有自己的规范要求:

  • DTD 必须是: <!doctype html>;

  • 顶层标签必须包含 AMP 属性如: <html amp>,方便其他程序识别 AMP
    HTML;

  • 必须在 HEAD
    区域中放置 <link rel="canonical" href="$SOME_URL" /> 标签,指定该页面普通版本的
    URL;如果只有一个版本,则使用当前 URL;

  • 必须将<meta charset="utf-8"> 放置在 HEAD 区域最开始的位置;

  • 必须在 HEAD 区域包含这个 ViewPort:
    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,minimal-ui">

  • 必须将 <script async src="https://cdn.ampproject.org/v0.js"></script> 作为 HEAD区域最后的元素;

  • 必须在 HEAD
    区域包含上面示例所示的<style amp-boilerplate> 和 <noscript>的相关代码;

更多 AMP HTML 相关说明,可移步 AMP HTML官方文档

六、架构协议类

1.尝试使用SPDY和HTTP 2

在条件允许的情况下可以考虑使用SPDY协议来进行文件资源传输,利用连接复用加快传输过程,缩短资源加载时间。HTTP
2在未来也是可以考虑尝试的。

2.使用后端数据渲染

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

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

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

关于页面优化的常用技术手段和思路主要包括以上这些,尽管列举出很多,但仍可能有少数遗漏,可见前端性能优化不是一件简简单单的事情,其涉及的内容很多。大家可以根据实际情况将这些方法应用到自己的项目当中,要想全部做到几乎是不可能的,但做到用户可接受的原则还是很容易实现的。

于此同时我们要清楚的是,在我们做到了极致优化的同时也付出了很大的代价,这也是前端优化的一个问题。理论上这些优化都是可以实现的,但是作为工程师我们也要明白懂得权衡。优化提升了用户体验,使数据加载更快,但是项目代码却可能打乱,异步内容要拆分出来,首屏的一个雪碧图可能要分成两个,页面项目代码维护成本成倍增加,项目结构也可能变得混乱。所以前期在设计构建、组件的解决方案时要解决好异步的自动处理问题。任何一部分优化都可以做得很深入,但不一定都值得,在优化的同时也要尽量考虑性价比,这才是我们作为一名前端工程师处理前端优化时应该具有的正确思维。

1 赞 收藏
评论

图片 3

定位:解决单一问题

经过前面对 AMP 的介绍,你一定会感到奇怪,为什么 AMP HTML
有那么多限制和约束,这样阉割后的 HTML 还有什么适用场景。实际上,AMP
只关注于一件事 —— 提高静态页面的性能。

这个「静态」并不是指没有服务端参与的页面,而是指没有复杂交互、以内容展现为主的资源页,典型例子就是新闻详情页。现在的网站类型很多,游戏类、视频类、电商类等等,每一类网站都有着自己的特点,优化策略也各不相同,用一种方案去解决所有问题不切实际。所以
AMP 项目将关注点放在了更容易优化且效果最明显的内容型页面。

2)AMP HTML 组件

自定义组件

AMP HTML 自定义5个组件:
amp-ad、amp-embed、amp-img、amp-pixel、amp-video

组件直接以标签的形式进行使用,如页面中需要加载video、img
使用相应的组件即可,如下:

图片 4

图片 5

amp-video amp-img
组件实际是使用HTML原生<video> <img> 标签来实现,所以在页面上的展示效果和原生HTML一致。

图片 6

amp-ad、amp-embed 组件主要用于引入广告类信息,使用iframe的方式来实现。

扩展组件

AMP HTML的一个重要特性就是可扩展性,它提供扩展组件来实现丰富的功能。

官网目前提供的扩展有youtube视频组件、twitter组件、轮播、滚动、instagramd等等。

使用扩展组件需要在页面头部引入依赖的JS文件,如使用twitter组件:

图片 7

twitter组件的显示效果如图:

图片 8

扩展组件使用iframe来实现,定义扩展组件必须严格遵循AMP的3p contribution
guidelines(为了保证性能,定义扩展组件的要求非常多)。

选型:纯 web 技术方案

Web
优化有很多种方案,每种方案都有自己的适用范围。有些收益很高的优化手段,存在这样那样的限制:例如针对具体业务逻辑所做的优化,很难通用化;部署
Google
的 PageSpeed 模块等服务端优化方案,使用成本很高;借助客户端所做的优化,如现在广为流行的移动端
WebView 容器加速方案,优化效果局限在指定 APP
内,甚至还会导致使用通用浏览器访问速度更慢(这个话题很有意思,有机会以后再讨论)。

以内容为主的新闻详情页,大部分性能消耗在图片、视频等媒体资源以及第三方功能如广告、社会化组件的加载上。将这些内容替换为
AMP Components,避免资源默认被加载,再用 AMP Runtime
统一协调和管理,确实是一个通用化、低使用成本且能让所有浏览器受益的折中方案。而且,AMP
方案不依赖任何特定的服务端或客户端,可以将页面直接托管在
CDN,进一步提高用户访问速度。

2.AMP JS

AMP JS 是 AMP 技术的核心。

图片 9

AMP JS
负责协调资源的加载时机和优先级,让外部资源按不同顺序加载使得页面的主要内容优先加载;AMP
JS
的resources模块根据元素优先级(amp-img的优先级高于amp-ad的优先级)、操作优先级、可视优先级给资源评分,根据评分调整资源加载优先级。

它还负责页面的性能优化,例如在资源加载完成前对页面元素布局预处理,禁用慢的CSS选择器,对
iframe 进行沙盒处理,提供对自定义元素的支持。

AMP JS 也负责提供验证器等调试功能,在URL最后加 #development=1
就会开启调试模式,AMP会自动加载验证器,并在控制台显示本页不符合AMP规范的报错信息。

实现:资源调度与控制

浏览器对不同资源加载和预加载有自己的策略,对于预加载,我们有一些控制权,但总的看来这一块对于开发者来说还是很不可控。例如浏览器默认会并行加载多张图片,但在屏幕小、网速慢、性能差的手机上,串行由上到下加载图片很可能体验更好。

移动设备在网络、CPU、内存等方面与 PC 差距很大,很多 PC
上可以忽略的问题,在移动端不得不重视起来。例如我们都知道图片是异步加载的,页面触发
DOMContentLoaded
事件并不需要等图片加载完,但在移动端,大量图片加载带来性能开销却会大幅延后
DOMContentLoaded
时机。以下是我们在某个移动产品中,将图片进行延迟加载处理后的
DOMContentLoaded
时间对比统计,可以看到明显的变化:图片 10

将图片、视频等标签和第三方功能换成 AMP Components 后,AMP Runtime
可以自动处理延迟加载、按需加载等逻辑,确保页面首屏性能。为了避免延迟加载的资源引发页面抖动,开发者必须给每个
AMP Components 都设置高宽属性,每个 Components 都支持多种 layout
布局,在 responsive 布局下,组件会根据初始高宽比例自动调整大小。

另外,一些资源非常消耗性能,例如 gif 和 video,AMP Runtime
可以在它们处于不可见时销毁元素,释放资源。总之,使用了 AMP
方案,相当于将页面资源托管给了 AMP Runtime
管理,一次修改就可以坐享后续所有策略升级带来的性能提升。

3.Google AMP Cache

Google AMP
Cache是一个基于代理机制的内容分发网络(CDN),它会分发所有合格的AMP文件,它会抓取AMP页面并进行缓存,自动提升页面的性能。使用Google
AMP
Cache,页面、JS文件、图片等都是从同一个源获取,并且使用HTTP2.0来优化性能。

这个缓存机制还带有的验证系统,以确保网页不受外部资源的限制,能随时随地正常运行。它能自动验证网页是否符合AMP
HTML的规范。

观点:很有借鉴意义

本文到这里,差不多快要结束了。经过上面的介绍,大家对 AMP
项目应该有了一定的认识。最后谈谈我的看法:

AMP 项目对书写代码设置了大量限制,例如所有资源只能托管给 AMP Runtime
加载;不允许使用 AMP Runtime、AMP Components 之外的 JS;不允许使用
inline JS;只能使用有限的 inline CSS 样式;JS 和 Web Font 必须使用指定的
CDN
等等,这都是为后面的优化策略做准备。整体原理并不复杂,难点是配套设施的建立,以及如何说服网站主改造代码。不过,Google
后续很可能对使用了 AMP 的页面提权,这样一来大家就有动力了。

符合 AMP 规范的页面不会比由 WPO
专家优化后的页面更快,它是一个通用化的技术,肯定包含很多业务用不上的代码逻辑,也有很多优化手段它无法提供。但对于不知道如何
WPO 的网站来说,使用 AMP 则是一个非常不错的选择。

不过,我认为 AMP 很难直接用在国内项目中。首先,前面说过,AMP
Runtime、Components 必须从 cdn.ampproject.org 加载;Web Font
必须从 fonts.googleapis.com 加载。这样做的出发点是为了更可控,以及更好的在各网站之间共享缓存,但是这些域名在国内很难访问甚至直接被墙。其次,从目前
AMP 目前已有的扩展组件来看,instagram、twitter、youtube
这类国外媒体常用的服务在国内都无法使用,内置的 ad 组件也不符合国情。

但是,AMP 项目对我们进行移动 Web
优化仍然很有借鉴意义。实际上,控制资源加载、处理响应式元素避免页面抖动、主动释放资源等策略,我们在项目中都有自己的尝试与经验,但我们的方案要么过分依赖服务端,要么没有抽象成通用模式,导致无法推广到更多产品,这些都是后续可以努力的方向,而
AMP 规范和代码实现,将会是最好的参考资料。

1 赞 3 收藏
评论

图片 3

二、AMP HTML 和 HTML 比较

简单了解了 AMP 的相关规范,我们来验证下 AMP 是不是如传说中那么NB。。。

分别用 AMP HTML 和 HTML
写了两个一样的页面,页面中有33个HTTP请求,包含一个video、28张图片等资源。不多说,直接上图:

3G(1Mbps 40ms RTT)网络状态下,HTML页面:

图片 12

3G(1Mbps 40ms RTT)网络状态下,AMP页面:

图片 13

从上图对比可看出,3G网络下,AMP页面的onload时间比HTML页面快50%以上,当然这是在HTML页面图片没做lazy-load优化的情况下。

3G(1Mbps 40ms RTT)网络状态下,HTML页面:

3G(1Mbps 40ms RTT)网络状态下,AMP页面:

从上面两图对比可看出,3G网络下AMP页面的渲染时间明显快于HTML页面。

AMP页面优化资源加载,自动对资源做延迟加载,首屏完整展现的速度明显快于HTML页面。

上面的测试页面是静态内容页面,不涉及到服务器数据拉取和复杂的页面交互,所以有一定的局限性。要深入了解AMP页面和HTML的差异,还需要更多的测试。

三、AMP如何提升性能?

在静态内容页面测试数据中,AMP页面的加载速度确实更快,那么AMP提升页面加载速度的秘诀是什么捏,我们一起来看看。

1.只允许异步加载script

HTML 解析器遇到 script 标签,它会暂停构建 DOM,并移交控制权给 JavaScript
引擎;等 JavaScript 引擎执行完毕,浏览器从中断的地方恢复 DOM
构建。执行内联脚本会阻塞 DOM
构建,也就延缓了首次渲染。为了减少JS对页面渲染的延迟,AMP不允许直接使用内联脚本,只允许异步加载JS。

AMP页面不允许直接包含任何内联JS,页面交互可在AMP组件中处理,AMP组件是经过精心设计的保证不会影响页面性能。第三方JS只允许在
iframe 中使用,这样就不会阻塞主页面的渲染。

2.静态资源指定宽高

扩展资源如图片、iframe等必须在标签中指定他们的宽高,AMP可以在这些资源下载完成以前就决定每一个元素的宽高和位置,AMP在所有资源加载完之前就开始页面布局。

AMP把文档和资源分开布局,避免样式重新计算和布局,资源加载完成后不会重新布局。

3.避免扩展机制影响渲染

AMP支持一些扩展组件如:<amp-lightboxes>,<amp-tweets>,使用这些组件需要加载相应的JS文件,会增加额外的HTTP请求,但是这些请求不会阻塞页面的布局和渲染。

任何页面用原生的script标签,必须要通知AMP系统,即在`script`中加
`custome-element`属性。

4.关键路径禁用第三方JS

AMP 只能在 sandboxed iframe 中加载第三方 JS。把他们当做
iframes,因此不会阻塞主页面。如果第三方JS触发多个样式重计算,iframe中也只有很少一部分DOM,重新布局不会消耗很多性能。

5.CSS必须内联,内联样式表最大50kb

CSS会阻塞页面渲染,阻塞页面加载。在AMP页面中,只允许内联样式,这会在关键渲染路径上比一般的页面减少1或多个HTTP请求。

CSS使用内联,内联样式表(inline stylesheet)最大不超过50kb。

6.字体必须有效触发

Web字体非常大,因此Web字体对性能优化是至关重要的。在一个普通的页面中有一些script和样式表,浏览器需要等待这些资源加载完成后开始加载这些大的字体资源。

在AMP中所有的JS都是异步加载而且只允许使用内联样式表,所以没有HTTP请求阻塞浏览器去加载字体资源。

7.减小样式重计算

修改元素样式时,会触发样式重新计算,这是非常高的性能消耗,因为浏览器需要重新布局整个页面。AMP页面在进行DOM写操作之前会先读取DOM,这样能确保样式重计算时一次最精确到每一帧的样式。

8.只运行经GPU加速的动画

AMP网页上的动画只允许变形和透明度调整,从而节省重新布局页面的时间。

9.优化资源加载次序

AMP控制所有的资源加载,优先加载必要的资源(如首屏需要展示的资源),预加载可以延迟加载的资源。

AMP加载资源时,最重要的资源最先被加载,images 和 ads
在他们可能被用户看到的情况下才加载,或者在用户快速滚动到他们的位置时加载。

10.使用 preconnect API

新的preconnect
API用来确保HTTP请求尽可能快。页面可以在用户看到之前就渲染完成。通过即时加载,页面可能在用户选择它的时候就已经是可用的了。

虽然预渲染可以让页面更快,但是也会消耗大量的带宽和CPU。AMP对减少这两个因素进行了优化。预渲染只会下载被遮住的部分资源,而且不会渲染很耗CPU的内容。

四、总结与思考

AMP亮点:

  1. AMP有利于网站SEO,在网站内容差不多的情况下,使用AMP的网站在 Google
    搜索中可以获得更靠前的排名。

  2. 延迟加载、按需加载使得首屏展现更快。

  3. 尤其对内容型页面性能优化明显。

AMP限制:

网络限制,如AMP JS、AMP Components 必须从 cdn.ampproject.org 加载;Web
Font 必须从 fonts.googleapis.com
加载,这些源网站在国内访问速度很慢甚至直接被墙。

引入第三方资源受限。

需要遵循严格的代码规范指引。

AMP设计的初衷就是针对静态内容,用来加速新闻类网站,所以对其他交互较多的网站可能并不适用。但是,AMP
控制资源加载、处理响应式元素避免页面抖动、主动释放资源等策略可以作为我们对移动
Web 优化的参考。

参考资料:
1.
2.
3.
4.

相关阅读

一站式满足电商节云计算需求的秘诀

面向亿万级用户的QQ一般做什么?——兴趣部落的 Web
同构直出分享

「腾讯云游戏开发者技术沙龙」11月24
日深圳站报名开启
畅谈游戏加速

 

此文已由作者授权腾讯云技术社区发布,转载请注明文章出处

原文链接:

海量技术实践经验,尽在腾讯云社区!

发表评论

电子邮件地址不会被公开。 必填项已用*标注