客户端与服务器端交互处理
面试题:当用户在地址栏输入网址,到最后看到页面,都经历了什么?
1. URL地址解析
A:URI/URL/URN
URI 统一资源标识符
URL 统一资源定位符
URN 统一资源名称
B:一个完整URI的组成部分和实际意义
- 协议:http、https、ftp
- 域名:顶级域名、一级域名、二级域名、常用域名的行政
- 端口号:80、443、27017、端口号范围
- 请求资源路径名称:伪URL
- 问号参数
- hash值
C:特殊字符加密和解密
- encodeURI/decodeURI
- encodeURIComponent/decodeURIComponent
- escape/unescape
2. DNS域名解析
A:DNS域名是什么
- 发布站点时配置域名解析
- 网址访问进行DNS域名反解析
B:DNS prefetch DNS预获取
- 减少dns的请求次数
- 进行dns预获取
1
2
3
4
5<meta http-equiv="x-dns-prefetch-control" content="on">
<link rel="dns-prefetch" href="//static.360buy.com">
<link rel="dns-prefetch" href="//misx.360buy.com">
<link rel="dns-prefetch" href="//test.360buy.com">
<link rel="dns-prefetch" href="//assets.resource.com"> - 缓存的时间在一分钟左右
3. 建立TCP连接(三次握手)
- 第一次握手:由浏览器发起,告诉服务器我要发送请求了
- 第二次握手:由服务器发起,告诉浏览器我准备接受了,你赶紧发送吧
- 第三次握手:由浏览器发送,告诉服务器,我马上就要发了,准备接受吧
4. 发送HTTP请求
A:HTTP请求报文
- 请求行
- 请求头(首部)
- 请求主体
B:强缓存和协商缓存
- 强缓存(Cache-Control、Expires)
- 协商缓存(Last-Modified、Etag)
5. 服务器得到并处理请求
A:WEB(图片)服务器和数据服务器
- Tomcat
- NGINX
- Apache
- IIS
- …
B:HTTP响应报文
- 响应状态码
- 200 / 201 /204
- 301 / 302 / 304 / 307
- 400 / 401 / 404
- 500 / 503
- 响应头(首部)
- 响应主体
6. 客户端渲染页面
A:浏览器渲染页面的步骤
- 解析HTML,生成DOM树;解析css,生成CSSDOM树
- 将DOM树和CSSOM树结合,生成渲染树(Render Tree)
- Layout(回流):根据生成的渲染树,计算它们在设备视口(viewport)内的确切位置和大小,这个阶段是回流
- Painting(重绘):根据渲染树以及回流得到的几何信息,得到节点的绝对像素
- Display:将像素发送给GPU,展示在页面上
B:DOM的重绘和回流
- 重绘repaint:元素样式的改变(但宽高、大小、位置等不变);如outline、visibility、color、background-color等
- 回流/重排reflow:元素的大小或位置发生了变化(当页面信息和几何布局发生变化的时候),触发了重新布局,导致渲染树重新计算布局和渲染;如添加或删除可见的DOM元素;元素的位置发生变化;元素的尺寸发生变化;内容发生变化(比如文本变化或图片被另一个不同尺寸的图片所代替);页面一开始渲染的时候(这个无法避免);因为回流是根据视口的大小来计算元素位置和大小的,所以浏览器窗口尺寸变化也会引发回流…
- 注意:回流一定会触发重绘,而重绘不一定触发回流
C:前端性能优化之:避免DOM的回流
- 放弃传递操作dom的时代,基于vue/react开始数据影响试图模式
- mvvm / mvc / virtual dom / dom diff
- 分离读写操作(现代浏览器都有渲染队列的机制)
- offsetTop、offsetLeft、offsetWidth、offsetHeight、clientTop、clientLeft、clientWidth、clientHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、getComputedStyle、currentStyle…会刷新渲染队列
- 样式集中改变
box.style.csstext = 'width:100px,height:100px;'
div.className = 'box'
- 缓存布局信息
div.style.left = div.offsetLeft + 1 + 'px'; div.style.top = div.offsetTop + 1 + 'px'
改为1
2
3
4var curLeft = div.offsetLeft
var curTop = div.offsetTop
div.style.left = curLeft + 1 + 'px'
div.style.top = curTop + 1 + 'px'
- 元素批量修改
- 文档碎片:createDocumentFragment
- 模板字符串拼接
- 动画效果应用到position属性为absolute或fixed的元素上(脱离文档流)
- css3硬件加速(GPU加速)
- 比起考虑如何减少回流重绘,我们更期望的是,根本不需要回流重绘;transform / opacity / filters … 这些属性会触发硬件加速,不会引发回流和重绘
- 可能会引发的坑:过多使用会占用大量内存,性能消耗严重,有时候会导致字体模糊
- 牺牲平滑度换取速度
- 每次1像素移动一个动画,但是如果这个动画使用了100%的CPU,动画看上去就会是跳动的,因为浏览器正在与更新回流作斗争。每次移动3px可能看起来平滑度低了,但它不会导致CPU在较慢的机器中产生抖动
- 避免table布局和使用css的JavaScript表达式
7. 断开连接(四次挥手)
- 第一次挥手:由浏览器发起,发送给服务器,我请求报文发送完了,你准备关闭吧
- 第二次挥手:由服务器发起,告诉浏览器,我接受完请求报文了,我准备关闭,你也准备吧
- 第三次挥手:由服务器发起,告诉浏览器,我响应报文发送完毕, 你准备关闭吧
- 第四次挥手:由浏览器发起,告诉服务器,我响应报文接收完毕,我准备关闭,你也准备吧
A:Connection:Keep-Alive 保持TCP不中断
前端性能优化汇总
1.减少HTTP请求次数和请求的大小
- 文件合并压缩
- 雪碧图 css sprite
- 图片base64
- 尽量使用字体图标
- 图片懒加载
- 音视频取消预加载
- 在客户端和服务端进行信息交互的时候,对于多项数据我们尽可能基于json格式来进行传送(json格式的数据处理方便,资源偏小)
- 开起服务器端的gzip压缩
2.建立缓存机制
- DNS解析
- 数据缓存(例如:本地缓存)
- 强缓存和协商缓存(304)
- 离线缓存
- 做CDN加速
3.代码上的优化
- 减少DOM的重绘和回流
- 在js中尽量减少闭包的使用