您好!欢迎来到爱源码

爱源码

热门搜索: 抖音快手短视频下载   

前台工程师必备:从浏览器渲染到性能优化 《源代码交易》

  • 时间:2022-09-01 01:29 编辑: 来源: 阅读:295
  • 扫一扫,手机访问
摘要:前台工程师必备:从浏览器渲染到性能优化 《源代码交易》
本文主要谈浏览器的渲染原理、流程及相关性能问题。 问题1。为什么css需要放在头部?2.JS为什么要放在身体后面?3.图片的加载和渲染会阻碍页面DOM的构建吗?4.页面出现前DOM解析了吗?5.首屏时间是基于什么?浏览器渲染1。浏览器渲染图【来自google开发者的文档】浏览器渲染页面主要经过以下几个步骤:1。解析HTML标记,构建DOM树。 2.求解CSS标记并构建CSS SOM树 3.将DOM和CSSOM合并到一个渲染树中 4.根据渲染树进行布局,计算每个节点的几何信息。 5.在屏幕上画出每个节点。 为了构建渲染树,浏览器基本完成了以下工作:从DOM树的根节点开始,遍历每个可见节点 有些节点是不可见的(例如,脚本标签、元标签等)。)并将被忽略,因为它们不会出现在渲染输出中。 有些节点被CSS隐藏了,所以它们在渲染树中也会被忽略。例如,上面示例中的span节点——它不会出现在渲染树中——有一个显式规则在该节点上设置“display: none”属性。 对于每个可见的节点,找到适当的CSSOM规则并应用它们。 发出节点,以及它们的内容和计算的样式。 根据上面的分析,DOM树和CSSOM树的构造对页面性能有很大的影响。没有DOM树,页面没有基本的标签块,没有样式,页面基本是空白的。 那么具体css的解析规则是什么呢?js是如何影响页面渲染的?通过理解这一点,我们可以优化页面的性能。 2.css解析规则< div id="div1 " >& ltdiv class = " a " & gt& ltdiv class="b " >...& lt/div & gt;& ltdiv class="c " >& ltdiv class="d " >...& lt/div & gt;& ltdiv class="e " >...& lt/div & gt;& lt/div & gt;& lt/div & gt;& ltdiv class="f " >& ltdiv class="c " >& ltdiv class="d " >...& lt/div & gt;& lt/div & gt;& lt/div & gt;& lt/div & gt;# div1.c.d {}。法国货到付款{}。{} # div1.f {}。c.d {}从左到右的匹配规则如果从左到右解析css,就意味着我们需要遍历更多的节点。 无论样式规则有多详细,每个dom节点仍然需要遍历,因为整个样式规则会有其他公共样式影响。 如果从右向左解析,因为子元素只有一个父元素,所以可以快速定位到当前dom字符不符合样式规则。 3.js加载和执行机制首先要明确。我们可以通过js修改网页的内容、风格和交互,也就是说js会影响页面的dom结构。如果js和dom是并行构建和执行的,那么就很容易发生冲突,所以js在执行时必然会阻塞dom和cssom的构建过程,无论是外部js还是内联脚本。 js的位置会影响dom解析吗?首先,为什么我们提倡在body标签后面加载js?从演示来看,页面domcontentload无论是放在头部还是放在正文之后,加载时间都是一样的:从图中我们可以看到,js的加载和执行是阻止dom解析的,但是由于页面不是一次渲染的,所以我们需要做的就是尽量让客户看到第一个屏幕是渲染的,js放在头部, 所以页面的内容区域在解析之前就被屏蔽了,导致客户看到的是白屏,而js放在了正文后面。 虽然页面的dom还没有解析,但是有些楼层已经渲染好了,这也是我们看重页面首屏时间的原因。 只有建立DOM和CSSOM树并合并成渲染树,才能绘制页面图形。是不是整个DOM树和CSSOM树都是先建好才能画页面图形?显然,这不符合我们平时访问页面的认知。事实上,为了实现更好的客户体验,演示引擎会尽量将内容尽快显示在屏幕上。 它不必等到整个HTML文档都解析完了,而是会开始构建渲染树并设置布局。 在不断从网络接收和解析其他内容的同时,呈现引擎将解析和显示一些内容。 浏览器什么时候做初始图?您可以查看本文对浏览器首次呈现时间的探索。 4.图片加载和渲染机制首先我们来回答上面的问题:图片的加载和渲染会不会阻碍页面渲染?答案是图片的加载和渲染不会影响页面的渲染。 那么标签中的图片和样式中的图片的加载和渲染时间是多少呢?解析HTML[遇到标签加载图片]-->:构建DOM树加载样式-->:解析样式[背景图片链接does--> load]-->:构建样式规则树并加载JavaScript-->:执行JavaScript代码匹配DOM树和样式规则树构建渲染树[遍历DOM树时在对应的样式规则上加载背景图片]计算布局绘制的元素位置[开始渲染图片]当然,在匹配DOM树和样式规则树构建渲染树时,只会将可见的元素及其对应的样式规则组合输出到渲染树,也就是说有不可见的在匹配DOM树和样式规则树时,如果发现某个元素对应的样式规则有display:none,浏览器会认为该元素是不可见的,所以不会输出到渲染树。 优化性能。最小化层次结构# div p . class { color:red;} .类{颜色:红色;}层次的减少意味着匹配时遍历的dom更少。 关于少嵌套的编写规范也是基于这个原因。 2.使用类选择器而不是标签选择器来减少匹配的数量。3.按需加载CSS(function(){ window . gconfig = window . gconfig | | { };window . gconfig . is mobile =/iPhone | iPad | iPod | Android/I . test(navigator . user agent);var hClassNameif(window . gconfig . is mobile){ h class name = ' phone ';document . write(' & lt;link rel = " style sheet " href = " https://RES . HC-cdn . com/c page-pep-discount-area-V6/2 . 0 . 24/m/index . CSS "/& gt;');document . write(' & lt;' link rel = " preload " href = "//RES . HC-cdn . com/c page-pep-discount-area-V6/2 . 0 . 24/m/index . js " cross origin = " anonymous " as = " script "/>);} else { hClassName = ' pcdocument . write(' & lt;link rel = " style sheet " href = " https://RES . HC-cdn . com/c page-pep-discount-area-V6/2 . 0 . 24/PC/index . CSS "/& gt;');document . write(' & lt;' link rel = " preload " href = "//RES . HC-cdn . com/c page-pep-discount-area-V6/2 . 0 . 24/PC/index . js " cross origin = " anonymous " as = " script "/>);} var root = document . document element;root . class name+= hClassName;})();Async和defender[来自https://www . growingwiththeweb . com/2014/02/async-vs-defender-attributes . html]使用(1)如果脚本是模块化的,不依赖于任何脚本,请使用async。 (2)如果脚本依赖于另一个脚本,请使用defer。 减少资源请求的并发浏览器是有限的,所以为了减少浏览器中很多不必要的资源优先加载造成的页面渲染的阻塞时间和网络请求响应时间,首先要想到减少页面加载的资源,尽量通过压缩合并、懒人加载等方法减少页面的资源请求。 推迟加载图像虽然图像的加载和渲染不会影响页面渲染,但是我们需要对图像进行延迟加载,以便首先显示第一个屏幕图像,并尽可能减少资源请求的数量。 document . addevent listener(" DOMContentLoaded ",function(){ let lazy images =[]. slice . call(document . query selectorall(" img . lazy "));让active = falseconst lazy load = function(){ if(active = = = false){ active = true;settime out(function(){ lazy images . foreach(function(lazy image){ if((lazy image . getboundingclientrect()。top & lt= window.innerHeight & amp& amplazy image . getboundingclientrect()。bottom & gt= 0)& amp;& ampgetComputedStyle(lazyImage)。展示!= = " none "){ lazy image . src = lazy image . dataset . src;lazy image . srcset = lazy image . dataset . srcset;lazy image . class list . remove(" lazy ");lazy images = lazy images . filter(function(image){返回图像!= = lazyImage});if(lazy images . length = = = 0){ document . remove event listener(" scroll ",lazy load);window . removeeventlistener(" resize ",lazy load);window . removeeventlistener(" orientation change ",lazy load);} } });active = false}, 200);} };document . addevent listener(" scroll ",lazy load);window . addevent listener(" resize ",lazy load);window . addevent listener(" orientation change ",lazy load);});参考延迟加载图片和视频的做法来推广活动。2.1惰性加载和异步加载。惰性加载和异步加载是优化活动性能的主要手段。说白了,就是把所有客户不需要或者不会马上看到的页面数据和内容,在页面首屏渲染后,都移到页面首屏进行加载,把页面渲染首屏的数据加载量和js、css执行带来的性能损失降到最低。 2.1.1导航下拉异步加载导航下拉内容是一个非常复杂的html片段。如果直接加载,浏览器渲染时间会拖慢页面的整体加载时间:所以我们需要通过异步加载来获取这个html片段,然后在页面第一次屏幕渲染后再添加到页面中。大致代码如下:$。ajax({ url: url,async: false,timeout: 10000,success:function(data){ container . innerhtml = data;var append html = $(' & lt;' div class = " footer-wrapper " >;'+container . query selector(' # footer ')。innerHTML+' & lt;/div & gt;');var tempHtml = ' & ltdiv style = " display:none;"& gt+' & lt;script type = " text/html " id = " header-lazy load-html-drop " class = " header-lazy load-html " data-holder = " # holder-drop " & gt;+append html . find(' # header-lazy load-html-drop ')。html()+' & lt;\/script & gt;& ltscript type = " text/html " id = " header-lazy load-html-MB nav " class = " header-lazy load-html " data-holder = " # holder-MB nav " & gt;+append html . find(' # header-lazy load-html-MB nav ')。html()+' & lt;\/script & gt;& lt/div & gt;;$('#footer ')。append(tempHtml);Fe loader . onload(function(){ Fe loader . use(' @ cloud/common-resource/header ',function(){ });$('#footer ')。css('display ',' block ');});},error: function (XMLHttpRequest,textStatus,error thrown){ console . log(XMLHttpRequest . status,XMLHttpRequest.readyState,text status);}, });2.1.2图片的懒人加载。官网的cui套件中已经有懒加载插件支持图片的懒加载。使用页面非常简单:;& ltimg class = " lazy load " data-src = " http://www . place hold . it/375 x200/eee/444/2 " src = " placeholder image URL "/>;& ltimg class = " lazy load " data-src = " http://www . place hold . it/375 x200/eee/444/3 " src = " placeholder image URL "/>;& ltdiv class = " lazy load " data-src = " http://www . place hold . it/375 x200/eee/444/3 " & gt;& lt/div & gt;...& lt/div & gt;从代码中,我们几乎可以猜出图片的懒加载原理。事实上,通过覆盖img标签的src属性,我们使得img标签在开始加载时不加载图片,因为没有src的具体图片地址。重要资源加载后,通过监控onload的时间或滚动条滚动时间,重写相应标签的src值,实现图片的懒加载:/* * loadimage * @ param { html element } El-the IMAGE element * @ private */_ load(El){ let source = El . getattribute(ATTR _ IMAGE _ URL);if (source) {让处理器= this。_ config.processorif(processor){ source = processor(source,El);} el.addEventListener('load ',()= & gt{ El . class list . remove(class name);});//判断是否可以是what元素if(El . tagname = = ' img '){ El . src = source;} else {//判断source是否是类名。如果是,则将其添加到If类中(/[a-za-z0-9 _-]+$/。test(source)){ El . class list . add(source);} else { let styles = El . get attribute(' style ')| | ' ';styles+= `;背景图像:URL($ { source });`;el.setAttribute('style ',样式);El . style . background image = source;//= ` background-image:URL($ { source });`;} } El . remove attribute(ATTR _图像_网址);}}具体插件代码可以查看https://git.huawei.com/cnpm/lazyload。 同时在官网页脚采用其他加载方式,也达到了懒人加载的效果。页脚图片在css中引用。如果你想延迟加载页脚图片,你需要延迟加载页脚css。但是延迟加载css的后果是页面加载的瞬间页脚会显示混乱,所以我们可以在加载css样式之前隐藏页脚。加载css后,页脚dom中的display:块将自动显示页脚。 (= =因为页脚的seo特性没有懒加载==)2.1.3楼层内容的懒加载是基于xtpl自身的懒加载能力,配合pep定制页面模板的逻辑,我们可以实现html的懒加载。 第一次渲染页面时,只有各楼层的总框架、标题等关键信息可用。如果有必要,可以使用默认图片作为占位符,或者设置最小高度以防止锚点定位失败。 当页面滚动到楼层的位置时,js代码将执行它。在初始化函数中,加载渲染了楼层的html,实现了楼层图片和html的懒加载,减少了首屏时间。 具体代码如下: 2.2.资源整合。统一维护页眉页脚资源的基础模板的优化涉及到资源的合并、压缩和异步加载,dom的延迟加载和图片的懒加载。 首先我们给出一个官网基础模板引用的部分js资源的表格:这部分js的问题分散在pep的各个资产库的路径维护中,有的压缩了,有的没有压缩,js的加载基本是顺序进行的,所以我们在这部分整合了js和css资源,操作是迁移、合并、压缩。 建立公共资源仓库,统一维护和管理表头、表尾和公共资源代码。 2.2.2.将基本函数js用相同的加载方式组合起来,压缩common . js import’。/common/js/agrid ';“导入”。/common/js/jquery . base64 ';“导入”。/common/js/lang-tips ';“导入”。/common/js/setLocaleCookie ';“导入”。/common/js/pep dialog ';如上面的代码所示,将官网使用的分散的基础函数js合并成一个common.js,由福喜管道发布后会被cui套件自动压缩。这样做的效果当然是减少官网页面请求的资源数量和资源大小。 2.2.3.观察资源的异步加载。从2.2.1中的表格可以发现,官网中的大部分js都是放在头或者体之后依次加载的。这些资源的加载时间必须在DOMOnLoad之前,这样会阻塞页面的渲染,导致页面首屏加载缓慢。我们需要做的是整理前面的头尾资源,找出onload之后可以加载哪些资源。也就是我们可以把页面加载时不需要执行的js和css移到页面渲染后加载。没有这部分js逻辑的阻挡,渲染页面首屏的时间会大大减少。 通过cui套件中的feloader插件,我们可以方便的控制js和css的加载时间:feloader . onload(function(){ feloader . use([' @ cloud/link-to/index ',' @cloud/common-resource/uba ',' @cloud/common-resource/footer ',' @cloud/common-resource/header ',' @ cloud/common-resource/prompt . CSS ',' @ cloud/common-resource/footer . CSS ',])});从下图可以清楚的看到js的加载已经转移到onload: 2.2.4图片压缩除了设计给出的对图片的压缩要求,我们还通过对一些不经常升级的小图标图片进行base64编码来减少页面上的图片请求数量。 2.3预解析和预加载除了延迟加载,基础模板还进行dns预解析、资源预加载等措施,提前解析dns、加载页面资源。 2.3.1 dns预解析在客户访问过官网页面后,DNS预解析可以使客户在访问双十一活动页面前提前进行DNS解析,从而减少双十一活动页面的DNS解析时间,提高页面访问性能。其实写法也很简单:< link rel = " DNS-prefetch " href = "//RES . HC-cdn . com " & gt;& ltlink rel = " DNS-prefetch " href = "//RES-static 1 . Huawei cloud . com " & gt;& ltlink rel = " DNS-prefetch " href = "//RES-static 2 . Huawei cloud . com " & gt;& ltlink rel = " DNS-prefetch " href = "//RES-static 3 . Huawei cloud . com " & gt;2.3.2预加载活动页面的js也采用预加载的方法来提高页面加载性能。为什么预载可以达到这种效果?我们需要看到以下摘录:Preloader简介如果HTML解析器在创建DOM时遇到同步脚本,解析器会停止创建DOM,转而执行脚本。 所以,如果资源的获取只发生在解析器创建DOM的时候,同步脚本的介入会让网络空置,尤其是对于外部脚本资源。当然,页面中的脚本有时会造成延迟。 预加载器的出现优化了这一过程。Preloader通过分析浏览器对HTML文档的早期解析结果,找到可能包含资源的标签(这个阶段称为标记化),并收集这些资源的URL。 标记化阶段的输出将被发送到真正的HTML解析器,收集到的资源URL将和资源类型一起被发送到提取器,提取器将根据这些资源对页面加载速度的影响依次加载页面。 基于以上原理,我们在官网预加载相对重要的js资源,让浏览器尽快加载页面需要的重要资源。 & ltlink rel = " preload " href = "//RES . HC-cdn . com/cnpm-Fe loader/1 . 0 . 6/Fe loader . js " as = " script "/& gt;& ltlink rel = " preload " href = "//poly fill . alicdn . com/poly fill . min . js?features=default,es6 " as = " script "/& gt;& ltlink rel = " preload " href = " https://RES-static 3 . Huawei cloud . com/content/dam/cloud bu-site/archive/commons/3rd lib/jquery/jquery-1 . 12 . 4 . min . js " as = " script "/& gt;& ltlink rel = " preload " href = "//RES . HC-cdn . com/cnpm-WPK-reporter/1 . 0 . 6/WPK-performance . js " as = " script "/& gt;& ltlink rel = " preload " href = "//RES . HC-cdn . com/c page-pep-2019 nov-promotion/1 . 1 . 15/components/activity-banner/images/banner _ MB . jpg " as = " image " media = "(max-width:767 px)" & gt;优化效果3。总结前端性能优化的方法和手段不局限于文章语句。官网前端团队会在前端性能优化的道路上多学习,多探索,做到华为云官网页面加载性能的极致!点击关注,第一时间了解华为云鲜科技~


  • 全部评论(0)
资讯详情页最新发布上方横幅
最新发布的资讯信息
【域名/主机/服务器|】qq邮箱提醒在哪里打开(2024-06-04 18:58)
【技术支持|常见问题】1556原创ng8文章搜索页面不齐(2024-05-01 14:43)
【技术支持|常见问题】1502企业站群-多域名跳转-多模板切换(2024-04-09 12:19)
【技术支持|常见问题】1126完美滑屏版视频只能显示10个(2024-03-29 13:37)
【技术支持|常见问题】响应式自适应代码(2024-03-24 14:23)
【技术支持|常见问题】1126完美滑屏版百度未授权使用地图api怎么办(2024-03-15 07:21)
【技术支持|常见问题】如何集成阿里通信短信接口(2024-02-19 21:48)
【技术支持|常见问题】算命网微信支付宝产品名称年份在哪修改?风水姻缘合婚配对_公司起名占卜八字算命算财运查吉凶源码(2024-01-07 12:27)
【域名/主机/服务器|】帝国CMS安装(2023-08-20 11:31)
【技术支持|常见问题】通过HTTPs测试Mozilla DNS {免费源码}(2022-11-04 10:37)

联系我们
Q Q:375457086
Q Q:526665408
电话:0755-84666665
微信:15999668636
联系客服
企业客服1 企业客服2 联系客服
86-755-84666665
手机版
手机版
扫一扫进手机版
返回顶部