十二:页面渲染机制及可做的性能优化

一个页面从服务器访问回来后,浏览器拿到页面源代码,之后做的一些事情(1-5是交给GUI渲染线程完成的)
    1. 生成 DOM TREE =>对HTML的处理
      - 基于HTTP获取的是流文件(进制编码)
      - 把进制编码编译为具体的字符
      - 词法解析
      - 生层具体的节点(元素节点/文本节点...)
      - 按照相互的嵌套关系生成一个DOM树(节点树)
    1. 生成 CSSOM TREE =>对CSS的处理
    1. 生成 RENDER TREE (渲染树)
    1. 布局/回流/重排 Layout
      • 按照渲染树计算出每一个元素在视口中的位置和大小
    1. 分层
      • 按照计算出来的样式进行分层
      • 单独计算每一层的绘制列表(具体怎么绘制)
  • 6.绘制/重绘 Painting
    • 把生成的绘制列表提交给“合成线程”
    • “合成线程”进行我们最后的绘制,呈现在浏览器的页面上
真正的同时做多件事情必须依赖多线程(浏览器是多线程的)
  • JS本身是单线程的 (因为浏览器本身只分配一个线程 “GUI渲染线程” 运行JS代码),从本质来讲是不能同时做多件事情的,但有同步跟异步
    • 同步:一件事情完成,再去做下一件事情
    • 异步:上一件事情没有完成(做一些特殊处理[async await等]),下一件事情继续执行 (但不是JS可以同时处理两个事情)
  • 浏览器生层DOM TREE/CSSOM TREE...的过程也是单线程的“GUI渲染线程”(配合浏览器的多线程去完成一些事情,例如:资源请求就是利用的就是浏览器的HTTP网络线程去做的)
浏览器具体的解析过程 “GUI渲染线程”:
  • 自上而下解析完所有的HTML标签/各种节点后,DOM TREE就生成了
  • 但是过程中还会遇到一些比较特殊的
    • link href='xxx.css' 外链式- >浏览器会分配一个新的HTTP网络线程去加载资源文件,不会阻碍DOM树的渲染
    • <style> ... </style> 内嵌式- >不用去请求新的资源文件了,但是此时样式还没有处理,浏览器会做一个记录,它会等待所有的CSS资源加载回来之后,按照先后顺序依次渲染CSS,从而生成CSSOM树
      -** @import 'xxx.css'** 导入式 - >也是分配网络HTTP线程去加载资源文件,但是此时GUI渲染线程会被阻塞掉[阻碍DOM树渲染](只有等资源加载回来,才会继续渲染DOM)
    • 遇到script 内嵌js代码的 - >立即执行JS(阻碍DOM TREE的渲染)
    • 遇到script 外链js代码的(src)- > 阻碍DOM TREE的渲染,同时分配一个HTTP线程去加载资源文件,加载回来后立即执行JS,如果JS中没有采用异步,直接获取DOM元素,而DOM元素此时还没有渲染,JS是获取不到的
    • 遇到img - >某些老旧版本浏览器会阻碍DOM渲染,新版浏览器虽然不会阻碍DOM渲染,但是图片资源的请求会占用HTTP线程(浏览器同时只能开6~7个HTTP线程,这样图片/音视频资源加载本来就会慢一些,会影响其他资源link/script等的加载)
可做的性能优化
  • link放到HEAD中(尽可能提前去加载资源文件,这样等DOM树渲染完,资源可能也加载回来了); 当代浏览器的机制越发完善,Webkit浏览器预测解析:chrome的预加载扫描器html-preload-scanner通过扫描节点中的 “src” , “link”等属性,找到外部连接资源后进行预加载,避免了资源加载的等待时间,同样实现了提前加载以及加载和执行分离
  • 把script放到页面的底部(先渲染DOM TREE,再执行JS,也可以获取到DOM元素了),也可以基于事件DOMContentLoaded/load等到结构加载完再去获取DOM元素
  • 当代前端开发,开始只把首屏的结构/内容写出来,渲染只是首屏的,当首屏加载完,页面滚动的时候,再基于JS创建其他屏幕的结构和内容 => 骨架屏/SSR =>客户端骨架屏,开始首屏结构都没有,只有一个loading或者占位图而已...
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容