JS进阶(五)同步异步编程及浏览器的底层渲染机制

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 浏览器渲染机制浏览器底层渲染机制一个页面从服务器访问,拿到页面源代码之后做的事情是什么?生成Dom树(DOM Tree) => 对HTML文件的处理基于HTML获取的是流文件 (进制编码)把进制编码编译为具体的字符按照令牌TOKEN进行解析 (分词/断词)生成具体的节点 (元素标签/文本节点....)按照相互的依赖关系生成一个DOM树 (节点树)

浏览器渲染机制

浏览器底层渲染机制

一个页面从服务器访问,拿到页面源代码之后做的事情是什么?

  1. 生成Dom树(DOM Tree) =>  对HTML文件的处理
  • 基于HTML获取的是流文件 (进制编码)
  • 把进制编码编译为具体的字符
  • 按照令牌TOKEN进行解析 (分词/断词)
  • 生成具体的节点 (元素标签/文本节点....)
  • 按照相互的依赖关系生成一个DOM树 (节点树)

屏幕截图 2023-07-05 233218.png

生成CSSOM Tree => 对CSS文件进行处理

屏幕截图 2023-07-05 233239.png

  1. 生成渲染树(Render Tree)
  • DOM TREE + CSSOM TREE
  • Meat、Head、Link和display:none;等这些元素是不会出现在渲染树的
  1. 布局/回流/重排 Layout
  • 按照渲染树计算出每一个元素在视口中的位置和大小
  1. 分层
  • 按照计算出来的层级进行分层
  • 定位
  • 设置透明度 rgba
  • 设置滤镜
  • 文本超过盒子大小,裁切
  • 单独计算每一层的绘制列表(具体绘制)
  1. 绘制/重绘 Painting
  • 把生成的绘制列表提交给"合成线程"
  • "合成线程"进行我们最后的绘制,呈现在浏览器的页面上
  1. 光栅化,合成

分层之前的操作都是基于GUI渲染线程来完成

进程与线程

  • 进程: 一个程序(浏览器新建一个也卡就是一个进程) 【工厂】
  • 线程: 一个进程中可能包含多个线程,每个线程可以同时做一件事情,真正的同时做一件事情,必须依赖多线程【工人】

JS中的同步异步

浏览器就是多线程 , 但是JS本身是单线程。因为浏览器本身只分配了一个线程“GUI渲染线程”运行JS代码,JS本身从本质上来讲,是不能同时做多件事的。

  • 同步:上一件事情完成,再去做下一件事情
  • 异步: 上一件事情没有完成(我们把它做一些特殊处理),下一件事情继续执行 【绝对不是同时做两件事】

浏览器生成DOM TREE/CSSOM TREE ... 的过程也是单线程(配合浏览器的多线程去完成一些事情,例如资源请求就是利用浏览器的网络线程去做的)

浏览器具体的解析过程 "GUI渲染线程"

  1. 自上而下解析完所有的HTML标签/DOM节点后,DOM TREE就生成了
  2. 解析过程中会遇到比较特殊的
  • 外链式  link href = “”
    => 浏览器会分配一个新的HTTP网络进程去加载资源文件
    => 不会阻碍DOM树的渲染
  • 内嵌式  < style > 。。。</ style >
    => 不用去请求新的资源文件了,但是此时样式没有处理,浏览器会做一个记录 ,它会等所有的CSS资源加载回来之后,按照先后顺序依次渲染CSS,从而生成CSSOM树
  • @import 'xxx.css' 导入式
    =>  虽然也是分配HTTP网络线程去加载文件,但是此时GUI渲染线程会被阻塞掉【阻碍DOM树的渲染】(只有等待资源加载回来,才会继续渲染DOM)
  1. 遇到script标签
  • 遇到内嵌js代码,会立即执行JS (阻碍dom树渲染)
  • 遇到script 外链js代码的
  • 阻碍DOM TREE的渲染,同时分配一个HTTP线程去加载资源文件,加载回来后立即执行JS ( JS 中没有采用异步,直接获取DOM元素,而DOM元素此时没有渲染,JS是获取不到的)
  • 把script放到页面底部 (先渲染DOM TREE,再执行JS,也可以获取到DOM元素了)

想要script放在前面还可以获取dom,有3种解决办法
> setTimeout(()=>{ ... }, 0) 
> window.addEventListener('DOMContentLoaded',function(){ ...   })  触发条件:DOM TREE加载完即可
> window.onload = function(){ ... }  => 触发条件是:所以dom资源都加载完成(包含DOM TREE/CSS/图片),再执行

async / defer 给script设置的属性

> async 是开辟HTTP线程加载资源文件,此时DOM TREE继续,但是资源文件一旦加载回来,停止DOM TREE,先执行JS代码(不考虑JS引用顺序,谁先加载回来谁先执行)
> defer 也是开辟HTTP线程加载资源文件,即使资源文件加载回来,也会等待DOM树渲染完成,defer效率更好,但是不兼容低版本浏览器

屏幕截图 2023-07-05 233319.png

  • 遇到img,正常情况下,老版本浏览器会阻塞dom渲染,新版浏览器虽然不会阻碍DOM渲染,但是会占用图片资源请求,会占用HTTP线程(浏览器只能同时开6-7个HTTP线程,这样的话,图片或者音视频资源加载本来就会慢一些,会影响关键(其他link/script)资源的加载), 图片资源的渲染也是比一般资源耗时间的,也会拖累渲染速度

以上性能优化的点:

1、不用@import

2、link标签放到HEAD中,尽可能提前加载资源文件,这样等DOM树渲染完,资源就加载回来了: 当代浏览器的机制越发完善,chrome的预加载扫描器通过"src","link"等属性,找到外部链接资源后预加载,避免了资源加载等待,同事实现了提前加载和执行分离

3、如果CSS代码比较少,尽可能使用内嵌式,可以减少HTTP请求,但是如果样式比较多,采用内嵌式,第一次加载HTML都会浪费很长时间,这样还不如基于link分开加载; 移动端开发都是内嵌优先(也要考虑CSS代码量)

4、尽可能减少DOM或者减少DOM的层级嵌套,以及标签语义化(当代前端开发,只把首屏结构/内容写出来,渲染知识首屏的,当首屏加载完,页面滚动的时候,在给予JS创建其他屏幕的结构和内容 => 骨架屏/SSR => 客户端股价屏,开始首屏结构都没有,只有一个loading或者展位图)

5、图片合并(sripte) / BASE64  / iconfont / svg / http2 升级协议

BASE64 不发松请求(好用但是要慎用,加大了文件体积)  

6、图片懒加载 / 预加载

网络层优化

CRP浏览器关键节点优化 (critical rendering path)

webpack层优化

安全优化

代码层优化 闭包

相关文章
|
6天前
|
JavaScript 安全 前端开发
乾坤js隔离机制
乾坤js隔离机制
|
15天前
|
前端开发 JavaScript 数据库连接
掌握 JavaScript 异步编程:从回调到 Async/Await
在现代 JavaScript 开发中,异步编程是处理非阻塞操作的关键技术。本文从早期的回调函数讲起,逐步过渡到 Promise 和 ES2017 的 async/await 语法,展示了异步编程如何变得更加简洁和强大。通过实用的技巧和最佳实践,帮助开发者避免常见陷阱,提升代码效率和可靠性。
|
12天前
|
XML JSON 前端开发
JavaScript 异步编程
JavaScript 异步编程
20 3
JavaScript 异步编程
|
1天前
|
JavaScript 前端开发 开发者
探索Node.js中的异步编程模式
【9月更文挑战第33天】在JavaScript的后端领域,Node.js凭借其非阻塞I/O和事件驱动的特性,成为高性能应用的首选平台。本文将深入浅出地探讨Node.js中异步编程的核心概念、Promise对象、Async/Await语法以及它们如何优化后端开发的效率和性能。
13 7
|
4天前
|
JavaScript 调度 数据库
深入浅出:Node.js中的异步编程与事件循环
【9月更文挑战第30天】在Node.js的世界里,理解异步编程和事件循环是掌握其核心的关键。本文将通过浅显易懂的语言和实际代码示例,带你探索Node.js如何处理并发请求,以及它是如何在幕后巧妙地调度任务的。我们将一起了解事件循环的各个阶段,并学会如何编写高效的异步代码,让你的应用程序运行得更加流畅。
25 10
|
11天前
|
JavaScript 前端开发 数据库
探索Node.js中的异步编程模型
【9月更文挑战第23天】在Node.js的世界里,异步编程是核心的魔法,它让这个平台能够处理高并发请求。本文将带你深入理解Node.js的异步编程模型,通过代码示例和直观的解释,我们将一起揭开异步编程的面纱。
30 16
|
3天前
|
JavaScript 前端开发 开发者
深入理解Node.js中的事件循环和异步编程
【9月更文挑战第31天】本文旨在揭示Node.js背后的强大动力——事件循环机制,并探讨其如何支撑起整个异步编程模型。我们将深入浅出地分析事件循环的工作原理,以及它如何影响应用程序的性能和稳定性。通过直观的例子,我们会展示如何在实际应用中利用事件循环来构建高性能、响应迅速的应用。此外,我们还会讨论如何避免常见的陷阱,确保代码既优雅又高效。无论你是Node.js的新手还是经验丰富的开发者,本篇文章都将为你提供宝贵的洞察和实用技巧。
17 6
|
7天前
|
前端开发 JavaScript
JavaScript中的Promise:简化异步编程
JavaScript中的Promise:简化异步编程
|
13天前
|
前端开发 JavaScript 开发者
探索JavaScript的异步编程之旅
【9月更文挑战第21天】在数字世界中,时间就是一切。本文将带你深入理解JavaScript中的异步编程模式,通过实际代码示例,展示如何高效处理任务,优化用户体验。从回调函数到Promises,再到async/await,我们将一步步解锁JavaScript异步编程的秘密。
|
13天前
|
Web App开发 JavaScript 前端开发
探索Node.js中的异步编程模型
【9月更文挑战第21天】在现代Web开发中,Node.js以其非阻塞I/O和事件驱动的特性成为热门选择。本文将深入探讨Node.js的异步编程模型,揭示其背后的原理,并通过示例代码展示如何高效利用异步特性来处理并发任务。
下一篇
无影云桌面