当前位置: 首页 > news >正文

初二怎么做网站seo网站案例

初二怎么做网站,seo网站案例,广东梅州兴宁做网站公司,网站建设公司的重要性之前一直不愿意写一篇关于原理的#xff0c;因为说起来实在是太繁杂#xff0c;要写得细#xff0c;码字梳理#xff0c;计算下来起码都要差不多三周。以前一直躲避这个事情#xff0c;现在反正有时间#xff0c;为了不荒废自己#xff0c;那就从头捋一遍。也方便自己后…        之前一直不愿意写一篇关于原理的因为说起来实在是太繁杂要写得细码字梳理计算下来起码都要差不多三周。以前一直躲避这个事情现在反正有时间为了不荒废自己那就从头捋一遍。也方便自己后期回忆。 这篇文章总结就是带你了解用户输入一个地址按回车到页面出现都发生了什么。 一、网络层知识补充 开始之前先补充一下网络层协议的相关知识点如下图 这张图展示了网络层主要涉及到的传输协议前端需要注重的是HTTP和TCP和SSL协议当然要想了解IP传输协议也是可以的你们自己去了解每个字段代表什么计算IP地址什么的太多内容了细讲有点占篇幅。 1. HTTP协议的补充 提到HTTP协议HTTP协议的发展史就不得不提了毕竟涉及到HTTPS和HTTP的区别。那就走一波呗。 HTTP是怎么出现的呢它是为了实现传输HTML而专门设计的协议。在HTML没有出来前基本信息的录入都是人工读卡或者手动录入这些信息需要共享或者校对都比较麻烦。懒的人都很擅长找解决方案所以有两位帅哥就想能不能让这些数据在某个地方实现快速查找的同时又能共享数据这样既减轻工作量又保证了信息准确性。于是HTML就产生了产生了之后要传输怎么办呢没有传输的协议我就创造一个呗于是HTTP最初版本出现第一版的HTTP协议很简单没有版本号只支持传输文本只支持GET方法简称0.X版本吧它只支持返回指定路径里的数据。 1.1 HTTP1.0 随着发展第一版的协议已经没有办法满足需求所以HTTP1.0出现了。 HTTP1.0需要解决的问题及解决方案如下图 问题解决方案1.只支持HTML没法实现更复杂的操作如上传下载文件 引入content-type字段text/plain纯文本text/html纯HTML格式 application/octet-stream二进制数据流application/x-www-form-urlencoded 等等2.没有缓存的概念造成资源浪费引入Expires和Cache-Control字段进行缓存控制3.传输的是文本http0.x版本用的是ASCII码字集没有进行压缩文件头部增加content-encoding:gizp字段进行压缩传输4.没有错误处理机制引入标准错误状态码提示403404500等 虽然HTTP1.0比HTTP0.X版本更灵活但0.X版本遗留的部分问题并没有解决比如请求一次建立一次TCP链接HTTP1.0出现的缓存不够灵活等所以HTTP1.1应运而生。 1.2 HTTP1.1 HTTP1.1需要解决的问题及解决方案如下图 问题解决方案1.每一个请求都需要建立TCP连接然后再释放造成了极大的资源负担建立长链接一个TCP链接内运行多个请求和响应提高了资源的利用2.缓存上在短时间内1s内修改无法识别last-modified新增ETag和If-None-Match字段这儿一两句说不明白建议看相关文档于我而已就这点突出些3.请求头的method只有getposthead方法新增putoptionsdelete等字段更灵活更准确4.在不确定服务器是否会接收该资源就发送body占用带宽新增预检功能先只发header确认服务器是否有权限请求有再发送body节约带宽5.每台服务器绑定唯一的ip地址造成资源浪费增加host字段引入虚拟主机概念合理利用服务器资源6.涉及到用户隐私数据时有泄露信息的风险引入ssl证书后续多引入tls用于保护数据的安全和用户的认证 目前国内大部分都在用HTTP1.1版本那么怎么优化HTTP1.0存在的问题呢 1.2.1 HTTP1.1的优化 1.使用CDN加速静态资源放于CDN上让资源更靠近用户加快获取速度减少延迟 2.使用雪碧图哈哈这点不用说大家都知道还不是为了减少请求减少队头阻塞 3.使用缓存机制重复的资源自己从浏览器获取减少服务器的压力 4.启用Gzip压缩减少传输数据的大小减少网络传输的时间 5.域名分片将网站的资源分布在多个子域名下,实现更高的并发连接数毕竟浏览器对不同域名没有限制。 市面上目前常用的还是HTTP1.1版本但HTTP1.1是最好的吗当然不是毕竟HTTP2.0早就出来啦。它解决什么问题呢 1.3 HTTP2.0 HTTP2.0处理HTTP1.1的问题和解决方案 问题解决方案1.每个tcp长连接里面处理http请求有限引入多路复用概念。允许单个TCP连接并发处理多个请求并且不再依赖tcp连接实现多流并行2.客户端没有进行请求服务器不会主动推送资源给客户端支持服务器主动推送提前缓存可能需要的资源,从而减少延迟和提高性能减少ssr的时候白屏时间大大提升用户体验3.头部越来越重即使开启Gzip压缩可以压缩body头部字段过多的问题并没有办法解决使用Hpack算法压缩即静态字典动态字典Huffman编码压缩方法使得头部的体积也减小4.头部用的是纯文本传输占较大的传输空间并且有很多固定字段如cookie,user-agent等每次请求都会跟上造成资源浪费。每个请求都带完整的header,即使后面两个请求都带一部分相同的header造成了重复传输浪费了带宽用二进制分帧的形式将header和body分为两个流一个header frame一个data frame。5.队头阻塞按顺序返回数据没有优先级说法谁先请求先响应谁由于第四点引入了帧的概念因为每个帧都包含一个特定的类型和标识符以及帧的有效载荷。多个帧会形成流stream每个流有唯一的标识符。在发送请求时可以设置帧的优先级帧可以交错的发送也能进行流级别的流量控制 对比是写上了那对应的HTTP2.0用的技术并没有体现怎么转的那下面就引用一下参考的第一个链接作者的图吧 1.Hpack算法压缩展示如下图 2.二进制分帧的形式与文本传输的区别如下图 最后是1.0到2.0之前的发展史一目了然的图不要问我为什么没有3因为它没面世 1.4 HTTP3.0 HTTP2.0看起来用流解决了很大的问题但只是单纯的解决了HTTP协议上的头部问题对于传输层的TCP协议的队头并没有优化TCP协议的请求头依旧很繁重而且建立起TCP握手时间长。基于这个因素谷歌决定推出HTTP3.0版本舍弃TCP协议。舍弃TCP转而使用UDP协议。 HTTP/3.0在基于UDP迪菲赫尔曼算法Diffie–Hellman之上实现了QUIC协议Quick UDP Internet Connections 可能有人会说UDP是不可靠传输它只是尽最大努力交付这样数据丢失的问题怎么解决嗯基于目前用的UDP当然是不足以替代TCP。但是它修改了呀QUIC协议是在原UDP的基础上做了改造使得它提供了和TCP类似的可靠性。它提供了数据包重传、拥塞控制、调整传输节奏以及其他一些TCP中存在的特性。即拥有无序并发字节流又拥有稳定性还能用TLS1.3新的安全协议真的很让人期待啊。 思考了一下单纯说TCP头部重很多人没概念那我就上张TCP头部的图吧哈哈上学的时候考试要标注可以忽略写的文字哈 看上图就知道头部的臃肿度舍弃TCP是明智的。 2.域名系统DNS 为什么要提DNS呢主要是为了了解什么是根域名什么是顶级域名它们之间有什么关系,本地服务器是怎么走DNS解析拿到IP地址的。先上图 看图能知道根域名服务器→顶级域名服务器→权限域名服务器权限下面又可以细分如图二级域名三级域名 记得本地域名服务器不属于上图哦本地域名服务器后面要用到的哦 寻思了一下就先补充这些吧后续需要补充的再加。 二、算法知识补充 这儿需要补充的是二叉树相关的知识点只是简单了解本文不会延申到深度遍历和广度遍历。 什么是树树就是一个根上面很多树杈子这样就叫树方便理解上张图 注图内画红圈可以忽略 二叉树是一种特殊的树形结构它的特点是每个节点至多只有两棵子树。这儿要注意的是二叉树的子树有左右之分它的次序是不能任意颠倒的 二叉树又有几种类型满二叉树、完全二叉树、非完全二叉树。怎么辨别呢如下图 满二叉树最大的特点是每一层上的节点数都是最大的节点数满二叉树的第i层上有2的i-1次方个结点 完全二叉树如果对满二叉树的结点进行编号, 约定编号从根结点起, 自上而下, 自左而右。则深度为k的, 有n个结点的二叉树, 当且仅当其每一个结点都与深度为k的满二叉树中编号从1至n的结点一一对应时, 称之为完全二叉树 看上面两个定义应该能发现满二叉树是完全二叉树的特殊形态 这里就了解这么多知道什么是二叉树就好至于广度遍历和深度遍历感兴趣的自行了解哈。 三、渲染原理 1 DNS解析IP地址 用户输入y.abc.com点击回车键开始首先发生的第一步是将域名转为IP地址如果本地域名服务器有缓存该域名的IP地址就会直接向IP请求如果在本地域名服务器没有缓存那么就要用到域名解析系统“DNS”那么它是怎么从域名转为IP地址呢看下图 由上图可知DNS解析有两种解析方式一种是迭代查询一种是递归查询。根域名和顶级域名的关系在上面网络层知识补充上有有点懵的可以回头看哦。 单单看图可能有点不太理解那我就详细写一下迭代查询的步骤 1主机m.xyz.com先向其本地域名服务器的dns.xyz.com进行递归查询 2本地域名服务器采用迭代查询。它先向一个根域名服务器查询 3根域名服务器告诉本地域名服务器下一次应查询的顶级域名服务器dns.com的IP地址 4本地域名服务器向顶级域名服务器dns.com进行查询 5顶级域名服务器dns.com告诉本地域名服务器下一次应查询的权限域名服务器dns.abc.com的IP地址 6本地域名服务器向权限域名服务器dns.abc.com进行查询 7权限域名服务器dns.abc.com告诉本地域名服务器所查询的主机的IP地址 8本地域名服务器最后把查询结果告诉主机m.xyz.com。 递归查询也是类似上面的步骤。上面两种方式具体选哪个主要是看本地域名服务器自己选哪个方案。 到这肯定有人会问那每次本地每次都直接去根服务器去找那根域名服务器压力得多大啊全球也就13台根域名服务器tips不是说只有13台机器比如一个m根服务器可以在多个地点安装根域名服务器。嘿嘿我们能想到的别人怎么可能不早早就想到呢为了提高DNS的查询效率在域名服务器中广泛运用高速缓存域名服务器。用它存放最近查询过的域名以及从何处获得的域名映射信息的记录。例如在不久前已经有用户查询过y.abc.com的IP地址那么本地域名服务器就不必向跟域名服务器重新查询y.abc.com的IP地址而是直接把高速缓存中存放的上次查询结果告诉用户。还有一种方式本地域名服务器的缓存没有y.abc.com的IP地址但存放有顶级域名服务器dns.com的IP地址那么本地域名服务器可以直接找顶级域名服务器查询请求报文减少根域名服务器压力的同时也减少了DNS的查询请求和回答报文的数量。写多了写多了感兴趣的自己去百度吧 2 浏览器与服务器建立TCP连接    拿到IP地址之后就是要进行TCP连接。连接的图如下 我懒得画图啦直接就上计算机网络书本的图哈。 TCP三次握手建立连接需要注意哪些事项呢 1客户端和服务器传的SYN都为1的时候双方建立起连接 2SYN1时报文段不能携带数据 3为什么要确认一次呢最后一次的ACK1为了防止已失效的连接请求报文段突然又传送到服务器。防止资源浪费的同时确认双方的收发能力。 TCP建立起连接后就要看输入的连接是HTTP还是HTTPS啦。 这儿提出个欠欠的问题websocket是长连接那么它经不经过三次握手呢 嗯在网络里面传输的就TCP和UDP,UDP是出了名的不可靠传输别拿http3说话昂毕竟这玩意还在开发中websocket可是早就有了那只剩下TCP了所以要建立起稳定可靠的是不是必须经过TCP这点是不是一下子就清楚了 3 建立起TCP连接后进行SSL连接 首先这步有没有主要看输入的地址有没有https有才需要校验SSL证书有才需要这一步没有就跳过这一步。这儿需要注意一下http和https是两种不同的协议它们一点关系都没有http走的是80的端口而https走的是443的端口 写到这里了我都在犹豫要不要细写SSL建立的过程算了既然我自己做不了决定那就写一版粗略的写一版细的看文的自己选择性看呗。 3.1粗略版SSL建立连接 下图是别的作者画的图参考链接3的图我引用一下自己懒得画了懒是程序员第一生产力哈哈哈 这是粗略版的SSL的连接过程这儿需要注意三个点 1此时HTTP请求并没开始记好咯不要等会别人问ssl发生在http请求前还是请求后都回答错咯 2SSL证书也是有过期的说法的哦具体看买几年的一般小公司都是买一年然后续证的 3会存在中间人攻击不过达成的条件是客户端也要有相关中间人证书否则这个危险不会发生。 3.2详细版SSL建立连接 详细版那就要从由来开始一开始HTTP0.X协议传输都是明文是HTTP1.1后出现的加密看HTTP补充1.3里三个协议的对比就知道加密在什么时候用了。 由于是双方进行通讯所以考虑的一般是能双方进行加解密的方式所以选择上暂时只有对称加密和非对称加密 3.2.1对称加密 对称加密优势 算法公开、计算量小、加密速度快、加密解密效率高适合大量数据的加解密 对称加密的劣势交易双方都使用同样钥匙安全性得不到保证容易遭受黑客攻击。 3.2.2非对称加密 由于对称加密安全性得不到保证所以用非对称加密加密密钥和解密密钥不同。服务端有 一对公钥和私钥公钥用于加密私钥解密私钥用于加密公钥解密。 第一种方案直接用公钥加密如下图 请求的过程 客户端请求公钥 → 使用公钥加密传输数据 → 服务端使用私钥解密获取到请求原文 响应的过程 服务端使用私钥加密返回加密数据 → 客户端使用公钥解密获取响应报文。 存在的问题 请求阶段是公钥加密公钥不能解密所以请求是安全的。但响应阶段黑客同样可以获取到公钥在响应阶段黑客介入使用公钥对密文解密响应是不安全的。 由上可知直接用公钥私钥加密不够安全那怎么办呢第二种方案就出来了。 3.2.3 非对称加密对称加密 第二个方案就是双方共同利用 random_c random_s pre-master生成随机master secret后续都用这个加密的随机数进行通讯即可。在生成随机数进行沟通时走的是非对称加密到后期双方用加密后的随机数进行通讯走的是对称加密 如下图其实就是粗略版那张图 这样是不是就安全了呢嘿嘿当然不是啦不然怎么会有中间人攻击这个定义出来呢对吧如下图 图上表明了中间人介入的情况那么是不是中间人防不胜防呢也不是的。主要有两点 ①中间人向客户端发送公钥时客户端就会询问你“此网站的证书存在问题你确定要信任这个证书么。”所以从这个角度来说其实 HTTPS 的整个流程还是没有什么问题主要问题还是客户端不够安全。 ②中间人攻击需要客户端也有相关中间人证书否则也不会产生这个危险。 3.2.4 非对称加密对称加密ca公钥 中间人攻击主要是利用传递公钥做文章那我们在传的时候可不可以不传公钥呢嘿嘿这时候强大的CA机构该出场啦 首先操作系统内已经内嵌CA机构的公钥cpk。CA机构有一对公私钥cpk/csk。服务端也有一对公私钥pk/sk。服务端(花钱买的ca证书)把自己的公钥传递给CA机构CA机构使用csk对pk进行加密得到ca.密文CA把这个ca.密文返回给服务端后面客户端请求服务器都传ca.密文客户端得到这个ca.密文后根据自己操作系统中内嵌的CA机构的公钥cpk就能解开这个ca.密文。这个思路看起来很安全是不是但是不要忘记咯ca的公钥cpk是公开的黑客也知道很容易的就能对ca.密文进行截胡也就能够知道服务端公钥pk。所以还是会存在中间人攻击如下图参考资料4作者的图 这么分析下来还是有中间人攻击怎么办呢那能不能让CA机构直接对服务端进行认证一下是正牌服务端而不是伪服务端呢答案是有的毕竟安全无小事嘛 3.2.5对称加密非对称加密CA证书 ca机构在上面的基础上再加上对合法的服务端做认证这样就安全了。怎么进行安全认证呢当服务端把公钥给了ca机构ca机构会对这个服务端做背景调查(域名、公司名、法人...)然后ca机构会向服务端下发证书。最重要的一点是服务端公钥和域名绑定。客户端浏览器访问服务器时首先通过ssl协议443端口获取服务端证书浏览器会对证书做校验(最重要的一点是校验服务端域名和服务端公钥绑定关系) 下面我们一起看看证书得示例点击网址前的安全锁符号进入详情如下图 1、证书的签发过程 1服务方 S 向第三方机构CA提交公钥、组织信息、个人信息(域名)等信息并申请认证 2CA 通过线上、线下等多种手段验证申请者提供信息的真实性如组织是否存在、企业是否合法是否拥有域名的所有权等 3如信息审核通过CA 会向申请者签发认证文件-证书。 证书包含以下信息申请者公钥、申请者的组织信息和个人信息、签发机构 CA 的信息、有效时间、证书序列号等信息的明文同时包含一个签名 签名的产生算法首先使用散列函数计算公开的明文信息的信息摘要然后采用 CA 的私钥对信息摘要进行加密密文即签名 2、请求和响应的详细过程 步骤如下 1申请证书 2颁发证书 ca端收到服务端的公钥域名之类的信息利用ca的公钥pk加密加密和别的信息等组成证书颁发给服务端 3客户端请求获取证书 4响应服务器返回证书 5ca机构校验证书真伪利用cpk解密得到pk生成一个随机num1传加密后的随机数num1给服务端 6传加密后的随机数num1给服务端 7服务端用私钥解密后得到了客户端传过来的随机值约定通过该值(num1)进行对称加密 8服务端响应客户端就用这个随机值进行通讯双方到这建立起了连接 9双方根据这个随机num1进行加密数据传输和解密获取数据 步骤描述如下图 这儿可能有人会问HTTP请求结束了那ssl连接是不是也跟着断了呢答案是否定的ssl连接是跟TCP挂钩的只要TCP不断它就不会断。 4 建立HTTP请求传输数据 TCP连接建立安全链接也建立起来后就可以到http的请求过程啦。http请求我觉得没有多少可说的那就想到什么说什么吧。 如上图就是http的请求general部分主要是请求的路径请求的方法和返回请求的状态码。request headers就是设置部分固定参数其实http知识补充部分就已经讲了一些固定的字段或者搭配这儿值得再讲一讲的就是Connection:keep-alive。这代表这次请求完成后希望继续保持连接不断开。 下图为请求时候自己接口需要的参数。 嗯其实http暂时觉得没有什么好讲的要是有人觉得哪些值得讲讲的可以私我呀我可以补充。 那么就讲讲 RESTful API 这个规则吧。RESTful API (Representational State Transfer API) 是基于 HTTP 协议的一种 Web API 设计风格具体就如下 使用 HTTP 方法处理资源GET、POST、PUT、DELETE 等使用 URI 标识资源使用 MIME 类型如 JSON 或 XML传输数据无状态性每个请求都是独立的服务器不会保存客户端的状态信息。 为什么需要RESTful API呢因为这样我们可以一目了然的看见客户端和服务器之间传递数据比如数据的增、删、改、查等操作。在构建 web 应用程序时我们可以使用 RESTful API 来实现后台服务与前端页面之间的数据交互。具体例子如下 1 设计资源和 URI确定需要提供哪些资源以及每个资源的 URI例如 /users 表示所有用户资源/users/:id 表示单个用户资源。 2实现资源的 HTTP 方法实现 GET、POST、PUT、DELETE 等 HTTP 方法根据请求的 URI 执行相应的操作。例如DELETE 方法就是url /role/${roleId}GET获取列表 3返回数据使用 MIME 类型如 JSON 或 XML返回数据客户端使用这些数据进行展示和操作。 4安全性和认证根据需要添加认证和授权机制确保只有授权用户可以访问和操作资源。 讲了这个之后想引出一个疑问http的请求有限制吗限制多少个请求 答案http请求没有限制即使在一个tcp里面也不会限制http的请求请求需要排队等待而已。 5 是否走缓存 按理缓存是在HTTP请求前讲的因为在请求前就要判断是否有强缓存强缓存的话是直接读取就好但貌似目前用更多的是协商缓存而协商缓存是经过HTTP的所以将缓存放到HTTP建立后聊聊。以下是强缓存的全部内容步骤如下 1浏览器发送HTTP请求前先访问浏览器缓存是否需要缓存如为否的话就默认为no-store不启用缓存每次都直接走请求 2启用缓存的话再判断是不是每次都重新验证是的话就默认为no-cache不存缓存在浏览器但可以进行协商缓存 3不是每次都重新验证就看看是否允许代理服务器缓存不允许就只运行浏览器缓存允许两者都缓存 4看看cache-control种的max-age或者s-maxage这个字段是代理服务器特有的还有expires计算缓存时间是否过期若过期则重新请求没过期则直接拿强缓存的内容 看下图注意事项也在下图看图片也挺清晰的懒得打字啦 走完强缓存后就到协商缓存。步骤如下 1在上面步骤2在no-cache的时候看看是否有协商缓存没有的话直接进行请求有的话判断缓存是否过期没过期直接使用缓存的内容返回相关内容 2已经过期的先判断ETag资源的唯一标识字符串是否存在存在的话向服务器发送请求并在头部携带if-none-match字段值为1服务器返回304则读取本地的资源返回200则资源发生了变化请求响应协商缓存最终都是返回需要展示的资源。 3如果ETag不存在则去判断Last-modified存在吗不存在直接向服务器发送请求获取资源存在的话向服务器发送请求并在头部携带if-modified-since字段值为1服务器返回304则读取本地的资源返回200则资源发生了变化请求响应协商缓存最终都是返回需要展示的资源。 具体如下图 由于这张图片的tips模块文字有点不太清晰我写一遍 tips1ETag的生成需要服务器的额外开销会影响服务端的性能所以使用ETag要审时度势 tips2分布式系统尽量关闭ETag每台机器生产的ETag都不一样last-modified是必须保存一致的。 tips3用ETag的原因是last-modified如果改动太快100ms而if-modified-since监听的是秒会被误以为没有改动而导致该请求的没请求。或者是编辑了文件因为文件内容没改变仍通过最后编辑时间进行判断产生不该请求的时候请求了。 6 数据获取后断开TCP连接 该从缓存取得资源取了该通过HTTP请求获取资源的获取完成了那么就到了断开连接的时候啦。 下图为四次挥手的过程 为什么要进行四次挥手因为收到客户端发来的结束并不能立马结束要等数据传完确认接收完全才断连。 问为什么要在等待2MSLMSL最长报文段寿命RFC 793建议设为2分钟的时间后再断开连接 答①为了保证客户端发送的最后一个ACK报文段能够到达服务端②防止“已失效的连接请求报文段”出现在这次连接中。 对于保活计时器服务器每次接收到数据就重置保活计算器这儿不展开讲需要了解的可以自行百度。主要是应用于刚刚建立起连接然后客户端断连了如果客户端2小时没发消息给服务器服务器发送一次探测报文之后每隔75分钟发一次直到10次探测报文都没回复则中断连接。 下图是三次握手和四次挥手的状态流转挺有意思的贴出来有兴趣的可以看看 嗯这儿会有人觉得了解这么多有什么用呢我只是前端网络这块对前端开发或者在优化上说毫无意义。那到底这块有没有可以涉及到优化 我的回答当然有列举几点 1CDN加速就是在现有的Internet中增加一层新的CACHE(缓存)层将网站的内容发布到最接近用户的网络”边缘“的节点使用户可以就近取得所需的内容提高用户访问网站的响应速度。需要详细了解的可以看参考链接的内容懒得看参考就往dns那块回看看递归查询那个图就会发现权限域名那儿做了优化直接用智能调度的dns将cdn节点的ip返回给本地域名服务器直接去cdn的ip获取内容减少服务器的压力。 2缓存这个就是上面提到的强缓存和协商缓存强缓存减少过桥次数达到速度的提升协商缓存是减少过桥人数减少服务器的压力对应图片有写这句话哦可以回头看看 3雪碧图原理也是减少请求次数减少服务器压力 4开启gzip压缩减少数据的大小从而减轻服务器压力 5域名分片将网站的资源分布在多个子域名下,实现更高的并发连接数 6使用HTTP2.0多路复用提高效率 嘿嘿是不是总觉得有点熟悉感那当然啦在HTTP1.1优化那提到过这儿只是再次重申告诉小伙伴网络这块的优化也很重要不要只看渲染那块要全面些的去了解。 那么至此资源已经从网络上获取了接下来就进入了渲染的过程。嘿嘿你会不会觉得就剩渲染了这么简单三两笔就能搞定没多少内容了悄悄告诉你可能还有一半呢哈哈哈不要放弃啊坚持呀我写都写了那么久哪能让你一下子就看完的嘛实在不行去玩一阵回来再看呗。 7 浏览器渲染 7.1浏览器进程 开始往下讲前先老生常谈回顾一下浏览器的进程浏览器是多进程的大家都知道每开一个tab页面就相当开一个进程别杠某些情况可能会由于优化策略进行合并另说这个我想大家都知道哈。 浏览器进程主要有以下几个 Browser进程浏览器的主进程负责协调、主控只有一个作用 1负责浏览器界面的显示、与用户交互如前进、后退、刷新等 2负责各个页面的管理创建和销毁其他进程 3将渲染进程得到的内存中的栅格图绘制到用户界面上 4网络资源的管理和下载等 第三方插件进程 顾名思义就是在使用插件的时候才创建的 GPU进程 目前只有一个一般用于3D的绘制 浏览器渲染进程前端最关心的模块啦 默认每打开一个tab页面就会启动一个渲染进程主要负责页面的渲染脚本的执行事件的处理。 浏览器多线程主要是为了提高浏览器的稳定性哈哈总不可以这个页面崩了别的页面也崩了吧那人也崩了哈哈哈 7.2 浏览器渲染进程 浏览器渲染进程是我们的重点关键对象底层逻辑搞清楚了做优化自然而然就会了。浏览器渲染进程主要有GUI 渲染线程、 JavaScript引擎线程、 定时触发器线程、 事件触发线程、 异步http请求线程 1.GUI渲染线程 主要负责页面的渲染解析HTML、CSS构建DOM树布局和绘制等。当界面需要重绘或者由于某种操作引发回流时将执行该线程。该线程与JS引擎线程互斥当执行JS引擎线程时GUI渲染会被挂起当任务队列空闲时主线程才会去执行GUI渲染。 2.JS引擎线程 该线程当然是主要负责处理 JavaScript脚本执行代码。也是主要负责执行准备好待执行的事件即定时器计数结束或者异步请求成功并正确返回时将依次进入任务队列等待 JS引擎线程的执行。当然该线程与 GUI渲染线程互斥当 JS引擎线程执行 JavaScript脚本时间过长将导致页面渲染的阻塞。 3.定时器触发线程 负责执行异步定时器一类的函数的线程如 setTimeoutsetInterval。主线程依次执行代码时遇到定时器会将定时器交给该线程处理当计数完毕后事件触发线程会将计数完毕后的事件加入到任务队列的尾部等待JS引擎线程执行。 4.事件触发线程 主要负责将准备好的事件交给 JS引擎线程执行。 比如 setTimeout定时器计数结束 ajax等异步请求成功并触发回调函数或者用户触发点击事件时该线程会将整装待发的事件依次加入到任务队列的队尾等待 JS引擎线程的执行。 5.异步http请求线程 负责执行异步请求一类的函数的线程如 Promiseaxiosajax等。主线程依次执行代码时遇到异步请求会将函数交给该线程处理当监听到状态码变更如果有回调函数事件触发线程会将回调函数加入到任务队列的尾部等待JS引擎线程执行。 在这里我只会重点讲GUI渲染线程和JS引擎线程嗯我先立flag毕竟GUI渲染线程就有得我写的了立了flag才有动力写JS引擎线程JS引擎线程会包含后面3-4-5的线程结合聊。那么进入GUI渲染线程的主题吧 7.2.1 页面绘制的流程 页面绘制的流程不同浏览器的步骤大同小异图一为谷歌的渲染流程 图二是Mozilla 的 Gecko 呈现引擎主流程 看上图其实都是构建DOM树构建CSS Rules渲染树布局绘制显示。面试的时候大部分人都这样回答过吧。如果年限是2-3年的这样回答都很满意了因为知道整个流程不得不说现在培训出来的大部分带着偏见觉得会用三大框架足够根本不需要了解这些甚至也不屑于了解觉得没用如果年限上去了那就再往深处走吧。 在开始下文前需要知道的是请求回来的资源都需要经过Bytes转成对应的文件。 7.2.2  DOM的渲染 DOM的渲染首先是拿到HTML文件按照规则进行解构。 !DOCTYPE html htmlbodydivh1My First Heading/h1pMy first paragraph./p/div /body/html上面代码块parse后就成为下图 上图就是DOMDocument Object Model树啦 DOM是一棵树是树就会有父子和邻居的关系而且这棵树是暴露API给JS调用JS可以查询和修改这棵树。JS引擎V8通过bindings的系统将DOM包装为DOM API供给Web开发者调用。 这儿有个注意点一个文档里面可能包含多个DOM树类似用的slot一样插入一个DOM树最终都会在遍历树之后合成一棵树。 DOM树相对来说看起来比较简单那我们进阶一下 思考一下JS有AST抽象树HTML是不是也有呢嘿嘿当然有上图的代码抽象树如下 h1的详细AST抽象树如下 其实它跟JS的AST抽象树差不多都是一个对象不断的展开就是属性不太一样比如它的Text$3代表的是文字Element$1代表节点节点的name是什么attributes有哪些。 这儿有人会问为什么要了解这个别着急呀咱先看看目前流行的虚拟DOM结构 // 虚拟DOM节点的数据结构表示 const virtualNode {type: div, // 节点类型props: { // 节点属性id: textDiv,className: container},children: [ // 子节点{type: h1,props: {textContent: Hello!},children: []},{type: p,props: {textContent: This is an example of virtual DOM.},children: []}] };两者对比是不是相似度挺高的当然的啦毕竟虚拟DOM与真实DOM之间是一种映射关系。我记得有人纠结过虚拟DOM在vue中和react中是不是一样的其实没必要纠结VNnode就是模拟DOM节点的对象它们无论是在vue和react中都是一样的。并没有因为框架的原因导致这对象不同框架之间的不同在于diff算法的不同vue是双指针而react是单指针。 虚拟DOM的出现是为了减少对DOM的操作从而提高性能那么单纯的HTML怎么进行优化呢这儿就不得不提回流了虽然按理这个应该涉及到CSS再提的。回流就是DOM结构发生了变化触发了浏览器重走整个7.2的所有流程。这个代价是巨大的。那么写好稳定结构的HTML就比较关键了。如下图 这个结构怎么写我看之前带的小伙伴是用float一左一右当右边的选项边多的时候结构就变形排版错乱了这样就引起了回流。最佳的解决方案就是在外面套个div用flex布局左右两边固定宽度。稳定结构即使是后期修改布局也不至于删掉一个图标整个布局就垮掉。 再有就是在写原生的时候修改大面积的DOM时先display:none操作好了再加进来。或者是加入一段HTML节点的时候用document.createDocumentFragment()减少频繁的操作DOM从而提高性能。 7.2.3  CSS rules DOM树在渲染的同时CSS也同样在解析下面是解析成CSS rules的步骤。 如下代码 media screen and (min-width: 480px) {body {background-color: lightgreen;} }#main {border: 1px solid black; }.li-list {margin:5px } 将代码parse后就成下面的结构 这儿已经写了结构我就直接把CSS的AST搬出来了吧。 如果你想自己看某个网页的CSSRules直接输入 document.styleSheets[0].cssRules 就可以看见对应的结构。 这儿需要提一下cssText这儿还会进行CSSPropertyValue的一个转换。比如font-size:2em的2em会转换成32px。 这儿可能有人会问为什么你总爱提AST抽象树 因为AST本就是底层很重要的东西呀只不过大部分人都只接触或者是只听到了JS的AST抽象树实际HTML和CSS都是一样有抽象树它的核心作用是什么核心作用就是解析 - 转换 - 生成。Babel的作用大家都知道吧先将es6语法转为AST抽象树然后再将转换的AST抽象树转换成浏览器能识别的JS的AST抽象树最后浏览器解析出来。 就像DOM树的AST一样了解了它的结构你一发散思维就能感悟到虚拟DOM怎么来的为什么能从这个方面去优化。 回归CSS主题CSS文件解析成AST树后结构如下图 它会分成每个CSSStyleRule而且这儿要注意它不会根据你的层级去嵌套DOM的AST抽象树是有子节点就嵌套在childrens里面CSS Rules就不是例如ul就是一个单独的CSSStyleRuleulli又是一个单独的CSSStyleRule。 单纯的讲CSS的解析层面就是上面内容了CSS通常需要结合DOM生成渲染树才有更多可扩展性的讲。 7.2.4  渲染树 DOM树和CSS Rules都已经分别生成好了。那怎么让他们对应上呢咱回看7.2.1的两张图。在谷歌浏览器里面有一个Attachment的过程火狐浏览器有 FrameConstructor这个过程。它们两者的作用是一样的只不过用的方法不同而已大概执行的内容如下图图是偷的哈哈哈 算法主要是将解析后的DOM树和CSS Rulse进行匹配节点匹配对应的css样式进行渲染这个匹配过程提出来主要是引出部分关于CSS的优化。 在面试中我经常会问面试者你写CSS的样式会嵌套几层 有些人会很不屑于回答我这个问题那我问这个问题主要想考面试者什么呢其实就是想问他是否了解css选择器是从右往左找节点匹配对应的DOM样式的。 为什么css的选择器不是从左向右找呢比如.list-lili.content{} 按从左到右步骤如下 先找到所有 div 节点。 在 div 节点内找到所有的子 div并且是 class “list-li”。 然后再依次匹配li .content等情况。 遇到不匹配的情况就必须回溯到一开始搜索的 div  节点然后去搜索下个节点重复这样的过程。嗯就是广度遍历不理解可以看补充知识的树那儿节点一层层往下找遍历的时间会比较长 按从右往左步骤如下 首先就查找到 class“content” 的元素。 接着检测父节点是否为 li 元素如果不是则进入同级其他节点的遍历如果是则继续匹配父节点满足 class“list-li” 的 div 容器。 这样就又减少了集合的元素只有符合当前的子规则才会匹配再上一条子规则。 对比起来从右往左这样更快的找到节点需要的时间就更短。 从这儿我又会延申问面试者你写的less或者是scss一般写多少层嵌套 如果我现在问屏幕前的你你会怎么答还是会说按照需求去嵌套多少层吗我希望你在看完这篇文章后别人问的时候你回答是嵌套一般不超三层因为按css选择器从右往左读的原则越嵌套多查找的时间越长。嵌套三层是相对更合适的。 在面试中我也会问为什么在日常中用class多过id的有人会告诉我大家都用好用。有些人也会回答到点上只要渲染过一次class再遇到一样class结构一样的就可以直接复用不需要浏览器再次渲染一次class样式。 那到底是怎么复用复用的条件是什么这儿就不得不提到computedStyle的高效共享这点啦。看下面代码 div classcontentp classtext我是看不同的优化/p /div div classcontentp classtext我是看不同的优化2/p /div--------------------------分割线-----------------div classcontentp classtext stylecolor:red我是看不同的优化/p /div div classcontentp classtext我是看不同的优化2/p /div--------------------------分割线-----------------div classcontentp classtext title滑过可见 我是看不同的优化/p /div div classcontentp classtext title滑过可见 我是看不同的优化2/p /div 上面哪个是共享的先思考然后看computedStyle的高效共享的规则 1、TagName和Class属性必须一样 2、不能用style属性哪怕属性是一样的都不共享 3、不能使用sibling选择器比如:first-child 4、标签内的属性必须要相等。 上述答案就是1和3共享2不共享。 computedStyle后就组装渲染树。注意一点形成渲染树的过程有布局同时进行无论是谷歌的layout还是Gecko的reflow都是在构建渲染树的同时在进行布局图片在7.2.1。 7.2.5  布局 布局中浏览器要做的事情是要弄清楚各个节点在页面中的确切位置和大小。通常这一行为也被称为“自动重排”。大白话就是按照写的每一个CSS样式去布局一个div比如它的宽高颜色字体等等属性。主要执行类似于下图图还是偷的哈哈哈 如图通过遍历DOM树创建渲染树LayoutTree节点一一对应。布局树中的节点实现布局算法。根据所需的布局行为LayoutObject有不同的子类。比如LayoutBlockFlow就是块级Flow的文档节点。样式更新阶段也会构建布局树。 这儿提个点伪类是作用在LayoutTree上的如p::before{content:Hi!}也不在DOM里而是在Layout Tree上。可以理解DOM是本体伪类是给本体的“化妆”比如伪娘本体是男的但是看着像女的 布局这块最值得提的可能就是涉及到怎么写css样式的最优方式。首先抛出个问题你在写一个class的时候什么样式先写有没有问过自己为什么这样写ok问完你我开始讲正题 .list-li{display: block;width: 100px;height: 200px;position: absolute;left:8px; }//--------------------分割线--------------.list-li{position: absolute;left:8px;display: block;width: 100px;height: 200px; } 上面两种样式有什么区别哪种是优选来按第一种class来因为浏览器是自上而下读取css布局的。那么首先读到是的它是块作用域然后宽度是100像素高度200像素然后到定位这浏览发现它给这个块划分的区域是不对的因为这个定位属性让它脱离了文档流。那怎么办呢浏览器只能重新排版将其从文档流抽出再进行布局。 那么这就说明了这儿浏览器是浪费了一些时间在重新排版上的。ok我们看第二个首先就告诉浏览器这个div是脱离文档流的然后它向左边偏离8像素然后宽是100像素高是200像素。全程浏览器没有触发重新排版的。对比下来是不是第二种写法更优 嗯事实就是第二种写法更优所以我们在写样式的时候也需要注意写的样式先后顺序。你要是杠我时间很短可以忽略不记那你可以不用看我文章毕竟都是这种小细节的优化多那么日常中怎么写顺序最优呢下面是对应的列表 名称属性定位属性 position  display  float  left  top  right  bottom   overflow  clear   z-index 自身属性 width  height  padding  border  margin   background 文字样式 font-family   font-size   font-style   font-weight   font-varient   color 文本属性 text-align   vertical-align   text-wrap   text-transform   text-indent    text-decoration   letter-spacing word-spacing    white-space   text-overflow CSS3 中新增属性 content   box-shadow   border-radius  transform 日常书写最好按照这个顺序写如果你没有用别的css插件的话养成好的习惯是很重要的在css这步就避免部分的回流这对程序员来说不是一个很nice的点吗 当然现在项目中很多人用stylelint这个插件stylelint里面的规则也有写属性按照什么顺序去排具体如下图 在布局这儿我主要想表达的就是在这儿做css样式写的优化。 其次还有一个点就是在布局这儿还有LayerTree。LayerTree就是根据脱离文档流的内容进行分层布局。以下这些属性都可能让其分层的position、css3的属性如transform属性、video、canvas、css3的动画效果属性等。 7.2.6  绘制 绘制这儿先甩两张图 第一张平面看到流程的一个是主线程和一个非主线程 一张能看见流转步骤的图当然这一看就不是我画的哈哈哈  从上面两张图应该能看到其实我们到了paint这个阶段了。 paint这个阶段其实说白了就是为每个图层生成绘制列表并将其提交到合成线程。到这儿页面上实质上还是什么都没有的因为这个阶段只是创建绘制指令paint op如下图 图片的面板是谷歌工具栏设置按钮旁边的...然后选择more tools找到Layers就可以看见啦 绘制指令paint op 可以理解为某些坐标x,y,w,h画一个矩形嗯试着读一下上图的代码drawPaint(paint)执行绘制开始第二步drawRect(0,0,990,1125,paint)绘制一个矩形坐标是(0,0,990,1125)第三步执行保存。 嘿嘿写过canvas的小伙伴这儿应该熟悉吧这其实就是在画canvas呀 由上图截图也可以看出前面说的绘制出来的就是每个图层的绘制列表。绘制列表完成后就会把它提交到合成线程 1 tiles模块 tiles是什么东西首先我们的页面是很大的向下拉伸理论上是可以无限延长的。如果我们一次性加载那用户得等疯了吧所以浏览器不可能加载完再画。这时就延申出来了分块平铺的概念。分块平铺是什么意思呢比如我们要铺一间房间的瓷砖不能一下子就铺完吧可以将房间划分为一块块区域比如厕所一块区域洗刷台一块区域阳台一块区域分区域来铺瓷砖。 分块平铺是发生在绘制后栅格化前。根据视口viewport所在位置的不同渲染进程合成器线程会选择靠近视口的图块tiles先进行渲染将最后选择渲染的图块传递给GPU栅格化线程池里的单个栅格化线程执行栅格化最后得到栅格化好后的tile图块。 上图就是可视窗口能看见的部分优先渲染滚动条后面是无线长的页面 那么什么叫栅格化呢往下看 2 raster模块 光栅化也称为栅格化就是将绘制指令paint op转化为位图bitmap的过程转化后每个像素点的rgba都确定。图块是栅格化的任务单位一般是256*256或者是512*512一个一个的转为bitmap具体怎么实现看下图 (GPU可以加速栅格化这儿可以拓展一下three的贴图向量也是为了方便快速栅格化) 栅格化所有的图块tiles完成后渲染进程的合成器线程收集tiles的draw quads信息创建CompositorFrame。可以理解为一个房间的瓷砖由很多个小瓷砖组成。 3 draw quads quad类似于在屏幕上特定位置绘制图块tile的指令draw quads就是绘制图块们的意思。此时的quads是层树LayerTree在拿属性树经过一堆变换后的最终结果每个quad都引用图块tiles在GPU内存里的栅格化输出结果。 很多个draw quads被包在CompositorFrame里面这个是渲染进程最后的输出 这儿按理是还有个activation的过程的但是我自己理解得还不够透暂时空着具体可以看链接像素的一生 7.2.7  显示 看到绘制小节的第一张图可以看到display是在GUI进程实现的。GUI进程的显示合成器会将CompositorFrame进行合并处理后进行显示。 显示这儿我摸得还是不够透就误导你们啦。 这儿提一下当用js或者是css触发回流时走的流程如下 如果是触发重绘的话就直接跳过Layout和layer这两步直接走Piant往后的步骤。 整篇文章暂时就先到这啦。JS引擎线程这块我会在6月底前补完。毕竟说了要顺带说JS引擎线程的flag都立下了哈哈哈。会完成的。如果感兴趣可以六月底再来看看哦。 参考文章 http发展史https://juejin.cn/post/7257740918433235000 content-type的类型https://blog.csdn.net/qq_44741577/article/details/136507746 SSL协议运行过程https://juejin.cn/post/7238619890993643575 https的原理加密等https://www.cnblogs.com/zhenjingcool/p/17255119.html CDN加速https://blog.csdn.net/weixin_42358261/article/details/113490522 浏览器渲染进程的线程出处https://juejin.cn/post/6844903761949753352#heading-12     DOM树和CSS树render树的原理https://blog.csdn.net/weixin_56266471/article/details/126107903 CSS渲染以及优化策略http://jartto.wang/2019/10/23/css-theory-and-optimization/ 像素的一生https://zhuanlan.zhihu.com/p/594398362
http://www.tj-hxxt.cn/news/224619.html

相关文章:

  • 淘宝客如何建设自己的网站企业服务咨询
  • 花木企业网站源码wordpress 仪表板主题
  • 网站开发的最后5个阶段网站建设依据什么法律
  • 海宁市规划建设局网站做招聘网站需要什么
  • 郑州快速建站公司仿素材网站源码
  • 上海的设计网站单位网站中文域名到期续费
  • 深圳网站推广优如何重建网站
  • 青海网页设计与网站建设网站建设创意文案
  • 做外贸网站案例宝安网站建设方案外包
  • 唐山做网站的电话吉林城市建设学校网站
  • ip做网站需要过白名单吗上海网站建设与设计公司好
  • 展示型网站模板代码百度seo官网
  • 旅游社网站建设规划书网站建设开场白
  • 镇江网站建设方式优化网站后台添加东西不能粘贴
  • 衡水需要做网站的公司开网站做彩票赚钱吗
  • 杭州网站建站公司自己做网站卖产品怎么样
  • 网站怎么用html网页设计代码作业网站
  • 条件查询 php网站源码建外贸网站有效果吗
  • 台州网站建设服务python编写网页
  • 网站做广告投放 要求做效果评估乐天seo培训中心
  • 企业logo设计网站进一步优化落实
  • 网站公司排行榜北京师范大学学风建设专题网站
  • 网站备案管理办法wordpress学生
  • 中国铁路建设集团公司网站wordpress取消自适应
  • 网站建制作建筑模板做凳子
  • 产品详情页面设计山西搜索引擎优化
  • 深圳华企网站建设落地页制作
  • 外贸网站建设制作滨海做网站的价格
  • 盘锦网站建设公司参考消息今天新闻
  • 深圳网站建设深正互联404源码网html