浏览器/页面渲染过程

1.网络通信

用户输入网址,输入url后会开一个新的网络线程

 DNS域名解析,查询出相应的IP地址

 发起TCP三次握手,建立连接 

为什么不是两次握手:

 3次握手完成两个重要的功能。既要两方做好发送数据的准备工作(两方都知道彼此已准备好),也要同意两方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。

如今把三次握手改成仅须要两次握手。死锁是可能发生的。

作为样例。考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发送了确认应答分组。依照两次握手的协定,S觉得连接已经成功地建立了,能够開始发送数据分组。但是,C在S的应答分组在传输中被丢失的情况下,将不知道S是否已准备好。不知道S建立什么样的序列号。C甚至怀疑S是否收到自己的连接请求分组。在这样的情况下,C觉得连接还未建立成功,将忽略S发来的不论什么数据分组,仅仅等待连接确认应答分组。而S在发出的分组超时后,反复发送相同的分组。这样就形成了死锁。

 发送http请求

var xhr = null;
function getData() {
    createXHR();
    httpStateChange();
}
function createXHR() {
    // step1. 创建XMLHttpRequest对象,也就是创建一个异步调用对象; 
    if (window.XMLHttpRequest) {
        xhr = new XMLHttpRequest();
    } else if (window.ActiveXObject){
        xhr = new ActiveXObject();
    }
    if(xhr){
        // step2. 创建HTTP请求,并指定改HTTP请求的方法、URL以及验证信息;
        // 第一个参数是以什么方式;第二个是往哪儿发送请求,第三个可以不写,默认true,表示异步,false表示同步;
        xhr.open('get/post',url,true);
        // step3. 设置响应HTTP状态变化的函数; 
        xhr.onreadystatechange = httpStateChange;
        // step4. 发送HTTP请求;
        xhr.send(null);
    } else {
        alert('not support xhr')
    }
}
function httpStateChange() {
    if(xhr.readyState === 4) {
        if (xhr.status === 200 || xhr.status === 0) {
            //判断异步调用是否成功,如果成功开始局部更新数据
            // step5. 获取异步调用返回的数据;
            var node = document.getElementById("myDIv");//更新数据
            node.firstChild.nodeValue = xmlHttpRequest .responseText;
            //code...
        } else {
            alert("出错状态码:"+xhr.status+"出错信息:"+xhr.statusText);
        }
    }
}

服务器找到资源,进行http响应,返回该资源(即HTML)(xhr.readyState === 4 && xhr.status === 200) 

 2.页面渲染(以下三个过程,是一边加载,一边解析,一边渲染的,而非相互独立)

 解析HTML文件,得到DOM树和CSS样式树

DOM树和CSS树的计算是同时执行的,因此通常需要把CSS放到head里让其先进行解析

一般来说,style的link标签需要尽量放在head里面,因为在解析DOM树的时候是自上而下的,而css样式又是通过异步加载的,这样的话,解析DOM树下的body节点和加载css样式能尽可能的并行,加快Render树的生成的速度,当然,如果css是通过js动态添加进来的,会引起页面的重绘或重新布局。

当浏览器解析到script标签时,为防止JavaScript脚本可能会改变现有的dom结构,会终止HTML文档的解析,因此一般把script标签放到dom的最后部分,以防止HTML解析阻塞,页面加载缓慢。可以在首绘不需要js的情况下用async和defer实现异步加载。这样js就不会阻塞html的解析了

 将DOM树和CSS样式树"整合"成渲染树。

(attention:渲染树的生成并不是和dom节点一一对应的,如display:none的节点就不会进入渲染树,这样确实可以提供一些性能的优化,同时你需要知道visibility:hidden的节点是会进入渲染树的 ) 

通过已知的HTML标签和他对应的样式去计算布局 (已经得到了dom节点以及dom之间的相对关系,浏览器就可以通过流模型的layout算法对页面中的各个节点进行定位。 

将计算好的渲染树渲染到显示器上(并非简单渲染,涉及z-index等)

3.页面性能优化

 1.防止css的过多嵌套,合理的css选择器可以避免这个问题。减少*和标签选择,如不用ul#id(应该是#id);选择器的深度降到最低,最高不要超过三层;

2.减少http的请求次数,将资源文件如(图片)进行整合(如雪碧图),将其他文件通过打包工具打包(webpack)。(为什么要这样做呢?因为加载两张50K的图片的速度没有加载一张100K的图片快,这是由于加载一张图片不需要切换工作,省下了部分切换工作时所需要的时间)

3.减少dom操作,让经常需要改动的节点脱离文档流(尽可能限制重绘的影响范围)

4.使用json格式进行数据交换,json格式是JavaScript的原生格式,因此使用的过程中不需要借助额外的工具包

5.解决阻塞渲染,优先加载HTML再解析js(在标签中使用 async或defer特性 )

页面的渲染过程并不是完全独立的,所以你可以经常看到页面一点点出来的情况就是一边解析,一边加载,一边渲染的工作现象。

参考链接:

 https://blog.csdn.net/riddle1981/article/details/78681191

猜你喜欢

转载自blog.csdn.net/MingleHDU/article/details/84567832
今日推荐