zoukankan      html  css  js  c++  java
  • 小白眼中的网页渲染

    从用户输入URL到浏览器呈现页面经过了哪些过程?

    • 1、用户输入URL,浏览器获取URL
    • 2、浏览器进行DNS解析(如果输入的是IP地址,此步骤省略)
      • 浏览器根据地址去本身缓存中查找dns解析记录,如果有,则直接返回IP地址,否则浏览器会查找操作系统中(hosts文件)是否有该域名的dns解析记录,如果有则返回。
      • 如果浏览器缓存和操作系统hosts中均无该域名的dns解析记录,或者已经过期,此时就会向域名服务器发起请求来解析这个域名。
    • 3、根据解析出的IP地址+端口,浏览器(应用层)发起HTTP请求,请求中携带(请求头header(也可细分为请求行和请求头)、请求体body)
      • header包含:
      1. 请求的方法(get、post、put..)
      2. 协议(http、https、ftp、sftp…)
      3. 目标url(具体的请求路径以及文件名)
      4. 一些必要信息(缓存、cookie之类
      • body包含:
      1. 请求的内容
    • 4、请求到达传输层,tcp协议为传输报文提供可靠的字节流传输服务,它通过三次握手等手段来保证传输过程中的安全可靠。通过对大块数据的分割成一个个报文段的方式提供给大量数据的便携传输。
    • 5、到网络层, 网络层通过ARP寻址得到接收方的Mac地址,IP协议把在传输层被分割成一个个数据包传送接收方。
    • 6、数据到达数据链路层,请求阶段完成
    • 7、接收方在数据链路层收到数据包之后,层层传递到应用层,接收方应用程序就获得到请求报文。
    • 8、接收方收到发送方的HTTP请求之后,进行请求文件资源(如HTML页面)的寻找并响应报文
    • 9、发送方收到响应报文后,如果报文中的状态码表示请求成功,则接受返回的资源(如HTML文件),进行页面渲染。

    页面的渲染

    图片说明
    对图中英文的解释:

    • 1.HTML parser:HTML解析器,其本质是将HTML文本解释成DOM tree。
    • 2.CSS parser:CSS解析器,其本质是讲DOM中各元素对象加入样式信息
    • 3.JavaScript引擎:专门处理JavaScript脚本的虚拟机,其本质是解析JS代码并且把逻辑(HTML和CSS的操作)应用到布局中,从而按程序要的要求呈现相应的结果
    • 4.DOM tree:文档对象模型树,也就是浏览器通过HTMLparser解析HTML页面生成的HTML树状结构以及相应的接口。
    • 5.render tree:渲染树,也就是浏览器引擎通过DOM Tree和CSS Rule Tree构建出来的一个树状结构,和dom tree不一样的是,它只有要最终呈现出来的内容,像或者带有display:none的节点是不存在render tree中的。
    • 6.layout:也叫reflow 重排,渲染中的一种行为。当rendertree中任一节点的几何尺寸发生改变了,render tree都会重新布局。
    • 7.repaint:重绘,渲染中的一种行为。render tree中任一元素样式属性(几何尺寸没改变)发生改变了,render tree都会重新画,比如字体颜色、背景等变化。

    浏览器解析渲染页面主要包括以下过程:

    • 1.浏览器通过HTMLParser根据深度遍历的原则把HTML解析成DOM Tree。
    • 2.将CSS解析成CSS Rule Tree。
    • 3.根据DOM树和CSSOM树来构造render Tree。
    • 4.layout:根据得到的render tree来计算所有节点在屏幕的位置。
    • 5.paint:遍历render树,并调用硬件图形API来绘制每个节点。

    前端性能优化

    1.HTML解析

    HTML解析是浏览器的HTML解析器把HTML解析成dom tree,而在解析过程,浏览器根据HTML文件的结构从上到下解析html,HTML元素是以深度优先的方式解析,而script、link、style等标签会使解析过程产生阻塞,阻塞的情况有:

    -外部样式会阻塞内部脚本的执行。 
    -外部样式与外部脚本并行加载,但外部样式会阻塞外部脚本执行。 
    -如果外部脚本带有async属性,则外部脚本的加载与执行不受外部样式影响 
    -如果link标签是动态创建(js生成),不管有无async属性,都不会阻塞外部脚本的加载与执行。
    

    2. CSS解析

    CSS Parser作用就是将很多个CSS文件中的样式合并解析出具有树形结构Style Rules,在对样式解析的过程中,默认CSS选择器是从右往左进行解析的。至于为什么是从右到左,而不是从左到右、也不会是从左到左…

    3. 脚本执行

    当浏览器解析HTML时,当遇到script标签就会立即解析脚本,同时阻塞解析文档直到脚本执行完毕(你可能问为什么要这样设计,明显啊,脚本的执行是改变css和dom,会造成render tree不停的重绘和重排的),而当script是引入外部js文件时,会阻塞到js文件下载完成并且执行完成为止(除非加了defer或者async属性)。脚本在解析过程中将对dom或css的操作解析出来加入到DOM Tree和cssom中。

    所以进入正题,性能优化:

    性能优化

    1.对于css:

    优化选择器路径:健全的css选择器固然是能让开发看起来更清晰,然后对于css的解析来说却是个很大的性能问题,因此相比于 .a .b .c{} ,更倾向于大家写.c{}。
    压缩文件:尽可能的压缩你的css文件大小,减少资源下载的负担。
    选择器合并:把有共同的属性内容的一系列选择器组合到一起,能压缩空间和资源开销
    精准样式:尽可能减少不必要的属性设置,比如你只要设置{padding-left:10px}的值,那就避免{padding:0 0 0 10px}这样的写法
    雪碧图:在合理的地方把一些小的图标合并到一张图中,这样所有的图片只需要一次请求,然后通过定位的方式获取相应的图标,这样能避免一个图标一次请求的资源浪费。
    避免通配符:.a .b {} 像这样的选择器,根据从右到左的解析顺序在解析过程中遇到通配符()回去遍历整个dom的,这样性能问题就大大的了。
    少用Float:Float在渲染时计算量比较大,尽量减少使用。
    0值去单位:对于为0的值,尽量不要加单位,增加兼容性

    2.对于JavaScript:

    1)尽可能把script标签放到body之后,避免页面需要等待js执行完成之后dom才能继续执行,最大程度保证页面尽快的展示出来。
    2)尽可能合并script代码,
    3)css能干的事情,尽量不要用JavaScript来干。毕竟JavaScript的解析执行过于直接和粗暴,而css效率更高。
    4)尽可能压缩的js文件,减少资源下载的负担
    5)尽可能避免在js中逐条操作dom样式,尽可能预定义好css样式,然后通过改变样式名来修改dom样式,这样集中式的操作能减少reflow或repaint的次数。
    6)尽可能少的在js中创建dom,而是预先埋到HTML中用display:none来隐藏,在js中按需调用,减少js对dom的暴力操作。

    3.对于HTML:

    1)避免再HTML中直接写css代码。
    2)使用Viewport加速页面的渲染。
    3)使用语义化标签,减少css的代码,增加可读性和SEO。
    4)减少标签的使用,dom解析是一个大量遍历的过程,减少无必要的标签,能降低遍历的次数。
    5)避免src、href等的值为空。
    6)减少dns查询的次数。

    详细请见链接:https://juejin.im/post/5bbaa549e51d450e827b6b13

  • 相关阅读:
    [洛谷P2711]小行星
    [洛谷P2264]情书
    [洛谷P2626]斐波那契数列(升级版)
    [洛谷P3195][HNOI2008]玩具装箱TOY
    [洛谷P3254]圆桌问题
    [洛谷P1251]餐巾计划问题
    [洛谷P4015]运输问题
    [洛谷P2604][ZJOI2010]网络扩容
    [洛谷P4001][BJOI2006]狼抓兔子
    [洛谷P3153] [CQOI2009]跳舞
  • 原文地址:https://www.cnblogs.com/sunidol/p/11301836.html
Copyright © 2011-2022 走看看