从案例分析如何优化前端性能

图片 9

Web 的现状:网页性能提升指南

2017/09/21 · 基础技术 ·
性能

原文出处: Karolina
Szczur   译文出处:碧青_Kwok   

互联网发展非常迅速,所以我们创造了Web平台。通常我们会忽视连通性等问题,但用户们却不会视而不见。一瞥万维网的现状,可以发现我们并没有用同情心、变通意识去构建它,更不要说性能了。

所以,今天的Web是什么状态呢?

在这个星球上的74亿人中,只有46%可以上网。平均网络速度上限为7Mb/s。更重要的是,有93%的互联网用户正在通过移动设备进行访问——若不适配移动设备将引起用户反感。通常情况下,数据比我们假设的更昂贵——可能需要1到13小时才能购买500MB的数据包(德国
vs. 巴西;更有趣的统计数据参见 Ben
Schwarz 的 Beyond the Bubble: The Real
World
Performance)。

我们的网站也不是完美的——平均网站是原始Doom游戏的大小(约3
MB)(请注意,为了统计准确,应使用中位数,阅读 Ilya
Grigorik
的优秀“平均页面”是一个神话,中档网站大小目前为1.4MB)。图像可以轻松占用1.7
MB的带宽,而JavaScript平均值也有400KB的体积。这不仅是Web平台的问题,原生应用程序可能更糟,还记得为了获取错误修复版本,而下载200MB安装包的情景吗?

技术人员经常会发现自己处于特权状态。随着最新的高端笔记本电脑、手机和快速有线互联网连接,很容易让我们忘记,这些并不是每个人都有的条件(实际上,真的很少)。

如果我们从特权和缺乏同情的角度来构建网络平台,那么将导致排他性的糟糕体验。

考虑到设计和开发的性能,我们怎样才能做得更好?


从案例分析如何优化前端性能

2016/08/30 · 基础技术 ·
性能

原文出处:
css-tricks   译文出处:王下邀月熊   

在 De
Voorhoede工作的日子里,我们一直在追寻为用户构建高性能的前端解决方案。不过并不是每个客户会乐于遵循我们的性能指南,以至于我们必须一遍又一遍地跟他们解释那些保证他们能够战胜竞争对手的性能策略的重要性。最近我们也重构了自己的官方主页,使其能够拥有更快地响应速度与更好地性能表现。
图片 1

网络性能优化实战

优化所有资源

理解浏览器如何分析和处理资源,是显著提高性能的最强大但未充分利用的方式之一。事实证明,浏览器在嗅探资源方面非常出色,同时解析并确定其优先级。这里是关键请求的来源。

如果请求中包含用户视口中呈现内容所必需的资源,则该请求至关重要。

对于大多数网站,它将是HTML、必要的CSS、logo、网络字体,也可能是图片。在许多情况下,几十个其他不相关的资源(JavaScript、跟踪代码、广告等)影响了关键请求。幸运的是,我们能够通过仔细挑选重要资源并调整优先级来控制这种行为。

通过“我们可以手动强制调高资源的优先级,确保所需的内容按时呈现。这种技术可以显著改善“交互时间”指标,从而使最佳的用户体验成为可能。

图片 2

关键请求对许多人来说,似乎仍然是一个黑匣子,可共享资料的缺乏并不能改变现状。幸运的是,Ben
Schwarz
发表了关于这个问题的非常全面并平易近人的文章——关键请求。另外,请参阅Addy的文章,在Chrome中的预加载、预取和优先级(Preload,
Prefetch and Priorities in
Chrome)。

图片 3

[在Chrome开发人员工具中启用优先级]

要跟踪在请求优先级处理方面的情况,请使用Lighthouse性能工具和关键请求链审核工具,或查看Chrome开发人员工具中“网络”选项卡下的请求优先级。

性能调优始于设计

在前端项目中,我们常常与产品经理以及UI设计讨论如何在美感与性能之间达到平衡,我们坚信更快地内容呈现是好的用户体验的不可分割的一部分。在我们自己的网站中,我们是以性能优于美感。好的内容、布局、图片与交互都是构成你网站吸引力的不可或缺的部分,不过这些复杂的元素的使用往往也意味着页面加载速度的增加。设计的核心即在于决定我们网站需要呈现哪些内容,往往这里的内容会指图片、字体这样的偏静态的部分,我们首先也从对于静态内容的优化开始。

首屏一秒渲染原则

对于APP里面的H5页面首屏渲染时间不能超过1秒,首屏不要加载太多资源。Google提出了1秒钟完成首屏页面的渲染!

图片 4

  1. 服务器响应必须小于200ms
  2. 尽量少的重定向
  3. 尽量少的第一次渲染请求数
  4. 避免过多阻塞的JS、CSS
  5. 给浏览器留200ms的渲染时间
  6. 优化我们的JS执行效率和渲染时间

通用性能清单

  1. 积极地缓存
  2. 启用压缩
  3. 优化关键资源的优先级
  4. 使用CDN(Content Delivery Networks)

Static Site Generator

为了演示与测试方便,我们基于NodeJS搭建了一个混合使用MarkDown与JSON作为配置的静态网站生成器,其中一个简单的博客类型的网站的配置信息如下:

JavaScript

{ “keywords”: [“performance”, “critical rendering path”, “static site”,
“…”], “publishDate”: “2016-08-12”, “authors”: [“Declan”] }

1
2
3
4
5
{
  "keywords": ["performance", "critical rendering path", "static site", "…"],
  "publishDate": "2016-08-12",
  "authors": ["Declan"]
}

而其内容为:

JavaScript

# A case study on boosting front-end performance At [De
Voorhoede]() we try to boost front-end
performance… ## Design for performance In our projects we have daily
discussions…

1
2
3
4
# A case study on boosting front-end performance
At [De Voorhoede](https://www.voorhoede.nl/en/) we try to boost front-end performance…
## Design for performance
In our projects we have daily discussions…

下面,我们就这个静态网站,进行一些讨论。

加载优化

图片优化

图片通常占网页传输的大部分有效载荷,因此图片优化可以带来最大的性能提升。有许多现有的策略和工具可以帮助我们删除额外的字节,但是首先应考虑的问题是:“图片对于我想传达的信息和效果至关重要吗?”。如果可以消除它,不仅可以节省带宽,而且还节省了请求。

在某些情况下,可以通过不同的技术实现类似的结果。比如CSS就具有艺术方向的一系列属性,例如阴影、渐变、动画及形状,允许我们构造适当风格的DOM元素。

Image Delivery

图片是网站的不可或缺的部分,其能够大大提升网站的表现力与视觉效果,而目前平均大小为2406KB的网页中就有1535KB是图片资源,可见图片占据了静态资源多么大的一个比重,这也是我们需要重点优化的部分。
图片 5

减少HTTP请求

尽量减少页面对后台的请求数,能合并的合并。

  • 合并CSS、JavaScript等代码
  • 合并小图片,使用雪碧图

选择正确的格式

如果不能舍弃图片,确定哪种格式更合适就很重要了。首先要在矢量和光栅图形之间做出选择:

  • 矢量图形:分辨率独立,通常体积更小。非常适合logo、icon和简单的图形,包括基本形状(线,多边形,圆和点)。
  • 光栅图形:呈现更详细的信息,比较适合相片。

做出首个决定后,可以选择以下几种格式:JPEG、GIF、PNG–8、PNG–24,或最新的
WEBP 与 JPEG-XR
格式。有了这么多的选项,如何确保我们做出正确的选择?以下是找出最佳格式的基本方法:

  • JPEG:颜色非常丰富的图片(例如照片)
  • PNG–8:色彩相对单一的图片
  • PNG–24:局部透明的图片
  • GIF:动图

Photoshop可以通过各种设置,例如降低质量、降低噪音或色彩数量来优化以上每一种格式。确保设计师了解上述性能实践,并能够使用正确的方式优化相应格式的图片。如果您想了解更多如何处理图片,请阅读
Lara Hogan 的好文 Designing for
Performance。

WebP

WebP
是面向现代网页的高压缩低损失的图片格式,通常会比JPEG小25%左右。然后WebP目前被很多人忽视,也不常使用。截止到本文撰写的时候,WebP目前只能够在Chrome,
Opera and Android (大概占用户数的
50%)这些浏览器中使用,不过我们还是有办法以JPG/PNG来弥补部分浏览器中不支持WebP的缺憾。

使用响应性网页设计,避免重定向

响应性网页设计是指通过同一网址提供相同HTML代码的网站设计方法,使用户不用考虑所使用的是PC、Pad、APP设备,自动适应所使用的设备屏幕。

试用新格式

图像格式有几个较新的玩家,即WebP、JPEG 2000 和
JPEG-XR。它们都是由浏览器厂商开发的:Google 的 WebP,Apple 的 JPEG 2000
和 Microsoft 的 JPEG-XR。

WebP
是最受欢迎的竞争者,支持无损和有损压缩,这使得它非常灵活。无损的 WebP
比 PNG 小26%,比 JPG 小25-34%
。WebP
有着74%的浏览器支持,它可以安全地进行降级,最多可节省1/3的传输字节。JPG
和 PNG 可以在 Photoshop
和其他图像处理应用程序以及命令行界面(brew install webp)中转换为WebP。

如果你想探索其他格式之间的视觉差异,推荐 Github 上这个很赞的
Demo。

picture标签

使用picture标签可以方便的对于WebP格式不支持的情况下完成替换:

XHTML

<picture> <source type=”image/webp” srcset=”image-l.webp”
media=”(min-width: 640px)”> <source type=”image/webp”
srcset=”image-m.webp” media=”(min-width: 320px)”> <source
type=”image/webp” srcset=”image-s.webp”> <source
srcset=”image-l.jpg” media=”(min-width: 640px)”> <source
srcset=”image-m.jpg” media=”(min-width: 320px)”> <source
srcset=”image-s.jpg”> <img alt=”Description of the image”
src=”image-l.jpg”> </picture>

1
2
3
4
5
6
7
8
9
<picture>
  <source type="image/webp" srcset="image-l.webp" media="(min-width: 640px)">
  <source type="image/webp" srcset="image-m.webp" media="(min-width: 320px)">
  <source type="image/webp" srcset="image-s.webp">
  <source srcset="image-l.jpg" media="(min-width: 640px)">
  <source srcset="image-m.jpg" media="(min-width: 320px)">
  <source srcset="image-s.jpg">
  <img alt="Description of the image" src="image-l.jpg">
</picture>

这里我们使用了 picturefill by Scott
Jehl作为Polyfill库来保证低版本的浏览器中能够支持picture标签,并且保证跨浏览器的功能一致性。并且我们还使用了img标签来保证那些不支持picture的浏览器能够正常工作。

使用浏览器缓存

使用浏览器缓存减少对服务器的请求,所有可缓存静态资源(JS、CSS、图像、媒体文件、PDF文件)都应该在服务器端启用浏览器缓存(缓存一切可以缓存的资源)。注:
HTML不是静态资源。

  • 设置Expires报头为将来某个时间,比如设置为1周。则浏览器在这一周内访问将使用已经缓存的资源,不会发出GET请求去网络查看资源是否发生改变。除非用户手动清除了缓存。

图片 6

对于设置了缓存的网络请求我大致画了一个流程图如下:

图片 7

  • 上面提到的使用外联式引用CSS、JavaScript可以启动浏览器的缓存功能

用工具和算法进行优化

即使使用了高效的图像格式,也不应跳过后处理优化。这一步很重要。

如果您选择了尺寸相对较小的
SVG,它们也是可以再次压缩的。SVGO
是一个命令行工具,可以通过剥离不必要的元数据来快速优化
SVG。另外,如果您喜欢Web界面或受操作系统的限制,请使用 Jake
Archibald 的
SVGOMG。因为 SVG 是基于 XML
的格式,它也可以在服务器端进行 GZIP 压缩。

ImageOptim
是大多其他图像类型的最好选择。包括 pngcrush、pngquant、MozJPEG、Google
Zopfli等,它在一个全面的开源包中捆绑了一大堆优秀的工具。ImageOptim
可以以 Mac OS 应用程序、命令行界面和 Sketch
插件形式,轻松地实现到现有的工作流程中。对于那些在 Linux 或 Windows
上的场景,大多数 ImageOptim 的 CLI 都可以在您的平台上使用。

如果您倾向于尝试新兴的编码器,Google 今年早些时候发布了
Guetzli——源自
WebP 和 Zopfli 的开源算法。Guetzli
可以比任何其他可用的压缩方法生成35%更小体积的
JPEG
。唯一的缺点是:处理时间慢(CPU 每处理百万像素需要1分钟)。

选择工具时,请确保它们生成所需的结果并适应团队的工作流程。理想情况是,将优化过程自动化,这样就不会产生漏掉的情况。

图片多格式生成

现在我们已经可以通过设置不同的图片尺寸、格式来保证图片的分发优化,不过我们总不希望每次要用一张图片的时候就去生成6个不同的尺寸/实例。我们希望有一种抽象的方法可以帮我们自动完成这一步,为我们自动生成不同的格式/尺寸,然后自动插入合适的picture元素,在我们的静态网站生成器中是这么做的:

  • 首先是要gulp
    responsive来生成不同尺寸的图片,该插件同样会输出WebP格式的图片
  • 压缩生成好的图片
  • 用户只需要在MarkDown中编写![Description of the image](image.jpg)即可
  • 我们自定义的MarkDown渲染引擎会在处理过程中自动使用picture元素替换这些img标签

启用压缩、合并功能

通过对HTML、CSS、JavaScript等资源进行压缩合并。并在服务器端设置GZip。

  • 文件资源压缩:将多余的空格、换行符、缩进、注释等不必要的字节去掉从而提高下载、解析、执行速度,这一类的在线工具比较多,这里列举几个如下:

    • 在线JS/CSS/HTML压缩
    • Minify your
      JavaScript
    • YUI
      Compressor
  • 合并文件:每一个CSS、JS文件都是一个HTTP请求,适当将相关的多份文件合并成一个文件以减少HTTP的请求数。

    • minify
  • 启动网络服务器压缩功能:Apache、Nginx、IIS都支持配置压缩功能。

由于我们后台项目采用了.NET架构,所以我们在此针对IIS进行压缩功能的配置。IIS默认是启动压缩功能的,IIS支持“静态内容压缩”和“动态内容压缩”两种,如下图,

图片 8

另外微软为我们提供了一份很好的文档:Configuring HTTP Compression in IIS
7.aspx)

响应式图片

十年前,我们使用一种分辨率,就可以为所有人服务,但时代变化太快,现今的响应式
Web
已非往日可比。这也是为什么我们必须要特别留心,去精心优化视觉资源,确保它们适应各种视口设备。幸运的是,感谢
Responsive Images
社区小组,我们可以完美使用 picture
元素和 srcset 属性(二者都有85%+支持率)。

SVG Animation

我们的网站中也存在着很多的Icon以及动画性质图片,这里我们是选择SVG作为Icon与Animation的格式,主要考虑有下:

  • SVG是矢量表示,往往比位图文件更小
  • SVG自带响应式功效,能够根据容器大小进行自动缩放,因此我们不需要再为了picture元素生成不同尺寸的图片
  • 最重要的一点是我们可以使用CSS去改变其样式或者添加动画效果,关于这一点可以参考CodePen上的这个演示
    点击预览

    图片 9

首屏加载、按需加载、预加载

首屏应该尽量控制在1秒之内;对于相当屏幕不用的资源应该放到用户需要的时候再加载(延迟加载、上拉滚屏加载);可感知和不可感知的加载(Loading加载进度条、提前加载下一页)。

srcset 属性

srcset在分辨率切换方案中效果最佳——即当我们需要根据用户的屏幕密度和大小显示图像时。基于srcsetsize属性中的一组预定义规则,浏览器将选择最佳图片,相应地提供给视口。这项技术可以带来很大的带宽和请求节省,特别是对于移动用户。
图片 10
[srcset 使用示例]

Custom Web Fonts

我们首先回顾下浏览器是如何使用自定义字体的,当浏览器识别到用户在CSS中基于@font-size定义的字体时,会尝试下载该字体文件。而在下载的过程中,浏览器是不会展示该字体所属的文本内容,最终导致了所谓的Flash of Invisible Text现象。现在很多的网站都存在这个问题,这也是导致用户体验差的一个重要原因,即会影响用户最主要的内容浏览这一操作。而我们的优化点即在于首先将字体设置为默认字体,而后在自定义的Web
Font下载完毕之后对标准字体再进行替换操作,并且重新渲染整个文本块。而如果自定义的字体下载失败,整个内容还是能保证基本的可读性,不会对用户体验造成毁灭性的打击。
图片 11

首先,我们会为需要使用到的Web
Fonts创建最小子集,即只将那些需要使用的字体提取出来,而并不需要让用户下载整个字体集,这里推荐使用Font
squirrel webfont
generator。另外,我们还需要为字体的下载设置监视器,即保证能够在字体下载完毕之后自动回调,这里我们使用的是fontfaceobserver,它会为页面自动创建一个监视器,在侦测到所有的自定义Web
Fonts下载完毕后,会为整个页面添加默认的类名:

CSS

html {font-family: Georgia, serif;} html.fonts-loaded {font-family:
Noto, Georgia, serif;}

1
2
html {font-family: Georgia, serif;}
html.fonts-loaded {font-family: Noto, Georgia, serif;}

不过现在CSS的font-display属性也原生提供了我们这种替换功能,更多详情可见font-display属性。

渲染优化

picture 元素

picture元素和media属性旨在使艺术设计变得容易。通过为不同情形提供不同图片(通过媒体查询进行测试),无论什么分辨率,我们都能始终将图像中最重要的元素保持在焦点。
图片 12
[picture 元素使用示例]

请务必阅读 Jason Grigsby 的 Responsive
Images
101指南,以便对这两种方法进行彻底的阐述。

JS 与 CSS 的懒加载

总的来说我们希望所有的资源能够尽可能快地加载完毕,不过往往为了保证首页加载的速度,我们会考虑将部分非首屏需要的JS/CSS文件进行延迟加载,或者对于重复的视图使用浏览器本地缓存。

HTML中添加Viewport来加速页面的渲染

<meta name="viewport" content="width=device-width, initial-scale=1">

使用图片 CDN 进行分发

视觉优化的最后一步是分发。所有资源都可以从使用 内容分发网络
中受益,但还有一些针对图片优化的特定工具,例如
Cloudinary 和
imgx。使用这些服务的好处远远超过了减少服务器上的流量,并显着降低了响应延迟。

CDN可以很好的解决重图片网站的复杂度,包括响应式服务与图片优化。虽然产品不同(价格也是如此),但是大多数方案都是根据设备和浏览器,调整大小、裁剪来确定哪种格式最适合用户。甚至更多——它们可以压缩、检测像素密度、水印、识别面部,并允许后置处理能力。借助这些强大的功能,和将参数附加到URL的能力,以用户为中心的图片服务变得十分容易。

Lazy Load JS

目前来说,我们的网站都是偏向于静态,并不需要太多的JavaScript介入,不过考虑到日后的扩展空间,我们还是构建了一套完整的JS的工作流。众所周知,如果将JS直接放置到head标签中,其会阻塞整个页面的渲染。对于该点,最简单的方式就是将会阻塞渲染的JS脚本移动到页面的尾部,在整个首屏渲染完毕之后再进行加载。另一个常用的手段就是依然保持JS文件位于head标签中,不过为其添加一个defer的属性,这保证了浏览器只会先将该脚本下载下来,然后等到整个页面加载完毕再执行该脚本。
另一个需要注意的是,因为我们并不使用类似于jQuery这样的第三方依赖库,而更多的依赖于浏览器原生的特性,因此我们希望在合适的浏览器内加载合适版本的JS代码,其效果大概如下:

XHTML

<script> // Mustard Cutting if (‘querySelector’ in document &&
‘addEventListener’ in window) { document.write(‘<script
src=”index.js” defer></script>’); } </script>

1
2
3
4
5
6
<script>
// Mustard Cutting
if (‘querySelector’ in document && ‘addEventListener’ in window) {
  document.write(‘<script src="index.js" defer></script>’);
}
</script>

减少DOM节点

DOM节点太多会影响页面的渲染,尽量减少DOM节点

图像性能清单

  1. 选择正确的图片格式
  2. 尽可能使用矢量图形
  3. 如果变化不明显,则降低图片质量
  4. 使用新格式图片
  5. 使用工具与算法优化
  6. 学习srcsetpicture
  7. 使用图片 CDN

Lazy Load CSS

正如上文所述,我们的网站偏向于静态展示,因此首屏的最大问题就是CSS文件的加载问题。浏览器会在head标签中声明的所有CSS文件下载完毕之前一直处于阻塞状态,这种机制很是明智的,不然的话浏览器在加载多个CSS文件的时候会进行重复的布局与渲染,这更是对于性能的浪费。
为了避免非首屏的CSS文件阻塞页面渲染,我们使用loadCSS这个小的工具库来进行异步的CSS文件加载,它会在CSS文件加载完毕后执行回调。不过,异步加载CSS也会带来一个新的问题,如果我们将所有的CSS全部设置为了异步加载,那么用户会首先看到单纯的HTML页面,这也会给用户不好的体验。那么我们就需要在异步加载与首屏渲染之间找到一个平衡点,即首先加载那些必要的CSS文件。
我们一般将首屏渲染中必要的CSS文件成为Critical
CSS,即关键的CSS文件,代指在保证页面的可读性的前提下需要加载的最少的CSS文件数目。Critical
CSS的选定会是一个非常耗时的过程,特别是我们网站本身的CSS样式设置也在不停变更,我们不可能完全依赖于人工去提取出关键的CSS文件,这里推荐Critical这个辅助工具能够帮你自动提取压缩Critical
CSS。下图的一个对比即是仅加载Critical CSS与加载全部CSS的区别:

图片 13

上图中红色的线,即是所谓的折叠分割点。

动画优化

  • 尽量使用CSS3动画
  • 合理使用requestAnimationFrame动画代替setTimeout
  • 适当使用Canvas动画
    5个元素以内使用css动画,5个以上使用Canvas动画(iOS8可使用webGL)

Web 字体优化

自定义字体是一项非常强大的设计工具。但是能力伴随着很多责任。现有68%的网站在使用
Web字体,这种类型的资源是性能杀手之一
(平均轻松可达100KB,取决于变体和字体的数量)。

即使体积不是最大的问题,不可见文本闪动(FOIT)也算是。当Web字体加载中或加载失败时,会发生FOIT,这会让空白页面,从而导致内容无法访问。首先仔细检查我们是否需要Web字体可能是值得的。如果真是这样,有一些策略可以帮助我们减轻对业务的负面影响。

服务端与缓存

高性能的前端离不开服务端的支持,在我们的实践中也发现不同的服务端配置同样会影响到前端的性能。目前我们主要使用Apache
Web Server作为中间件,并且通过HTTPS来安全地传递内容。

CSS优化

You can leave a response, or trackback from your own site.

Leave a Reply

网站地图xml地图