渲染机制
浏览器
1. 渲染机制
- 什么是 DOCTYPE 及作用
DTD 告诉浏览器文件是什么文档类型,浏览器根据它来判断用什么引擎来解析渲染文件。
DOCTYPE 用来声明文档类型和 DTD 规范。
- 浏览器是怎么渲染过程
HTML 5: <!DOCTYPE html>
HTML 4.01 Strict: 严格模式 不包含展示性和弃用的元素
HTML 4.01 Transitional:宽松模式
- 重排 Reflow
定义:DOM 结构中的各个元素都有自己的盒子模型,这些都是需要浏览器根据各种样式来计算并根据计算结果将元素放到它该出现的位置。
- 触发 Reflow:
当你增加、删除、修改 DOM 结点时,会导致 Reflow 或 Repaint
移动 DOM 位置
当你修改 CSS 样式时
当你 Resize 窗口时,或是滚动的时候
当你修改网页的默认字体时
- 重绘 Repaint
定义:页面要呈现的内容全部画在屏幕上。
- 触发 Rrpaint:
DOM 改动
CSS 改动
例:当添加 DOM 时,最好一次添加,避免多次。
- 布局 Layout
总结:
- 当用户输入一个 URL,浏览器就会发送一个请求,请求URL对应的资源
- HTML解析器会将这个文件解析,构建成一棵DOM树
- 构建 DOM 树时,遇到 JS 和CSS元素,HTML 解析器就将控制权转让给JS或者CSS解析器
- JS或者CSS解析器解析完这个元素时候,HTML又继续解析下个元素,直到整棵DOM树构建完成
- DOM 树构建完之后,浏览器把 DOM 树中的一些不可视元素去掉,然后与 CSSOM 合成一棵 render 树
- 接着浏览器根据这棵 render 树,计算出各个节点(元素)在屏幕的位置。这个过程叫做 layout,输出的是一棵 layout 树
- 最后浏览器根据这棵 layout 树,将页面渲染到屏幕上去
2. js 运行机制
- js 单线程:一个时间之内 js 只能做一件事
- 任务队列:同步任务和异步任务
-
Event Loop:浏览器的引擎遇到了 setTimeout,识别是异步任务,浏览器把这个 time
模块拿走,时间到了再放到异步队列中去。-
异步任务:
- setTimeout 和 setInterval
- DOM 事件
- ES6 的 Promise
-
3. 页面性能
-
提升页面性能的方法:
- 资源压缩合并,减少 HTTP 请求
-
非核心代码异步加载-》异步加载的方式-》异步加载的区别
异步加载的方式:
- 动态脚本加载
- defer
- async
异步加载的区别:
- defer 是在HTML解析完后才会执行,如果是多个,按照加载的顺序依次执行
- async 是在加载完之后立即执行,如果是多个,执行顺序和加载顺序无关
-
利用浏览器缓存-》缓存的分类-》缓存的原理
与缓存相关的HTTP头
- 强缓存
// 表示绝对时间,服务器下发的
Expires Expires:Thu,21 Jan 2017 23:39:02 GMT
// 比较的是本地的时间,会有偏差,3600s内无需请求
Cache-Control Cache-Control:max-age=3600
// 两者时间如果都下发了,规定选取后者。- 协商缓存
与服务器协商
// 服务器下发的时间 如果过期
Last-Modified If-Modified-Since Last-Modified:Web,26 Jan 2017 00:35:11 GMT
//Hash值 判断还可不可以使用-->
Etag If-None-Match - 利用 CDN:网络加速
- 预解析 DNS
如果页面是 HTTPS 协议开头的,强制打开 DNS 预解析
<meta http-equiv="x-dns-prefetch-control" content="on">
<!--预解析 DNS,尤其是在有多个域名时-->
<link rel="dns-prefetch" href="//host_name_to_prefetch.com">
动态脚本加载:
<scrīpt>
var oHead = document.getElementsByTagName(‘HEAD‘).item(0);
var oscrīpt= document.createElement("scrīpt");
oscrīpt.type = "text/javascrīpt";
oscrīpt.src="test.js";
oHead.appendChild( oscrīpt);
</scrīpt>
defer 与 async 用法:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>性能优化</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- <script src="./defer1.js" charset="utf-8" defer></script>
<script src="./defer2.js" charset="utf-8" defer></script> -->
<script src="./async1.js" charset="utf-8" async></script>
<script src="./async2.js" charset="utf-8" async></script>
<!-- 文件小先执行 -->
<script type="text/javascript">
document.write(‘<span>write</span>‘);
</script>
<script type="text/javascript">
for (var i = 0; i < 200000; i++) {
if (i % 20000 === 0) {
console.log(i);
}
}
</script>
</head>
<body>
</body>
</html>
4. 错误监控
-
前端错误的分类
-
及时运行错误:代码错误
- 1)try...catch
- 2) window.onerror
-
资源加载错误
- 1) object.onerror
- 2) performance.getEntries() 返回的是数组 performance.getEntries().forEach(item=>{console.log(item.name)})
- 3) Error 事件捕获
-
延伸:跨域的 js 运行错误可以捕获吗,错误提示什么,应该怎么处理?
- 1) 在 script 标签增加 crossorigin 属性
- 2) 设置 js 资源响应头加 Access-Control-Allow-Origin:
-
-
上报错误的基本原理
- 采用 Ajax 通信的方式上报
- 利用 Image 对象上报