美文网首页
前端性能优化-更多流行优化技术

前端性能优化-更多流行优化技术

作者: 一代码农1970 | 来源:发表于2021-07-09 17:39 被阅读0次

    一、拯救移动端图标 —— SVG

    常见的字体方案经历了三种:PNG、Iconfont、SVG。

    (一)PNG

    先说说PNG,是比较早的方案了。PNG 属于一种图片格式,颜色丰富、边缘平滑,而且还支持透明度,所以最早被设计师作为 Icon 输出的格式,从而沿用到前端代码中;但这种图片icon也存在很大的缺陷:
    1、尺寸问题,必须关注图片的宽高、比例,以免导致失真、变形。
    2、请求数量和体积问题,多个图片Icon需要通过雪碧图等技术来规避请求数量,而雪碧图的应用还需要关心icon的定位。
    3、灵活性,比较难以使用CSS3中的一些属性,效果不佳。比如:hover、阴影、transform、filter。

    (二)Iconfont

    Iconfont 是将图标制作成为了字体,从而利用上了字体的诸多优点,基本上能够规避 PNG 大部分缺点:
    1、请求数量,只需要考虑字体文件的加载即可。
    2、矢量图形足够灵活,像字体能够使用的 CSS 属性皆可使用,从而不必关心宽高、比例等问题(只需设置字体大小即可)。

    Iconfont 也存在一个致命问题:Icon 是单色的,或者仅能使用 CSS3 变色。
    Iconfont 背后原理是怎样的呢?
    1、将Icon制作成字体文件
    2、字符是如何被计算机渲染的?通过 i 标签(比较常见),并设置 class 来添加伪元素,而伪元素的值为字体文件中的字形编码,浏览器通过字形编码找到字符并渲染出来的。

    字符是如何被计算机渲染的?
    绝大多数的字体都包含一个或多个Charmap,它的作用是就是把一个字符从它的字符编码印射到字形索引。
    一般一个字符的渲染过程是这样的:
    1、加载字体文件
    2、确定要输出的字体大小
    3、输入这个字符的编码值
    4、根据字体文件中的 Charmap,把编码值转换成字形索引(就是这个字符对应字体文件中的第几个形状)
    5、根据索引从字体中加载这个字形
    6、将这个字形渲染成位图,有可能进行加粗、倾斜等变换。

    (三)SVG

    SVG 的优点:
    1、作为普通的页面元素,更具语义化
    2、矢量图形,足够灵活
    3、保持图片能力,支持彩色图标
    4、节省体积(Iconfont 往往需要一整套字体)

    二、最新的布局方案——Grid & Flex

    布局经历了几种方案:table布局、传统布局(float、position、display、盒模型)、flex布局、grid布局。
    table布局已经彻底淘汰了,传统布局PC端还有一些使用,尤其是CSS响应式;相较于最新的Grid、Flex来说,兼容性最好,但是效率最低,开发起来比较麻烦。
    当下用的最多的是flex布局和grid布局。
    flex布局移动端用的特别多,学习成本低,开发效率高,兼容性也还不错,它依据某个轴布局,可以看做是一维布局。
    grid布局在水平垂直两个方向上同时控制,可以称之为二维布局。Grid布局非常强大,但概念也最多,学习成本高一些,兼容性不如flex。

    (一)flex布局

    (1)核心概念
    flex 容器(Flex Container)
    它是所有flex项的直接父元素。
    我们把一个元素的display属性值改为 flex 或者 inline-flex后,这个元素就会成为flex容器,而容器中的直接子元素就会变为 flex元素。
    flex容器会有一些属性,通过它可以控制flex元素的大小、顺序、对齐以及间隔。

    1、flex-direction
    flex容器最典型的特征就是拥有水平和垂直方向两个轴,它决定了flex容器的主轴是哪个方向(与主轴相对的是交叉轴),也就是flex项的排列方向。
    2、flex-wrap
    决定flex项是否换行,默认是不换行的,当容器小于flex项所需要的面积时,flex项会等比例缩小。
    3、flex-flow
    上面两个属性的简写方式。
    4、justify-content
    决定flex项目在主轴上的对齐方式。
    5、align-items
    决定flex项目在交叉轴上的对其方式。
    6、align-content
    控制“多条主轴”的 flex 项目在交叉轴的对齐。所谓“多条主轴”是指存在换行。

    flex 项(Flex Item)
    它是flex容器的直接子元素,也有一些属性可以控制flex项:

    1、order
    定义flex项在排列时的顺序,数值越小优先级越高。
    2、flex-grow
    决定了flex项宽度或者高度的增长系数,它指定了flex容器中剩余空间的多少应该分配给项目,所谓剩余的空间是指flex容器的大小减去所有flex项的大小加起来的大小。如果所有的兄弟项目都有相同的flex-grow系数,那么所有的项目将获得相同的剩余空间,否则将根据不同的flex-grow系数定义的比例进行分配。
    3、flex-shrink
    决定了flex容器空间不足时,flex项目的缩小系数,与flex-grow相对。
    4、flex-basis
    决定了主轴方向上的初始大小,也就是主轴空间。
    有以下几点需要注意:
    单独使用 flex-basis,其实是定义了最小宽度,当内容撑大时,flex项目也变大。
    单独使用width,正常使用。
    两者同时使用,会采用较大的宽度,并且内容会溢出。(不设置break-all)
    5、flex
    属性2、3、4的简写方式。
    6、align-self
    决定了flex项目在交叉轴上的排列方向,覆盖flex容器中设置的align-items。

    (二)grid布局

    (1)grid 布局的核心概念
    1、网格容器(Grid Container),它是所有网格项的直接父元素
    2、网格项(Grid Item),它是网格容器的直接子元素
    3、网格线(Grid Line),是组成网格结构的分隔线,分为水平方向和垂直方向
    4、网格单元(Grid cell),由网格线将网格容器切分而成
    5、网格轨迹(Grid track),可以简单理解为网个容器的行和列
    6、网格区域(Grid area),由网格单元组成的块

    Grid布局主要有两种元素,即网格容器和网格项,因此就有作用于这两种元素上的属性。

    (2)网格容器属性
    1、display:grid | inline-grid
    grid 中的容器元素都是块级元素,而inline-grid中的容器元素是行内元素。

    2、grid-template-columns 和 grid-template-rows
    它们分别用来定义网格的行和列,它们的取值用来定义网格的大小,而之间的间隔表示网格线,网格线可以使用中括号进行命名。例如:grid-template-columns: [firstline] 40px [secondline] 40px [thirdline] 40px [endline]。
    对于重复的取值可以用 repeat 函数简写,例如:grid-template-columns: 40px 40px 40px等价为repeat(3, 40px)。
    再来看看有取值有哪些单位:
    传统单位,例如:px、百分比、auto等等
    fr,这是网格特有的单位,表示行和列中可用空间的一等份。

    3、grid-template-areas,用来定义网格区域。

    上述网格容器属性就是将网格分割成行列,而行列又可以组成区域。划分好区域以后,我们就可以利用网格项属性将区域分配给网格项。

    4、column-gap、row-gap用来定义行列之间的间隔。
    5、justify-items用来定义网格单元的水平对齐方式。
    6、align-items用来定义网格单元的垂直对齐方式。
    7、place-items 是上述两个属性的简写方式。
    8、justify-content用来定义容器内容的水平排布方式。
    9、align-content用来定义容器内容的垂直排布方式。
    10、place-content是上述两个属性的简写方式。
    11、grid-auto-columns为那些隐式列指明宽度。
    12、grid-auto-rows为那些隐式行指明高度。
    13、grid-auto-flow为那些没有分配区域的网格项指明流动方式,是按行流动还是按列流动。

    (3)网格项属性
    1、grid-column-start、grid-column-end、grid-row-start、grid-row-end都是描述网格线的,通过这四个属性可以画出一个区域,而这个区域即分配给了网格项。
    2、grid-column、grid-row为上述四个属性的简写属性。
    3、grid-area为上述四个属性的进一步简写形式,同时其值也可以直接写为区域名称。
    4、justify-self指明网格项自身的水平对齐方式。
    5、align-self指明网格项自身的垂直对齐方式。
    6、place-self是上述两个属性的简写属性。

    三、优化资源加载的顺序

    1、Preload

    <link rel="preload" href="test.jpg">
    

    2、Prefetch包括资源预加载、DNS预解析、http预连接和页面预渲染。
    资源预加载:<link rel="prefetch" href="test.css">
    DNS预解析:<link rel="dns-prefetch" href="//haitao.nos.netease.com">
    http预连接:<link rel="prefetch" href="//www.kaola.com"> 将建立对该域名的TCP链接
    页面预渲染:<link rel="prerender" href="//m.kaola.com"> 将会预先加载链接文档的所有资源
    那么Prefetch和Preload有什么区别呢?
    具体来讲,Preload来告诉浏览器预先请求当前页需要的资源,从而提高这些资源的请求优先级。比如,对于那些本来请求优先级较低的关键请求,我们可以通过设置Preload来提升这些请求的优先级。
    Prefetch来告诉浏览器用户将来可能在其他页面(非本页面)可能使用到的资源,那么浏览器会在空闲时,就去预先加载这些资源放在http缓存内,最常见的dns-prefetch。比如,当我们在浏览A页面,如果会通过A页面中的链接跳转到B页面,而B页面中我们有些资源希望尽早提前加载,那么我们就可以在A页面里添加这些资源Prefetch,那么当浏览器空闲时,就会去加载这些资源。
    所以,对于那些可能在当前页面使用到的资源可以利用Preload,而对一些可能在将来的某些页面中被使用的资源可以利用Prefetch。如果从加载优先级上看,Preload会提升请求优先级;而Prefetch会把资源的优先级放在最低,当浏览器空闲时才去预加载。

    资源加载优先级可以放在首屏资源优化中,通过首屏那一帧找出对应的关键请求链,然后调整这些资源的加载优先级可以提高首屏加载速度。

    另外,首屏速度也可以基于关键请求链做文章,从Localstorage、缓存等角度着手。

    四、预渲染优化页面首屏

    大型单页应用的性能瓶颈:JS下载 + 解析 + 执行
    可以通过 SSR 来优化,但存在问题:需要牺牲 TTFB 来补救 First Paint,实现起来也更加复杂。
    可以通过预渲染来解决首屏问题,Pre-rendering 打包时提前渲染页面,没有服务端参与。

    五、通过 windowing 优化大型列表的渲染

    加载大的列表、大表单的每一行严重影响性能,Lazy loading 仍然会让 DOM 变得很大。
    可以参考 react-window 的做法,它仅仅渲染大数据中的部分数据(仅仅填满视窗)的方法,从而解决一些常见的问题:
    1、减少初始渲染和数据更新时的节点数量,从而获得一个更好的滚动体验
    2、减少内存占用,从而避免大量DOM节点引起的内存泄露

    六、使用骨架组件减少布局移动(Layout Shift)

    骨架组件(Skeleton/Placeholder)的作用:
    1、占位
    2、提升用户感知性能
    注意:Placeholder要根据要替换的组件进行定制,从而避免 Layout Shift。

    相关文章

      网友评论

          本文标题:前端性能优化-更多流行优化技术

          本文链接:https://www.haomeiwen.com/subject/zmgfpltx.html