性能优化之-更高效的数据渲染

这篇具有很好参考价值的文章主要介绍了性能优化之-更高效的数据渲染。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言:中心思想还是让请求的资源得到更快响应的方法,比如压缩资源,减少数据量的大小,缓存数据以减少请求数量,http/2让网络传输变得更快这些,下面就让我们来看看浏览器是如何解析这些数据,最终又是如何将他们渲染在屏幕上的?在数据量不变的情况下还有哪些可以优化的点?

浏览器怎么渲染的,从输入一个路径地址开始

当浏览器获得一个html文件时,会“自上而下”加载,并在加载过程中进行解析渲染。
步骤: 构建DOM 和 CSSOM -> 构建render树 -> 布局render树 -> 绘制render树

1. 将HTML解析成一个DOM(文档对象模型)

浏览器会解析html文件中的标签,例如:<html></body><p>,给这些标签打上标记,遇到标记后浏览器使用令牌生成器开始生成令牌,例如:<p>hello</p>这样一个文本标签会生成:StartTag:p, hello, EndTag:p这样3个令牌,接着生成对应的nodes(节点)后就形成了DOM,也就是文档对象模型(Document Object Model,简称DOM))
![在这里插入图片描述](https://img-blog.csdnimg.cn/fe932a8694dd40bc927fec0f0a07cd34.png
性能优化之-更高效的数据渲染
性能优化之-更高效的数据渲染

2. 将CSS解析成 CSSOM(层叠样式表对象模型)

当html解析中遇到< link >标签时,会请求对应的CSS文件,当CSS文件就位时便开始解析它(如果遇到行内< style

时则直接解析),这一解析过程可以和构建DOM同时进行。 那其实css树构建的过程和dom树类似。也是经历了打标记, 生成令牌和节点的过程,不过这里的识别标记规则和dom不一样,因为css拥有继承属性的操作方式,父级部分属性样式会被子级样式继承,比如字体font-size,
font-weight, font-style,
行高line-height等,还有部分默认样式,如下图箭头所指便是默认的样式,红色框内是继承样式。

性能优化之-更高效的数据渲染

3. 构造 Rendering Tree。

根据DOM树,会遍历每一个可见的节点,对于每一个可见的节点,在CSSOM上找到匹配的样式并应用,生成Rendering Tree。
此时渲染树并不等同于构建DOM 树,因为如果遇到不可见(display:none)属性,会跳过该元素和其子项。另外在html的head里不包含任何可见信息,所以这部分的内容会被很快的去除;
性能优化之-更高效的数据渲染

4. 布局

有了Render Tree,浏览器已经能知道网页中有哪些节点、各个节点的CSS定义以及他们的从属关系。下一步就是计算出每个节点在屏幕中的位置和大小,这个操作称之为Layout。

5. 绘制

即遍历render树,并使用UI后端层绘制每个节点以像素显示在屏幕上。
这里需要注意的是:
1、 并不是所有的数据都已经加载出来了,而是先显示一部分,再显示另一部分。
2、 虽然是从上往下加载,但并不是一定要等着上面的内容显示之后才显示下面的内容,而是谁解析的快,就渲染的越快。
3、 CSS 加载不会阻塞 DOM 的加载,但是会阻塞 Dom 的渲染。虽然DOM 和 CSSOM 通常是并行构建的,但是Render Tree 是依赖于 DOM Tree 和 CSSOM Tree 的,所以他必须等待到 CSSOM Tree 构建完成,也就是 CSS 资源加载完成后,才能开始渲染。
如果引用的是外部样式,需要等待这些样式全部加载完后,才开始构建CSSOM。因为css文件中包含大量的样式,后面的样式会覆盖前面的样式,如果我们提前就构建CSSDOM,可能会得到错误的结果。
4、 JS文件不只是阻塞DOM的构建,它会导致CSSOM也阻塞DOM的构建;在构建DOM时,HTML解析器若遇到了JavaScript,那么它会暂停构建DOM,将控制权移交给JavaScript引擎,等JavaScript引擎运行完毕,浏览器再从中断的地方恢复DOM构建。
这是因为JavaScript不只是可以改DOM,它还可以更改样式,也就是它可以更改CSSOM。因为不完整的CSSOM是无法使用的,如果JavaScript想访问CSSOM并更改它,那么在执行JavaScript时,必须要能拿到完整的CSSOM。也就是说,在这种情况下,浏览器会先下载和构建CSSOM,然后再执行JavaScript,最后在继续构建DOM。
所以,如果我们想首屏渲染的越快,就越不应该在首屏就加载 JS 文件,这也是都建议将 script 标签放在 body 标签底部的原因。当然在当下,并不是说 script 标签必须放在底部,因为你可以给 script 标签添加 defer(延迟执行) 或者 async(异步下载) 属性;

关键渲染路径优化

关键渲染路径是浏览器将 HTML、CSS、JavaScript
转换为在屏幕上呈现的像素内容所经历的一系列步骤。也就是我们刚刚提到的的的浏览器渲染流程。

1、将能快速解析的数据放在前面,不好解析的放在后面

html语义化标签加强DOM解析,因为语义化标签是浏览器内置就能解析识别的标签;
尽量不要使用 table 布局。因为可能很小的一个小改动会造成整个 table 的重新布局,并且table不是一点一点加载渲染的,是一整个加载好了才渲染的;
一些装饰性元素可以适当的使用伪元素,避免增加无意义的页面元素;

2、让CSSOM不阻塞DOM的渲染

并不是所有的CSS资源都那么的 『关键』

举个例子:一些响应式CSS只在屏幕宽度符合条件时才会生效,还有一些CSS只在打印页面时才生效。这些CSS在不符合条件时,是不会生效的,所以我们为什么要让浏览器等待我们并不需要的CSS资源呢?
我们可以将打印相关的CSS移动到print.css,然后我们在HTML中引入CSS时,添加媒体查询属性print,代码如下:

上面代码添加了media="print"属性,所以上面CSS资源仅用于打印。添加了媒体查询属性后,浏览器依然会下载该资源,但如果条件不符合,那么它就不再阻塞渲染;

上面提供的方法是针对那些不需要生效的CSS资源,如果CSS资源需要在当前页面生效,只是不需要在首屏渲染时生效,那么为了更快的首屏渲染速度,我们可以将这些CSS也设置成非关键资源。只是我们需要一些比较hack的方式来实现这个需求:

<link href="style.css" rel="stylesheet" media="print" onload="this.media='all'">

上面代码先把媒体查询属性设置成print,将这个资源设置成非阻塞的资源。然后等这个资源加载完毕后再将媒体查询属性设置成all让它立即对当前页面生效。

类似的方案还有,代码如下:

<link rel="preload" href="style.css" as="style" onload="this.rel='stylesheet'">
<link rel="alternate stylesheet" href="style.css" onload="this.rel='stylesheet'">

总结一下就是把首屏渲染需要使用的CSS通过style标签内嵌到head标签中,其余CSS资源使用异步的方式非阻塞加载。优化过后可以对照看一下FP(首次绘制)的时间点有没有提前。
性能优化之-更高效的数据渲染

3、尽可能的不使用 @import 属性,import属性会在页面加载完成之后,等效于把css写到文档的底部,并且加载多个css文件时是串行加载,所以应该避免这种情况。

4、CSS 选择符从右往左匹配查找,应避免节点层级过多,并适当使用子选择器,例如 .list>a>img

5、异步JavaScript

为了避免阻塞,可以为script标签添加async或者defer属性。async的执行是加载完成就会立马去执行,而不像defer那样要等待所有的脚本加载完后按照顺序执行,下面可以听过这个两张图来对比一下他们的区别:

蓝色:文档解析
紫色:脚本加载
黄色:脚本执行
绿色: HTML 文档被完全加载和解析完成

defer

适用于如果你的脚本代码依赖于页面中的DOM元素(文档是否解析完毕),或者被其他脚本文件依赖时。
性能优化之-更高效的数据渲染

async

适用于如果你的脚本并不关心页面中的DOM元素(文档是否解析完毕),并且也不会产生其他脚本需要的数据时。
性能优化之-更高效的数据渲染

6、减少JS操作 DOM 的次数

把 DOM 和 JavaScript 各自想象成一个岛屿,它们之间用收费桥梁连接。——《高性能 JavaScript》

DOM 是属于渲染引擎中的东西,而 JS 又是 JS 引擎中的东西。当我们用 JS 去操作 DOM 时,本质上是 JS 引擎和渲染引擎之间进行了“跨界交流”。这个“跨界交流”的实现并不简单,它依赖了桥接接口作为“桥梁”。
性能优化之-更高效的数据渲染

过“桥”要收费——这个开销本身就是不可忽略的。我们每操作一次 DOM(不管是为了修改还是仅仅为了访问其值),都要过一次“桥”。过“桥”的次数一多,就会产生比较明显的性能问题。因此“减少 DOM 操作”的建议,并非空穴来风。

1、最常见的缓存Dom对象
操作Dom一般首先会去访问Dom,尤其是像循环遍历这种事件复杂度可能会比较高的操作,那么可以在循环之前就将主节点,不必循环的Dom节点先获取到,那么在循环里就可以直接引用,而不必去重新查询。

性能优化之-更高效的数据渲染

2、vue虚拟节点
虚拟Dom是js模似DOM树并对DOM树操作的一种技术。virtual DOM是一个纯js对象(字符串对象),所以对他操作会高效。
在dom发生变化的时候对虚拟dom进行操作,通过dom diff算法将虚拟dom和原虚拟dom的结构做对比,最终批量的去修该真实的dom结构,尽可能的避免了频繁修改dom而导致的频繁的重排和重绘。

减少 reflow/repaint

Reflow(重排):当浏览器发现某个部分发生了变化,影响了布局,我们需要重新验证并计算Render Tree。是Render Tree的一部分或全部发生了变化——这就是Reflow,或是Layout。

Repaint(重绘):如果只是改变了某个元素的背景颜色,文字颜色等,不影响元素周围或内部布局的属性,将只会引起浏览器的重绘,重画某一部分。

因此看出,重排要比重绘更花费时间,也就更影响性能。所以在写代码的时候,要尽量避免过多的重排。

以下操作会导致重排或重绘:

  • 删除,增加,或者修改DOM元素节点。

  • 改变元素的大小,位置时,或者将使用display:none时,会造成重排;修改CSS颜色或者visibility:hidden等等,会造成重绘。

  • 修改网页的默认字体时。 Resize窗口的时候(移动端没有这个问题),或是滚动的时候。 内容的改变,(用户在输入框中写入内容也会)。

  • 激活伪类,如:hover。

1、减少DOM操作,比如改变元素的尺寸,位置,显隐等。可以预先定义好 css 的 class,然后修改 DOM 的 className;

2、为动画的 HTML 元件使用 fixed 或 absoult 的 position,那么修改他们的 CSS 是不会 reflow 的。

3、隐藏元素,进行修改后,然后再显示该元素。

4、可以使用文档片段创建一个子树,然后再拷贝到文档中,文档片段是一个轻量级的document对象,它设计的目的就是用于更新,移动节点之类的任务,而且文档片段还有一个好处就是,当向一个节点添加文档片段时,添加的是文档片段的子节点群,自身不会被添加进去。

let fragment = document.createDocumentFragment();
appendNode(fragment, data);
ul.appendChild(fragment);

懒加载(延迟加载)

1、图片懒加载

对页面加载速度影响最大的就是图片,一张普通的图片可以达到几M的大小,而代码也许就只有几十KB。当页面图片很多时,页面的加载速度缓慢,几S钟内页面没有加载完成,用户会失去耐心。
为了加速页面加载速度,所以很多时候我们需要将页面内未出现在可视区域内的图片先不做加载, 等到滚动到可视区域后再去加载。参考库:vue-lazyload

<img v-lazy="/static/img/1.png">

2、路由懒加载

把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样做可以减少无效资源的加载,明显减少服务器的压力和流量,也能够减小浏览器的负担。
实现:结合 Vue 的异步组件和 Webpack 的代码分割功能

const Foo = () => import('./Foo.vue')
router = new VueRouter({ routes: [ { path: '/foo', component: Foo } ]})

(图片 素材都来源网络,侵权联系立马删)文章来源地址https://www.toymoban.com/news/detail-488990.html

到了这里,关于性能优化之-更高效的数据渲染的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 解决前端性能问题:如何优化大量数据渲染和复杂交互?

    ✨✨祝屏幕前的小伙伴们每天都有好运相伴左右,一定要天天开心!✨✨  🎈🎈作者主页: 喔的嘛呀🎈🎈 目录 引言 一、分页加载数据 二、虚拟滚动 三、懒加载 四、数据缓存 五、减少重绘和回流 六、优化图片和资源: 七、合并压缩文件 八、使用Web Workers  在前端开发

    2024年03月10日
    浏览(65)
  • 使用秘籍|如何实现图数据库 NebulaGraph 的高效建模、快速导入、性能优化

    本文整理自 NebulaGraph PD 方扬在「NebulaGraph x KubeBlocks」meetup 上的演讲,主要包括以下内容: NebulaGraph 3.x 发展历程 NebulaGraph 最佳实践 建模篇 导入篇 查询篇 NebulaGraph 自 2019 年 5 月开源发布第一个 alpha 版本以来,陆陆续续发布了 2.0 GA,到现在 v3.6.0,已经是 v3.x 版本中比较后期

    2024年02月10日
    浏览(61)
  • 前端面试:【性能优化】页面加载性能、渲染性能、资源优化

    嗨,亲爱的前端开发者!在今天的Web世界中,用户期望页面加载速度快、交互流畅。因此,前端性能优化成为了至关重要的任务。本文将探讨三个关键方面的性能优化:页面加载性能、渲染性能以及资源优化,以帮助你构建更快速、响应更快的Web应用程序。 1. 页面加载性能:

    2024年02月11日
    浏览(54)
  • 性能优化-卡牌项目渲染优化

    CPU 影响帧率 GPU 影响帧率 内存 超了会崩 显存 显存超了画面会异常,甚至可能导致游戏崩溃 带宽 影响耗电 设备性能不行又要求流畅,降低目标渲染分辨率,立竿见影,但是会牺牲画质 1 使用烘焙,减少实时渲染 2 静态合批,不动的做出Static的物体 1 遮挡剔除:被挡住看不见

    2024年03月20日
    浏览(51)
  • 前端--性能优化【上篇】--网络优化与页面渲染优化

    link标签的rel属性设置dns-prefetch,提前获取域名对应的IP地址 用户与服务器的物理距离对响应时间也有影响。 内容分发网络(CDN)是一组分散在不同地理位置的 web 服务器,用来给用户更高效地发送内容。典型地,选择用来发送内容的服务器是基于网络距离的衡量标准的。 优

    2024年02月08日
    浏览(44)
  • 前端性能优化之浏览器渲染优化

    在当今互联网高速发展的时代,用户对于网页加载速度和性能的要求越来越高。作为前端开发者,我们需要关注并致力于提升网页的加载和渲染性能,以提供更好的用户体验。而浏览器渲染优化正是我们实现这个目标的关键。在本文中,我们将探讨一些关于浏览器渲染优化的

    2024年02月11日
    浏览(41)
  • Unity 性能优化五:渲染模块压力

    Batching 在GPU渲染前,CPU会把数据按batch发送给GPU,每发送一次,都是一个drawcall,GPU在渲染每个batch的时候,会切换渲染状态,这里的渲染状态指的是: 影响对象在屏幕上的外观的渲染属性或材质,比如:材质球,贴如,颜色,渲染模式(透明、半透明)等 unity中的合批方式:

    2024年02月14日
    浏览(38)
  • 【Angular性能优化】项目8版本加载速度缓慢、白屏时间、首页渲染性能优化方案

    随着业务的代码一点点增加,加上Angular的项目本身就比 vue、react 的重一些,随之而来的启动速度,更改文件后编译速度,以及打包速度也会变慢,于是乎想着优化下我们的项目。 本文章主要说的是 : 打包Angular项目的一些配置,性能优化方面的方案 打包后,用户进入页面的

    2024年04月10日
    浏览(51)
  • 理解React页面渲染原理,如何优化React性能?

    当使用React编写应用程序时,可以使用JSX语法来描述用户界面的结构。JSX是一种类似于HTML的语法,但实际上它是一种JavaScript的扩展,用于定义React元素。React元素描述了我们想要在界面上看到的内容和结构。 在运行React应用程序时,JSX会被转换成真实的DOM元素,这个过程主要

    2024年02月08日
    浏览(46)
  • 极致性能优化:前端SSR渲染利器Qwik.js

    前端性能已成为网站和应用成功的关键要素之一。用户期望快速加载的页面和流畅的交互,而前端框架的选择对于实现这些目标至关重要。然而,传统的前端框架在某些情况下可能面临性能挑战且存在技术壁垒。 在这个充满挑战的背景下,我们引入了 Qwik.js 框架。Qwik.js 不仅

    2024年02月05日
    浏览(67)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包