1、从输入 url 到展示的过程
- DNS 解析
- TCP 三次握手
- 发送请求,分析 url,设置请求报文(头,主体)
- 服务器返回请求的文件 (html)
- 浏览器渲染
- HTML parser --> DOM Tree
- 标记化算法,进行元素状态的标记
- dom 树构建
- CSS parser --> Style Tree
- 解析 css 代码,生成样式树
- attachment --> Render Tree
- 结合 dom树 与 style树,生成渲染树
- layout: 布局
- GPU painting: 像素绘制页面
- HTML parser --> DOM Tree
2、重绘和重排的区别
当元素的样式发生变化时,浏览器需要触发更新,重新绘制元素。这个过程中,有两种类型的操作,即重绘与回流。
-
重绘(repaint): 当元素样式的改变不影响布局时,浏览器将使用重绘对元素进行更新,此时由于只需要UI层面的重新像素绘制,因此 损耗较少
-
回流(reflow): 当元素的尺寸、结构或触发某些属性时,浏览器会重新渲染页面,称为回流。此时,浏览器需要重新经过计算,计算后还需要重新页面布局,因此是较重的操作。会触发回流的操作:
- 页面初次渲染
- 浏览器窗口大小改变
- 元素尺寸、位置、内容发生改变
- 元素字体大小变化
- 添加或者删除可见的 dom 元素
- 激活 CSS 伪类(例如::hover)
- 查询某些属性或调用某些方法
- clientWidth、clientHeight、clientTop、clientLeft
- offsetWidth、offsetHeight、offsetTop、offsetLeft
- scrollWidth、scrollHeight、scrollTop、scrollLeft
- getComputedStyle()
- getBoundingClientRect()
- scrollTo()
回流必定触发重绘,重绘不一定触发回流。重绘的开销较小,回流的代价较高。
最佳实践:
-
css
- 避免使用
table
布局 - 将动画效果应用到
position
属性为absolute
或fixed
的元素上
- 避免使用
-
javascript
- 避免频繁操作样式,可汇总后统一 一次修改
- 尽量使用
class
进行样式修改 - 减少
dom
的增删次数,可使用 字符串 或者documentFragment
一次性插入 - 极限优化时,修改样式可将其
display: none
后修改
3、几种请求方法(get和post区别)
-
GET请求用于获取数据。
-
GET请求参数通过URL传递,POST请求参数放在Request body中。
-
GET请求比POS请求更不安全,GET请求的参数直接暴露在URL上,所以不能用来传递敏感信息。
-
GET参数有长度限制(受限于url长度,具体的数值取决于浏览器和服务器的限制,最长2048字节),而POST无限制。
-
POST请求一般用于新增数据.
-
本质上,GET和POST请求都是tcp连接,只是由于http协议规定和浏览器或者服务器的限制,导致他们在应用过程中体现形式不同。
-
GET产生一个TCP数据包;POST产生两个TCP数据包。对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
4、如何解决跨域
CORS
跨域资源共享(CORS,Cross-Origin Resource Sharing)是浏览器为AJAX请求设置的一种跨域机制
JSONP原理
由于浏览器的同源策略限制,不允许跨域请求;但是页面中的 script、img、iframe标签是例外,不受同源策略限制。
Jsonp 就是利用script
标签跨域特性进行请求。
JSONP 的原理就是,先在全局注册一个回调函数,定义回调数据的处理;与服务端约定好一个同名回调函数名,服务端接收到请求后,将返回一段 Javascript,在这段 Javascript 代码中调用了约定好的回调函数,并且将数据作为参数进行传递。当网页接收到这段 Javascript 代码后,就会执行这个回调函数。
JSONP缺点:它只支持GET
请求,而不支持POST
请求等其他类型的HTTP请求。
代理转发
在服务端进行跨域,比如设置代理转发。这种在服务端设置的代理称为“反向代理”,对于用户而言是无感知的。
Nginx代理转发设置:
//nginx.conf文件
server {
# Nginx启动的端口
listen 3000;
server_name localhost;
location ~ ^.*\.(html|js|css|png|gif|jpg|tpl|woff|woff2|tff|map|eot|coffee|exe|pkg)$ {
# 前端打包后文件放的位置
root /weblogic/webapp;
# 设置采用协议缓存
add_header Cache-Control no-cache;
}
# 将 /server-web/ 开头的请求进行转发,转发到proxy_pass设置的IP上
location /server-web/ {
# 转发地址
proxy_pass http://XXXXx;
# 设置采用协议缓存
add_header Cache-Control max-age=no-cache;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
5、V8垃圾回收机制
垃圾回收: 将内存中不再使用的数据进行清理,释放出内存空间。V8 将内存分成 新生代空间 和 老生代空间。
- 新生代空间: 用于存活较短的对象
- 又分成两个空间: from 空间 与 to 空间
- Scavenge GC算法: 当 from 空间被占满时,启动 GC 算法
- 存活的对象从 from space 转移到 to space
- 清空 from space
- from space 与 to space 互换
- 完成一次新生代GC
- 老生代空间: 用于存活时间较长的对象
- 从 新生代空间 转移到 老生代空间 的条件
- 经历过一次以上 Scavenge GC 的对象
- 当 to space 体积超过25%
- 标记清除算法: 标记存活的对象,未被标记的则被释放
- 增量标记: 小模块标记,在代码执行间隙执,GC 会影响性能
- 并发标记(最新技术): 不阻塞 js 执行
- 压缩算法: 将内存中清除后导致的碎片化对象往内存堆的一端移动,解决 内存的碎片化
- 从 新生代空间 转移到 老生代空间 的条件
6 内存泄露
- 意外的全局变量: 无法被回收
- 定时器: 未被正确关闭,导致所引用的外部变量无法被释放
- 事件监听: 没有正确销毁 (低版本浏览器可能出现)
- 闭包: 会导致父级中的变量无法被释放
- dom 引用: dom 元素被删除时,内存中的引用未被正确清空
可用 chrome 中的 timeline 进行内存标记,可视化查看内存的变化情况,找出异常点。
7、存储
我们经常需要对业务中的一些数据进行存储,通常可以分为 短暂性存储 和 持久性储存。
-
短暂性的时候,我们只需要将数据存在内存中,只在运行时可用
-
持久性存储,可以分为 浏览器端 与 服务器端
- 浏览器:
cookie
: 通常用于存储用户身份,登录状态等- http 中自动携带, 体积上限为 4K, 可自行设置过期时间
localStorage / sessionStorage
: 长久储存/窗口关闭删除, 体积限制为 4~5MindexDB
- 服务器:
- 分布式缓存 redis
- 数据库
- 浏览器:
8、浏览器缓存
缓存分为强缓存和协商缓存。强缓存不过服务器,协商缓存需要过服务器,协商缓存返回的状态码是304。两类缓存机制可以同时存在,强缓存的优先级高于协商缓存。当执行强缓存时,如若缓存命中,则直接使用缓存数据库中的数据,不再进行缓存协商。
强缓存(浏览器缓存)
- Expires;http1.0的产物;根据一个绝对时间来确定是否要利用缓存;
- cache-control;http1.1的产物,根据一个相对时间来确定是否利用缓存。主要是利用该字段的 max-age 值来进行判断,它是一个相对时间,例如 Cache-Control:max-age=3600,代表着资源的有效期是 3600 秒。
协商缓存(服务器缓存)
- Last-Modified 和 If-Modified-Since
第一次请求资源从服务器拉取的会自动带上该属性;第二次请求会跟服务端比对If-Modified-Since
的时间,没变动则使用本地的(状态304);结合Expires(过期时间:缓存的载止时间)
,跟随请求一起发出..资源没过期拿本地,否则重新请求
- Etag 和 If-None-Match:
第一次请求url 时候会给服务器上标记(一串字符串);第二次请求时候会比对服务端的If-None-Match
,没有改动依旧拿缓存(304)
更多缓存内容请看前端也要懂Http缓存机制
9、XSS和CSRF区别
- XSS攻击: 注入恶意代码
- cookie 设置 httpOnly
- 转义页面上的输入内容和输出内容
- 破解方法: 编码(将特殊字符串<进行转义)、过滤(移除用户上传DOM属性,如onerror;移除用户上传的style节点、script节点、iframe节点等)
- CSRF: 跨站请求伪造,CSRF攻击:最大的特点就是窃取身份,伪装成网站受信任的用户来发起请求实施攻击。防护:
- get 不修改数据
- 不被第三方网站访问到用户的 cookie
- 设置白名单,不被第三方网站请求
- 请求校验
10、HTTP与HTTPS的区别
- HTTP的URL由
http://
起始且默认使用端口80,而HTTPS的URL由https://
起始且默认使用端口443 - HTTP是超文本传输协议,信息是明文传输,HTTPS则是具有安全性的 SSL 加密传输协议
- HTTP的连接很简单,是无状态的,HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 http 协议安全
11、HTTP状态码
1xx表示客户端应该继续发送请求
2xx表示成功的请求
- 200表示OK,正常返回信息
- 201表示请求成功且服务器创建了新的资源
- 202表示服务器已经接受了请求,但还未处理
3xx表示重定向
- 301表示永久重定向,请求的网页已经永久移动到新位置
- 302表示临时重定向
- 304表示自从上一次请求以来,页面的内容没有改变过
4xx表示客户端错误
- 401表示服务器无法理解请求的格式
- 402表示请求未授权
- 403表示禁止访问
- 404表示请求的资源不存在,一般是路径写错了
5xx表示服务器错误
- 500表示最常见的服务器错误
- 503表示服务器暂时无法处理请求
12、TCP三次握手和四次挥手
1. TCP三次握手
建立连接前,客户端和服务端需要通过握手来确认对方:
- 客户端发送 syn(同步序列编号) 请求,进入 syn_send 状态,等待确认
- 服务端接收并确认 syn 包后发送 syn+ack 包,进入 syn_recv 状态
- 客户端接收 syn+ack 包后,发送 ack 包,双方进入 established 状态
2. TCP四次挥手
- 客户端 -- FIN --> 服务端, FIN—WAIT
- 服务端 -- ACK --> 客户端, CLOSE-WAIT
- 服务端 -- ACK,FIN --> 客户端, LAST-ACK
- 客户端 -- ACK --> 服务端,CLOSED
13、优化这块了解多少?
大体常见的手段了解.
客户端着手
- 压缩代码(JS/CSS),压缩图片
- 合并一些小图片(
css sprite
) - 若是打包的代码尽可能切割成多个
chunk
,减少单一chunk
过大 - 静态文件采用 cdn 引入
- HTTP的缓存头使用的合理
- 减小第三方库的依赖
- 对于代码应该考虑性能来编写,比如使用
requestAnimationFrame
绘制动画,尽可能减少页面重绘(DOM 改变) - 渐进升级,引入
preload
这些预加载资源 - 看情况用
service worker
来缓存资源(比如移动端打算搞 PWA)
服务端着手
- 带宽,域名解析, 多域名解析等
- 页面做服务端渲染,减小对浏览器的依赖(不用客户端解析)
- 渐进升级,比如引入 HTTP2(多路复用,头部压缩这些可以明显加快加载速度)
当然,这是这些都是很片面的点到,实际工作中去开展要复杂的多;
比如我们要多个维度去考虑的话,要去优化 DOM 的绘制时间,资源的加载时间,域名解析这些;
要全面的优化一个项目是一个大工程,
整理自: