background-image
属性指定的图片路径。浏览器会开始从服务器请求这些图片资源,并进行加载。background-image
属性设置)在它们的父元素可见时会开始加载,并在加载完成后进行渲染。alt
属性定义)或显示一个空白区域。srcset
属性可以实现根据屏幕大小加载不同尺寸的响应式图片。这可以提高页面的性能和适应性。以上是图片在 HTML 和 CSS 中加载和渲染的基本规则。通过优化图片大小、格式选择、懒加载等技术可以进一步提升网页加载速度和用户体验。
b 标记用于指定文本加粗的外观效果,通常只是为了强调关键词或短语,没有特别强的语义化含义。而 strong 标记则表示文本的强调重点,具有更强的语义化含义,并且可以改变文本的语调和读音等方面。
i 标记用于指定文本斜体的外观效果,通常只是为了强调关键词或短语,没有特别强的语义化含义。而 em 标记则表示文本的重要性,具有更强的语义化含义,并且可以改变文本的语调和读音等方面。
需要注意的是,在 HTML5 中,b 和 i 标记已经被废弃,推荐使用 strong 和 em 标记来代替。同时,随着搜索引擎的发展和语义化网页的兴起,h1-h6 标记也被赋予了更重要的语义化含义,应该根据具体情况来选择使用不同的标记。
因为浏览器在渲染html的时候是从上到下执行的,当遇到js文件的时候就会停止当前页面的渲染,转而去下载js文件。如果将script标签放在头部,在文件很大的情况下将导致首屏加载时间延长,影响用户体验。
SSG(Static Site Generation,静态网站生成)是指在构建时预先生成静态页面,并将这些页面部署到 CDN 或者其他存储服务中,以提升 Web 应用的性能和用户体验。
具体来说,SSG 的实现方式通常包括以下几个步骤:
相比于传统的动态网页,SSG 具有如下优势:
需要注意的是,SSG 不适用于频繁更新的内容和动态交互等场景,但对于内容较为稳定和更新较少的网站则是一个性能优化的好选择。
withCredentials
属性:在发送跨域请求时,将 XMLHttpRequest
对象的 withCredentials
属性设置为 true
,表示允许发送和接收包含凭证(Cookie、HTTP认证等)的请求。服务器端也需设置响应头 Access-Control-Allow-Credentials: true
,确保响应中包含 Set-Cookie
头信息。需要注意的是,对于简单请求(比如 GET、POST),服务器端的响应头不能包含除了基本字段之外的其他自定义字段,否则浏览器会返回错误。javascript复制代码const xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.open('GET', 'http://example.com/api', true);
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
// 请求成功处理逻辑
}
};
xhr.send();
Access-Control-Allow-Origin
:服务器端需要设置响应头 Access-Control-Allow-Origin
,指定允许请求的源。可以设置为具体的域名,或使用通配符 *
表示允许任意域名请求。同时需要设置 Access-Control-Allow-Credentials: true
表示允许携带凭证。HTML5是HTML的新标准,其主要目标是无需任何额外的插件如Flash、Silverlight等,就可以传输所有内容。它囊括了动画、视频、丰富的图形用户界面等。
HTML5是由万维网联盟(W3C)和 Web Hypertext Application Technology Working Group
合作创建的HTML新版本。
从文档声明类型上看:
HTML是很长的一段代码,很难记住。如下代码:
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3<html xmlns="http://www.w3.org/1999/xhtml">
HTML5却只有简简单单的声明,方便记忆。如下:
<!DOCTYPE html>
从语义结构上看:
不输入,浏览器将无法识别html文件,因此html将无法正常工作。
从网络传给渲染引擎的 HTML 文件字节流是无法直接被渲染引擎理解的,所以要将其转化为渲染引擎能够理解的内部结构,这个结构就是 DOM。
DOM 提供了对 HTML 文档结构化的表述。
在渲染引擎中,DOM 有三个层面的作用:
简言之,DOM 是表述 HTML 的内部数据结构,它会将 Web 页面和 JavaScript 脚本连接起来,并过滤一些不安全的内容。
HTML 解析器(HTMLParser): 负责将 HTML 字节流转换为 DOM 结构。
从图中我们可以知道,网络进程和渲染进程之间有一个共享数据通道,网络进程加载了多少数据, 就将数据传给HTML解析器进行解析。
HTML解析器接收到数据(字节流)之后,字节流将转化成DOM,过程如下:
预览
有三个阶段:
1、通过分词器将字节流转化为Token。 分词器先将字节流转换为一个个 Token,分为 Tag Token 和文本 Token。
注意,这里的Token并不是我们之前理解的Token,这里就是一个片段。
2、Token解析为DOM节点。
3、将 DOM节点添加到DOM树中。
我们知道,JavaScript可以修改DOM,它也会影响DOM的生成。
1、内嵌 JavaScript 脚本 比如我们嵌入了一段``标签的代码,之前的解析过程都一样,但是解析到script标签时, 渲染引擎判断这是一段脚本,此时 HTML 解析器就会暂停 DOM 的解析, 因为接下来的 JavaScript 可能要修改当前已经生成的 DOM 结构。
暂停解析之后,JavaScript 引擎介入,并执行``标签中的这段脚本。 脚本执行完成之后,HTML 解析器恢复解析过程,继续解析后续的内容,直至生成最终的 DOM。
2、引入 JavaScript 文件 基本上跟之前是一致的,不同点在于,暂停解析之后执行JavaScript 代码,需要先下载这段 JavaScript 代码。
白屏时间:即用户点击一个链接或打开浏览器输入URL地址后,从屏幕空白到显示第一个画面的时间。
当用户点开一个链接或者是直接在浏览器中输入URL开始进行访问时,就开始等待页面的展示。页面渲染的时间越短,用户等待的时间就越短,用户感知到页面的速度就越快。这样可以极大的提升用户的体验,减少用户的跳出,提升页面的留存率。
从输入url,到页面的画面展示的过程
1、首先,在浏览器地址栏中输入url
2、浏览器先查看浏览器缓存-系统缓存-路由器缓存,如果缓存中有,会直接在屏幕中显示页面内容。若没有,则跳到第三步操作。
3、在发送http请求前,需要域名解析(DNS解析),解析获取相应的IP地址。
4、浏览器向服务器发起tcp连接,与浏览器建立tcp三次握手。
5、握手成功后,浏览器向服务器发送http请求,请求数据包。
6、服务器处理收到的请求,将数据返回至浏览器
7、浏览器收到HTTP响应
8、读取页面内容,浏览器渲染,解析html源码
9、生成Dom树、解析css样式、js交互,渲染显示页面
浏览器下载HTML后,首先解析头部代码,进行样式表下载,然后继续向下解析HTML代码,构建DOM树,同时进行样式下载。当DOM树构建完成后,立即开始构造CSSOM树。理想情况下,样式表下载速度够快,DOM树和CSSOM树进入一个并行的过程,当两棵树构建完毕,构建渲染树,然后进行绘制。
Tips:浏览器安全解析策略对解析HTML造成的影响:
当解析HTML时遇到内联JS代码,会阻塞DOM树的构建,会先执行完JS代码;当CSS样式文件没有下载完成时,浏览器解析HTML遇到了内联JS代码,此时,浏览器暂停JS脚本执行,暂停HTML解析。直到CSS文件下载完成,完成CSSOM树构建,重新恢复原来的解析。
JavaScript 会阻塞 DOM 生成,而样式文件又会阻塞 JavaScript 的执行,所以在实际的工程中需要重点关注 JavaScript 文件和样式表文件,使用不当会影响到页面性能的。
针对DNS Lookup环节,我们可以针对性的进行DNS解析优化。
多花点钱吧
服务端的处理优化,是一个非常庞大的话题,会涉及到如Redis缓存、数据库存储优化或是系统内的各种中间件以及Gzip压缩等…
根据浏览器对页面的下载、解析、渲染过程,可以考虑一下的优化处理:
1document.documentElement.clientHeight//获取屏幕可视区域的高度
2element.offsetTop//获取元素相对于文档顶部的高度
因为JavaScript 会阻塞 DOM 生成,而样式文件又会阻塞 JavaScript 的执行,所以在实际的工程中需要重点关注 JavaScript 文件和样式表文件,使用不当会影响到页面性能的。
渐进式 JPEG(Progressive JPEG),即PJPEG,是该标准的三种流行压缩模式之一。
渐进式 JPEG 以特定方式压缩照片和图形,与基线 JPEG 不同,PJPEG 在 Web 浏览器中呈现时,会首先给出模糊图像的外观。然后一点一点地开始图片渲染,直到它显示完全渲染的图像。浏览器实际上是逐行解释图像,但在占位符中提供了完整图像的模糊预览。随着 Web 浏览器的渲染引擎处理数据,图像的对比度开始变得更清晰、更详细。直到最后渲染完毕,用户将看到完整的清晰图像。
PJPEG 能够起到一种很有意义的心理效果,让用户有东西可看,而不必坐着干等大型图像慢慢显示在屏幕上。
PJPEG 适用于大部分常用的浏览器,包括 Chrome
、Firefox
和 Internet Explorer 9
及更高版本。旧版本的 Internet Explorer 在显示渐进式 JPEG 时存在一些问题,不过这只是很小一部分用户。而不支持渐进式 JPEG 格式的浏览器会像普通 JPEG 一样加载照片。
实现预览有两种方式:
window.URL.createObjectURl
方法对选择的图片数据(可以勉强理解为input的value)生成一个blob对象路径FileReader
读取器那么无论那种方法,首先都得得到文件数据,获得文件数据是从files集合中获取。
先来看下 window.URL.createObjectURl
的实现方法:
1function imgChange(img) {
2 document.querySelector("img").src=window.URL.cteateObejectURL(img.files[0]);
3}
而使用 FileRader
读取文件.可分为四步;
FileReader
对像;readAsDataURL
方法读取文件;onload
事件监听。因为我们需要拿到完整的数据,但我们又不知道文件何时读完,所以需要第三步监听;FileReader
的 result
属性拿到读取结果。复制1function imgChange(img) {
2 // 生成一个文件读取的对象
3 const reader = new FileReader();
4 reader.onload = function (ev) {
5 document.querySelector("img").src = imgFile;
6 }
7 //发起异步读取文件请求,读取结果为data:url的字符串形式,
8 reader.readAsDataURL(img.files[0]);
}
SPA全名是Single Page Application
,指的是单页面应用。
SEO全称为Search Engine Optimization
,指的是搜索引擎优化。
SPA技术将产出html的逻辑从服务器转移到了客户端,在进入React, Vue等UI框架进行开发时,我们开发的页面更多的是在客户端进行脚本执行、数据请求和UI动态装载。
那么搜索引擎爬虫在抓取这样的页面的时,在未做任何优化的情况下,通常拿到的是类似下面的字符文本:
1<!DOCTYPE html>
2<html lang="zh-CN">
3<head>
4 <meta charset="UTF-8">
5 <title>title</title>
6</head>
7<body>
8<div id="root"></div>
9<script src="index.js"></script>
10</body>
11</html>
除了可以事先定义的title(可能title也不能事先确定),在SPA下很多内容需要通过ajax请求server拿到数据通过脚本执行产生。通常爬虫不会有类似浏览器的执行环境去产生这些内容。
那么如何让爬虫拿到的数据和用户通过浏览器看到的数据尽量是一致?
优点:用户体验好,前后端代码分离,利于后期的维护
缺点:seo不好,首次加载时长比较久,导航需要自己去实现前进后退。
优点:首屏加载快(因为服务器返回的网页已经包含数据, 所以之下载完JS/CSS就可以直接渲染)。每次请求返回的都是一个独立完成的网页, 更利于SEO。
缺点就是服务器压力会比较大,对网络要求比较大,
无需服务器实时动态编译,采用预渲染,在构建时针对特定路由简单的生成静态HTML文件
本质就是客户端渲染, 只不过和SPA不同的是预渲染有多个界面
最大优点: 由于有多个界面, 所以更利于SEO
最大缺点: 首屏加载慢, 预编译会非常的慢
SEO(Search Engine Optimization),汉译为搜索引擎优化。
搜索引擎优化是一种利用搜索引擎的搜索规则来提高目前网站在有关搜索引擎内的自然排名的方式。
SEO是指为了从搜索引擎中获得更多的免费流量,从网站结构、内容建设方案、用户互动传播、页面等角度进行合理规划,使网站更适合搜索引擎的索引原则的行为。
搜索引擎派出一个能够在网上发现新网页并抓取文件的程序,这个程序通常被称为蜘蛛或机器人。
搜索引擎蜘蛛从数据库中已知的网页开始出发,就像正常用户的浏览器一样访问这些网页并抓取文件。
并且搜索引擎蜘蛛会跟踪网页上的链接,访问更多网页,这个过程就叫爬行。
当通过链接发现有新的网址时,蜘蛛将把新网址记录入数据库等待抓取。
跟踪网页链接是搜索引擎蜘蛛发现新网址的最基本方法,所以反向链接成为搜索引擎优化的最基本因素之一。
没有反向链接,搜索引擎连页面都发现不了,就更谈不上排名了。
搜索引擎蜘蛛抓取的页面文件与用户浏览器得到的完全一样,抓取的文件存入数据库。
搜索引擎索引程序把蜘蛛抓取的网页文件分解、分析,并以巨大表格的形式存入数据库,这个过程就是索引。在索引数据库中,网页文字内容,关键词出现的位置、字体、颜色、加粗、斜体等相关信息都有相应记录。
搜索引擎索引数据库存储巨量数据,主流搜索引擎通常都存有几十亿级别的网页。
用户在搜索引擎界面输入关键词,单击“搜索”按钮后,搜索引擎程序即对输入的搜索词进行处理,如中文特有的分词处理,对关键词词序的分别,去除停止词,判断是否需要启动整合搜索,判断是否有拼写错误或错别字等情况。搜索词的处理必须十分快速。
对搜索词进行处理后,搜索引擎排序程序开始工作,从索引数据库中找出所有包含搜索词的网页,并且根据排名计算法计算出哪些网页应该排在前面,然后按一定格式返回“搜索”页面。
排序过程虽然在一两秒之内就完成返回用户所要的搜索结果,实际上这是一个非常复杂的过程。排名算法需要实时从索引数据库中找出所有相关页面,实时计算相关性,加入过滤算法,其复杂程度是外人无法想象的。搜索引擎是当今规模最大、最复杂的计算系统之一。
但是即使最好的搜素引擎在鉴别网页上也还无法与人相比,这就是为什么网站需要搜索引擎优化。没有 SEO 的帮助,搜索引擎常常并不能正确返回最相关、最权威、最有用的信息。
script 通常被放在 header 或者 body 标签中,但位置的不同对于页面的加载效果也不一样。
demo中引用的js文件,都有延迟3秒才执行完成的设定。
1
2 script 加载机制
3
4
5
6
img
预览
你能看到 html 第一时间被加载进来,但页面 body 内容迟迟没有渲染出来。因为在等待 header 标签中 script 脚本的加载,3 秒后,整个页面渲染完成。
1
2 script 加载机制
3
4
5
6
预览
这次 html 内容第一时间渲染完成,随后等待 js 的加载。
脚本会阻塞页面的渲染,所以推荐将其放在 body 底部,因为当解析到 script 标签时,通常页面的大部分内容都已经渲染完成,让用户马上能看到一个非空白页面。
另外你能看到多个脚本之间都是异步向服务器请求,他们之间不互相依赖,最终只等待 3 秒,而非 3+3+3 秒。
产生乱码的原因:
gbk
的编码,而内容中的中文字是utf-8
编码的,这样浏览器打开即会出现html
乱码,反之也会出现乱码;html
网页编码是gbk
,而程序从数据库中调出呈现是utf-8
编码的内容也会造成编码乱码;解决办法:
gbk
,而数据库储存数据编码格式是UTF-8
,此时需要程序查询数据库数据显示数据前进程序转码;1)SVG: SVG可缩放矢量图形(Scalable Vector Graphics)是基于可扩展标记语言XML描述的2D图形的语言,SVG基于XML就意味着SVG DOM中的每个元素都是可用的,可以为某个元素附加Javascript事件处理器。在 SVG 中,每个被绘制的图形均被视为对象。如果 SVG 对象的属性发生变化,那么浏览器能够自动重现图形。
其特点如下:
(2)Canvas: Canvas是画布,通过Javascript来绘制2D图形,是逐像素进行渲染的。其位置发生改变,就会重新进行绘制。
其特点如下:
注:矢量图,也称为面向对象的图像或绘图图像,在数学上定义为一系列由线连接的点。矢量文件中的图形元素称为对象。每个对象都是一个自成一体的实体,它具有颜色、形状、轮廓、大小和屏幕位置等属性。
响应式页面中经常用到根据屏幕密度设置不同的图片。这时就用到了 img 标签的srcset属性。srcset属性用于设置不同屏幕密度下,img 会自动加载不同的图片。用法如下:
1
使用上面的代码,就能实现在屏幕密度为1x的情况下加载image-128.png, 屏幕密度为2x时加载image-256.png。
按照上面的实现,不同的屏幕密度都要设置图片地址,目前的屏幕密度有1x,2x,3x,4x四种,如果每一个图片都设置4张图片,加载就会很慢。所以就有了新的srcset标准。代码如下:
1<img src="image-128.png"
2 srcset="image-128.png 128w, image-256.png 256w, image-512.png 512w"
3 sizes="(max-width: 360px) 340px, 128px" />
其中srcset指定图片的地址和对应的图片质量。sizes用来设置图片的尺寸零界点。对于 srcset 中的 w 单位,可以理解成图片质量。如果可视区域小于这个质量的值,就可以使用。浏览器会自动选择一个最小的可用图片。
sizes语法如下:
1sizes="[media query] [length], [media query] [length] ... "
sizes就是指默认显示128px, 如果视区宽度大于360px, 则显示340px。
离线存储指的是:在用户没有与因特网连接时,可以正常访问站点或应用,在用户与因特网连接时,更新用户机器上的缓存文件。
**原理:**HTML5的离线存储是基于一个新建的 .appcache
文件的缓存机制(不是存储技术),通过这个文件上的解析清单离线存储资源,这些资源就会像cookie一样被存储了下来。之后当网络在处于离线状态下时,浏览器会通过被离线存储的数据进行页面展示
使用方法: (1)创建一个和 html 同名的 manifest 文件,然后在页面头部加入 manifest 属性:
1
(2)在 cache.manifest
文件中编写需要离线存储的资源:
1CACHE MANIFEST
2 #v0.11
3 CACHE:
4 js/app.js
5 css/style.css
6 NETWORK:
7 resourse/logo.png
8 FALLBACK:
9 / /offline.html
(3)在离线状态时,操作 window.applicationCache
进行离线缓存的操作。
如何更新缓存:
(1)更新 manifest 文件
(2)通过 javascript 操作
(3)清除浏览器缓存
注意事项:
(1)浏览器对缓存数据的容量限制可能不太一样(某些浏览器设置的限制是每个站点 5MB)。
(2)如果 manifest 文件,或者内部列举的某一个文件不能正常下载,整个更新过程都将失败,浏览器继续全部使用老的缓存。
(3)引用 manifest 的 html 必须与 manifest 文件同源,在同一个域下。
(4)FALLBACK 中的资源必须和 manifest 文件同源。
(5)当一个资源被缓存后,该浏览器直接请求这个绝对路径也会访问缓存中的资源。
(6)站点中的其他页面即使没有设置 manifest 属性,请求的资源如果在缓存中也从缓存中访问。
(7)当 manifest 文件发生改变时,资源请求本身也会触发更新。
label标签来定义表单控制间的关系。当用户选择该标签时,浏览器会自动将焦点转到和标签相关的表单控件上。
<label for="Name">Number:</label>
<input type='text' name="Name" id="Name"/>
<label>Date:<input type="text" name="B"/></label>
顾名思义,“广播频道”,官方文档里的解释为“用于同源不同页面之间完成通信的功能”,在其中某个页面发送的消息会被其他页面监听到。
注意“同源”二字,该方法无法完成跨域的数据传输。
localStorage是浏览器多个标签共用的存储空间,所以可以用来实现多标签之间的通信(ps:session是会话级的存储空间,每个标签页都是单独的)。
SharedWorker可以被多个window共同使用,但必须保证这些标签页都是同源的(相同的协议,主机和端口号)
全双工(full-duplex)通信自然可以实现多个标签之间的通信
这样做确实可以实现我想要的功能,但是这样的方法相当浪费资源。虽然在这个性能过盛的时代,浪费不浪费也感觉不出来,但是这种实现方案,确实不够优雅。
两个需要交互的tab页面具有依赖关系。
如 A页面中通过JavaScript的window.open打开B页面,或者B页面通过iframe嵌入至A页面,此种情形最简单,可以通过HTML5的 window.postMessage API完成通信,由于postMessage函数是绑定在 window 全局对象下,因此通信的页面中必须有一个页面(如A页面)可以获取另一个页面(如B页面)的window对象,这样才可以完成单向通信;B页面无需获取A页面的window对象,如果需要B页面对A页面的通信,只需要在B页面侦听message事件,获取事件中传递的source对象,该对象即为A页面window对象的引用:
//B页面
window.addEventListner('message',(e)=>{
let {data,source,origin} = e;
source.postMessage('message echo','/');
});
postMessage的第一个参数为消息实体,它是一个结构化对象,即可以通过“JSON.stringify和JSON.parse”函数还原的对象;第二个参数为消息发送范围选择器,设置为“/”意味着只发送消息给同源的页面,设置为“*”则发送全部页面。
可以,通过给input标签设置multiple属性。
<input type="file" name="files" multiple/>
顾名思义,IconFont 就是字体图标。严格地说,就是一种字体,但是,它们不包含字母或数字,而是包含符号和字形。您可以使用 CSS 设置样式,就像设置常规文本一样,这使得 IconFont 成为 Web 开发时图标的热门选择。
即页面浏览量或点击量,用户每1次对网站中的每个网页访问均被记录1个PV。
用户对同一页面的多次访问,访问量累计,用以衡量网站用户访问的网页数量。
是指通过互联网访问、浏览这个网页的自然人。访问您网站的一台电脑客户端为一个访客。
00:00-24:00内相同的客户端只被计算一次。
link属于HTML标签,而@import是css提供的;
页面被加载时,link会同时被加载,而@import引用的css会等到页面被加载完再加载;
@import只在IE5以上才能识别,而link是XHTML标签,无兼容问题;
link方式的样式的权重高于@import的权重。
简单来说,共有以下几个过程:
下面我们来看看具体的细节。
DNS解析实际上就是寻找你所需要的资源的过程。假设你输入www.baidu.com,而这个网址并不是百度的真实地址,互联网中每一台机器都有唯一标识的IP地址,这个才是关键,但是它不好记,乱七八糟一串数字谁记得住啊,所以就需要一个网址和IP地址的转换,也就是DNS解析。
DNS解析其实是一个递归的过程。
输入www.google.com网址后,首先在本地的域名服务器中查找,没找到去根域名服务器查找,没有再去com顶级域名服务器查找,,如此的类推下去,直到找到IP地址,然后把它记录在本地,供下次使用。大致过程就是.-> .com ->google.com. -> www.google.com.。 (最后这个.对应的就是根域名服务器,默认情况下所有的网址的最后一位都是.,为了方便用户,通常都会省略,浏览器在请求DNS的时候会自动加上)
既然已经懂得了解析的具体过程,我们可以看到上述一共经过了N个过程,每个过程有一定的消耗和时间的等待,因此我们得想办法解决一下这个问题!
DNS存在着多级缓存,从离浏览器的距离排序的话,有以下几种: 浏览器缓存,系统缓存,路由器缓存,IPS服务器缓存,根域名服务器缓存,顶级域名服务器缓存,主域名服务器缓存。
比如访问baidu.com的时候,每次响应的并非是同一个服务器(IP地址不同),一般大公司都有成百上千台服务器来支撑访问。DNS可以返回一个合适的机器的IP给用户,例如可以根据每台机器的负载量,该机器离用户地理位置的距离等等,这种过程就是DNS负载均衡。
TCP提供一种可靠的传输,这个过程涉及到三次握手,四次挥手。
预览
客户端发送syn包(Seq=x)到服务器,并进入SYN_SEND状态,等待服务器确认;
服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(Seq=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。
数据传输完毕后,双方都可释放连接。最开始的时候,客户端和服务器都是处于ESTABLISHED状态,假设客户端主动关闭,服务器被动关闭。
预览
客户端发送一个FIN,用来关闭客户端到服务器的数据传送,也就是客户端告诉服务器:我已经不 会再给你发数据了(当然,在fin包之前发送出去的数据,如果没有收到对应的ack确认报文,客户端依然会重发这些数据),但是,此时客户端还可以接受数据。
FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
服务器收到FIN包后,发送一个ACK给对方并且带上自己的序列号seq,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号)。此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
服务器发送一个FIN,用来关闭服务器到客户端的数据传送,也就是告诉客户端,我的数据也发送完了,不会再给你发数据了。由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
至此,完成四次挥手。
发送HTTP请求,就是构建HTTP请求报文,并通过TCP协议,发送到服务器指定端口。
请求报文由请求行
,请求报头
,请求正文
组成。
对TCP连接进行处理,对HTTP协议进行解析,并按照报文格式进一步封装成HTTP Request对象,供上层使用。这一部分工作一般是由Web服务器去进行,比如Tomcat, Nginx和Apache等Web服务器。
HTTP报文也分成三段:状态码
,响应报头
和响应报文
。
预览
这个图就是Webkit解析渲染页面的过程。
整个渲染过程其实就是将URL对应的各种资源,通过浏览器渲染引擎的解析,输出可视化的图像。
浏览器解析html源码,然后创建一个 DOM树。并行请求 css/image/js在DOM树中,每一个HTML标签都有一个对应的节点,并且每一个文本也都会有一个对应的文本节点。DOM树的根节点就是 documentElement,对应的是html标签。
浏览器解析CSS代码,计算出最终的样式数据。构建CSSOM树。对CSS代码中非法的语法它会直接忽略掉。解析CSS的时候会按照如下顺序来定义优先级:
浏览器默认设置 < 用户设置 < 外链样式 < 内联样式 < html中的style。
DOM Tree + CSSOM –> 渲染树(rendering tree)。渲染树和DOM树有点像,但是是有区别的。DOM树完全和html标签一一对应,但是渲染树会忽略掉不需要渲染的元素,比如head、display:none的元素等。而且一大段文本中的每一个行在渲染树中都是独立的一个节点。渲染树中的每一个节点都存储有对应的css属性。
一旦渲染树创建好了,浏览器就可以根据渲染树直接把页面绘制到屏幕上。
以上四个步骤并不是一次性顺序完成的。如果DOM或者CSSOM被修改,以上过程会被重复执行。实际上,CSS和JavaScript往往会多次修改DOM或者CSSOM。
重绘是改变不影响元素在网页中的位置的元素样式时,譬如background-color(背景色), border-color(边框色),visibility(可见性),浏览器会根据元素的新属性重新绘制一次(这就是重绘,或者说重新构造样式),使元素呈现新的外观。
重绘不会带来重新布局,所以并不一定伴随重排。
渲染对象在创建完成并添加到渲染树时,并不包含位置和大小信息。计算这些值的过程称为布局或重排。
“重绘"不一定需要"重排”,比如改变某个网页元素的颜色,就只会触发"重绘",不会触发"重排",因为布局没有改变。
但是,“重排"必然导致"重绘”,比如改变一个网页元素的位置,就会同时触发"重排"和"重绘",因为布局改变了。
浏览器解析 href 不会阻塞对文档的处理(这就是官方建议使用 link 引入而不是 @ import 的原因),src 会阻塞对文档的处理。
在 HTML 中会遇到以下三类 script:
script标签用于加载脚本与执行脚本,直接使用script脚本时,html会按照顺序来加载并执行脚本,在脚本加载&执行的过程中,会阻塞后续的DOM渲染。
比如现在大家习惯于在页面中引用各种第三方脚本,但如果第三方服务商出现了一些小问题,比如延迟之类的,就会使得页面白屏。
针对上述情况,script标签提供了两种方式来解决问题,就是加入属性async以及defer,这两个属性使得script标签加载都不会阻塞DOM的渲染。
defer:此布尔属性被设置为向浏览器指示脚本在文档被解析后执行。
async:设置此布尔属性,以指示浏览器如果可能的话,应异步执行脚本。
如果script标签设置了defer属性,则浏览器会异步下载该文件并且不会影响后续DOM的渲染。
如果有多个设置了defer属性的script标签存在,则会按照顺序执行所有的script,defer脚本会在文档渲染完毕后,DOMContentLoaded事件调用前执行。
async属性会使得script脚本异步的加载并在允许的情况下执行,而async的执行并不会按照script标签在页面中的顺序来执行,而是谁先加载完谁先执行。
先看下什么是HTML:
超文本标记语言(英语:HyperText Markup Language,简称:HTML)是一种用于创建网页的标准标记语言。 HTML元素是构建网站的基石。HTML允许嵌入图像与对象,并且可以用于创建交互式表单,它被用来结构化信息——例如标题、段落和列表等等,也可用来在一定程度上描述文档的外观和语义。
那么如何理解 Web 语义化?
通俗的来讲就是从代码上来展示页面的结构,而不是从最终视觉上来展示结构。
单纯的HTML代码是不带任何样式的只是用来标记这一段是标题、这一块是代码、那一个是要强调的内容等等。
但是为什么我们只写HTML在浏览器中不同的标签也是有不同的样式呢?
那是因为各个浏览器都自带的有相应标签的默认样式,为了方便在没有设定样式的情况下友好的展示页面。
良好的语义化代码可以直接从代码上就能看出来那一块到底是要表达什么内容。
有伙伴会认为,我用DIV+CSS也能做出来一样的效果,虽然单纯看实现效果,两者并没有什么区别。
但是页面不止是给人看的,机器也要看爬虫也要看,网页结构更清晰方便开发维护。
特别是在网络或其他原因页面样式文件丢失的时候,良好语义结构组成的页面,肯定比全是div的页面对用户更友好。
总结下语义化的优点:
## defer
如果script标签设置了defer属性,则浏览器会异步下载该文件并且不会影响后续DOM的渲染。
如果有多个设置了defer属性的script标签存在,则会按照顺序执行所有的script,defer脚本会在文档渲染完毕后,DOMContentLoaded事件调用前执行。
## async
async属性会使得script脚本异步的加载并在允许的情况下执行,而async的执行并不会按照script标签在页面中的顺序来执行,而是谁先加载完谁先执行。
# 34.什么是 HTML 语义化?
先看下什么是HTML:
> 超文本标记语言(英语:HyperText Markup Language,简称:HTML)是一种用于创建网页的标准标记语言。 HTML元素是构建网站的基石。HTML允许嵌入图像与对象,并且可以用于创建交互式表单,它被用来结构化信息——例如标题、段落和列表等等,也可用来在一定程度上描述文档的外观和语义。
那么如何理解 Web 语义化?
通俗的来讲就是从代码上来展示页面的结构,而不是从最终视觉上来展示结构。
单纯的HTML代码是不带任何样式的只是用来标记这一段是标题、这一块是代码、那一个是要强调的内容等等。
但是为什么我们只写HTML在浏览器中不同的标签也是有不同的样式呢?
那是因为各个浏览器都自带的有相应标签的默认样式,为了方便在没有设定样式的情况下友好的展示页面。
良好的语义化代码可以直接从代码上就能看出来那一块到底是要表达什么内容。
## 为什么要使用语义化标签?
有伙伴会认为,我用DIV+CSS也能做出来一样的效果,虽然单纯看实现效果,两者并没有什么区别。
但是页面不止是给人看的,机器也要看爬虫也要看,网页结构更清晰方便开发维护。
特别是在网络或其他原因页面样式文件丢失的时候,良好语义结构组成的页面,肯定比全是div的页面对用户更友好。
总结下语义化的优点:
- 标签语义化有助于构架良好的HTML结构,有利于搜索引擎的建立索引、抓取。简单来说。
- 有利于不同设备的解析(屏幕阅读器,盲人阅读器等)
- 有利于构建清晰的机构,有利于团队的开发、维护