渲染机制
什么是DOCTYPE? 及作用
HTML5
<!DOCTYPE HTML>
HTML4.01版本 有两个模式 严格模式 传统模式
严格模式(DTD包含所有HTML元素和属性. 但不包括弃用的元素(eg:font),如果使用,可能解析时会出错)
传统模式(DTD包含所有,包括弃用的)
浏览器渲染过程
html -> 经过html Parser -> DOM Tree
样式 -> 经过 css parser -> style rules
Dom Tree + Style rules -> 经过attachment生成 Render Tree
Render Tree 通过 layout 绘制成页面
重排 Reflow
定义: 浏览器在DOM各元素(盒子)的位置发生改变并且重新计算绘制的过程,叫reflow, 它影响它所有的children、ancestors及siblings.
触发reflow:
- 对Dom节点增删改的时候, 会触发reflow或者repaint
- 移动dom的时候(比如动画)
- 修改样式的时候
- 改变窗口大小的时候(pc) , 或滚动的时候
- 修改默认字体(影响大)
重绘 Repaint
在改变 DOM 元素的视觉效果时触发,即不涉及任何排版布局的问题时触发。
如果只是改变某个元素的背景色、文 字颜色、边框颜色等等不影响它周围或内部布局的属性,将只会引起浏览器 repaint(重绘)。repaint 的速度明显快于 reflow
触发: Dom改动,css改动
如何减少最小程度的repaint: 节点改动,修改的结果尽量集合在一起(取最后的结果), repaint一次
// (不要改动一点,就repaint)
// 类似节流
如何尽可能的避免触发reflow和repaint,提高性能?
尽可能的减少DOM元素相互影响
-
避免设置内联样式
-
尽量简写CSS样式
-
删除复杂动画,尽量给动画元素设置position:fixed/absolute,使动画元素从DOM流中独立出来,从而减少对其他元素的影响。同时,尽量牺牲平滑度去满足性能,因为动画精度太强,会造成更多次的repaint/reflow
-
避免使用table进行布局:
-
table的每个元素的大小以及内容的改动,都会导致整个table进行重新计算,造成大幅度的repaint或者reflow。改用div则可以进行针对性的repaint和避免不必要的reflow
-
避免在CSS中使用运算式:
-
学习CSS的时候就知道,这个应该避免,不应该加深到这一层再去了解,因为这个的后果确实非常严重,一旦存在动画性的repaint/reflow,那么每一帧动画都会进行计算,性能消耗不容小觑。
-
减少DOM的层级,减少DOM的数量,DOM数量越少越好
-
慎改class!!去改子元素少的DOM的class
-
尽量采取批量更新元素样式的方式,比如可以将需要修改的样式集合放在一个class里,将这个class附给元素
布局 Layout (浏览器的布局)
html -> CSS -> render -> layout -> paint
JS运行机制
如何理解js的单线程
一个时间内只干一件事
什么是任务队列
事件队列(消息的队列,所谓任务是WebAPIs返回的一个个通知), 执行栈为空后会到任务队列中去取任务,依次执行任务队列中对应的回调函数, 其中分同步任务, 异步任务, 同步总是在异步之前执行.
异步任务:
- DOM事件
- ajax.(promise)
- setTimeout
Event loop
浏览器的事件循环, 主线程运行栈中。只要栈中的代码(api,同步)执行完毕,主线程就会去读取"任务队列",依次执行那些事件所对应的回调函数。 执行栈空了, 再去读取, 再循环.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>js运行机制</title>
</head>
<body>
<script type="text/javascript">
// console.log(1);
// setTimeout(function () {
// console.log(2);
// }, 0);
// console.log(3);
// console.log(4);
//
// console.log('A');
// setTimeout(function () {
// console.log('B');
// }, 0);
// while (1) {
//
// }
//
for (var i = 0; i < 4; i++) {
setTimeout(function () {
console.log(i);
}, 1000);
}
</script>
</body>
</html>
页面性能
提升页面性能的方法有哪些?
- 资源压缩合并, 减少http请求
- 非核心代码异步加载 ----> 异步加载的方式 ----> 异步加载的区别
- 利用浏览器的缓存 ----> 缓存的分类 ----> 缓存的原理
- 使用CDN
- DNS预解析
DNS预解析
// <meta>信息告诉浏览器,当前页面要做DNS预解析;https浏览器是默认不开启的(a标签)
<meta http-equiv="x-dns-prefetch-control" content="on" />
// 使用<link>标签来强制对DNS预解析;
<!--如果不确定是http还是https连接的话建议如下写法 -->
<link rel="dns-prefetch" href="//renpengpeng.com" />
异步加载的方式
- 动态脚本加载(script)
- async
- defer
异步加载的区别
defer是在html解析完之后才加载, 多个的话, 是按顺序的.
async是在会在下载完成后立刻执行, 多个的话, 是乱序的, 那个先回来, 那个先执行.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>性能优化</title>
<!-- <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>
</head>
<body>
<div class="">
test
<script type="text/javascript">
console.log('write');
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>
</div>
</body>
</html>
浏览器的缓存
缓存的分类
- 强缓存 // 直接读取浏览器存储在磁盘缓存(本地) 在相对时间内
Expires:Wed, 10 Jul 2019 09:53:41 GMT
Cache-Control:max-age=86400
- 协商缓存 // 询问服务器先 内容是否有改变
<!-- 下发的时间 -->
Last-Modified:Tue, 16 Feb 2016 04:22:55 GMT
<!--- 再次请求的携带的 下发的时间 -->
If-Modified-Since:Tue, 16 Feb 2016 04:22:55 GMT
<!-- 判断内容是否变化 hash值 (判不同) -->
Etag:"Fqbu34Q4nhvJ91e8LRlTj4yNHK6d.gz"
错误监控
问法:
- 如何保证代码(产品)质量?
- 如何检测js错误
前端错误的分类 1. 运行错误(代码错误) 2. 资源加载错误
- 即时运行错误(代码错误)
- 资源加载错误 (图片,js,css)
错误的捕获方式
performance.getEntries() 跟 document.getElementByTagName(’’) 比对. 缺失的资源为加载失败.
跨域的js也可以捕获.
处理:
- 后端处理跨域. 响应头Access-Control-Allow-Origin: *
- script标签添加crossorigin属性
上报错误的基本原理
- ajax通信的方式上报
- 利用Image对象上报
<script type="text/javascript">
// 地址 可带参数
(new Image()).src = 'http://baidu.com/tesjk?r=tksjk';
</script>