zoukankan      html  css  js  c++  java
  • 通过浏览器渲染过程来进行前端优化

    介绍
     
      做web开发,我个人觉得必须要弄清楚浏览器的渲染过程,否则我们很难进行前端优化。
      我今天就简单说一下页面加载和前端优化。
     
    页面加载
     
    我按照最简单的方式进行描述,实际上更复杂,不管是在浏览器端还是服务端,比如dns解析,代理服务器,负载均衡器等等。

     
    1、用户访问网页,发送一个http请求到网络服务器。
    2、网络服务器(应用服务器)解析请求,发送请求给数据库服务器。
    3、数据服务器返回数据给网络服务器,网络服务器解析数据,并生成html文件内容放入http response中,返回给浏览器。
    4、浏览器解析http response。
    5、浏览器创建DOM树。
    6、浏览器下载css,并应用在DOM树上,进行渲染。
    7、浏览器下载js,并解析执行js。
     

     
     
    缺陷
     
    以上整个流程中,如果其中任何一个流程出现问题,都不能顺利的渲染页面。
     
    服务端:
      网络服务器:无法获取到资源文件(404),或者由于并发的原因暂时无法处理你的请求(最常见的500错误),你的浏览器会长时间处于空白状态,直到服务器返回状态,或者进行超时处理。
      数据层:如果服务器停止,或忙于处理大数据等等,长时间无法返回数据给网络服务器,那么网络服务器一直处于等待状态中,如果请求量达到最大值,那么后面的请求都被堵塞,从而无法及时返回内容给浏览器。
     
    客户端:
      JavaScript:如果你的js写在body中的div里,而且这个js执行非常复杂的逻辑,那么整个页面处于等待状态中。
      不论js代码是内联还是包含在一个不相干的外部文件中,页面下载和解析过程肯定会停下,等待脚本执行完成这些处理,然后才能继续进行。——大多数浏览器使用单进程处理JavaScript的多个任务,同一时间只能有一个任务执行。
      CSS:可以同时下载多个CSS文件。
          如果我们把CSS样式放在页面底部,虽然使页面内容能更快的加载(因为将加载css 文件的时间放在最后,从而使页面内容先显示出来),但这样的内容是没有样式的,在CSS文件加载进来后,浏览器再对DOM使用样式,会出现我们常说的“无样式之闪烁”。
          更讨厌的是,上下都放置CSS样式,浏览器会首先按照上面的进行渲染,等到下面的样式上来,再按照下面的样式进行回流和重绘,用户感觉很差。
     
    注意两个词“repaint"和"reflow"。
      repaint(重绘)是在一个元素的外观被改变,但没有改变布局的情况下发生。——如果只是改变某个元素的背景色、文字颜色、边框颜色等等不影响它周围或内部布局的属性,将只会引起浏览器repaint。
      reflow(回流):浏览器发现某个部分发生了点变化影响了布局,需要倒回去重新渲染,这个回退的过程就叫回流。
    总结:以上两种严重影响用户体验,会无意识的流失用户。
     

     
    解决方案
     
     服务端:方式比较多,可以从架构上说(这个内容太多了,什么负载均衡了,什么缓存了,什么主从了),但是今天主要讨论语言层面。
        我们可以使用逐步返回内容的方式,输送数据给浏览器,如我们可以使用php的flush,把整个head部分,半个body加一部分div返回给浏览器,进行渲染,然后把其他部分逐步输送到浏览器。
        我们可以在服务端使用多线程或多进程的方式并发去进行数据处理。如php常见的
    复制代码
    do {
      $mrc = curl_multi_exec($mh, $active);
    }while($mrc==CURLM_CALL_MULTI_PERFORM);
    while ($active && $mrc == CURLM_OK){
      if (curl_multi_select($mh) != -1){
        do {
          $mrc = curl_multi_exec($mh,$active);
        }while($mrc==CURLM_CALL_MULTI_PERFORM);
      }
    }
    复制代码

    或者

    复制代码
    <?php
    while (count($sockets)) {
        $read = $write = $sockets;
        $n = stream_select($read,$write, $e, $timeout);
        if ($n > 0) {
            foreach ($read as $r) {
                $id = array_search($r, $sockets);
                $data = fread($r, 8192);
                if (strlen($data) == 0) {
                    fclose($r);
                    unset ($sockets[$id]);
                }else {
                    $retdata[$id] .= $data;
                }   
            }   
            $retdata[$id] = preg_replace('/^HTTP(.*?)
    
    /is',<em>, $retdata[$id]);</em>
                foreach ($write as $w) {
                    if (!is_resource($w))continue;
                    $id = array_search($w, $sockets);
                    fwrite($w, "GET /" . $url[$id] . "HTTP/1.0
    Host: " . $hosts[$id] ."
    
    ");
                    $status[$id] = 1;
                }   
        }else {
            break;
        }   
    }
    复制代码

    JavaScript:

      1、把脚本进行压缩(移除不必要的字符,注释以及空行)。

      2、对部分js文件进行合并,以减少http的请求个数,以减少服务器端的压力——但是要量力而行,因为如果你的js文件很大,下载很慢的话,很多功能都不能正常进行,我们可以按照业务进行合并。

      3、使用外部js文件。因为现在很多浏览器都有缓存,明显会减少http请求数。

      4、将脚本放在页面底部。先让用户看到内容,然后再加载js,这样用户会感觉页面加载速度很快。

    CSS:

      1、合并多个css文件,以减少http的请求个数,以减少服务器端的压力。

      2、使用外部css文件。主要原因是浏览器缓存,以减少http请求。

      3、放在页面顶部(head标签处),防止出现“无样式内容的闪烁”。

    总结
     

    以上是我通过浏览器的加载过程,来进行的前端优化,大家有什么更好的方式,不妨告知一、二。

  • 相关阅读:
    在C#代码中应用Log4Net(二)典型的使用方式
    在C#代码中应用Log4Net(一)简单使用Log4Net
    Windows Azure Active Directory (2) Windows Azure AD基础
    Windows Azure Virtual Network (6) 设置Azure Virtual Machine固定公网IP (Virtual IP Address, VIP) (1)
    Windows Azure Active Directory (1) 前言
    Azure China (6) SAP 应用在华登陆 Windows Azure 公有云
    Microsoft Azure News(3) Azure新的基本实例上线 (Basic Virtual Machine)
    Microsoft Azure News(2) 在Microsoft Azure上运行SAP应用程序
    Microsoft Azure News(1) 新的数据中心Japan East, Japan West and Brazil South
    Windows Azure HandBook (2) Azure China提供的服务
  • 原文地址:https://www.cnblogs.com/jymz/p/4398306.html
Copyright © 2011-2022 走看看