2. 八股
约 2840 字大约 9 分钟
2025-06-15
- 命名冲实 后绑定的重名数据系把前面的覆盖
- 安全风险 任何人可以获取和修改。
- 性能问题, 占用的存如果不解绑也不会清除
- 全局污染 任何人都可以获取到也可以修改
解决:模块化、命名空间、IIFE、开启严格模式、qiankun代理沙箱
地址栏输入url回车后发生了什么
1. url检测:纠错、补全、转换
检测url是否有误 如果没有带协议会补全协议 根据协议补全端口(http:80,https:443) 如果不是网址,是个关键词会使用搜索引擎加上关键词在搜索引擎中搜索 如果url中有中文等非ascii字符的话还会转换为ascii码
2. DNS解析
根据url地址先查看本地dns缓存,如果缓存命中则直接访问网址 如果缓存不命中则进行dns解析
3. 建立tcp连接
 如果使用的是https协议还会再进行SSL握手,建立加密信道。使用SSL握手时,会确定是否使用了http2
4. 浏览器自动发送请求
浏览器决定要附带哪些cookie到请求头中 浏览器自动设置好请求头、协议版本、cookie,发出GET请求
5. 服务器处理数据并响应
服务器处理请求,进入后端处理流程。完成处理后,服务器响应一个HTTP报文给浏览器。
6. 浏览器决定是否保留连接
浏览器根据使用的协议版本,以及Connection字段的约定,决定是否要保留TCP连接
如果不需要保留会进行tcp四次挥手
7. 解析状态
根据响应状态码决定如何处理该请求
8. 解析响应头
浏览器根据响应头中的Content-Type字段识别响应类型,比如:html、css、js、图片等资源会做不同的处理
接着会根据请求头中的设置的缓存、cookie等做处理
9. 解析响应体
浏览器开始从上到下解析响应体的内容 如:解析HTML,若遇到外部资源链接,则进一步请求资源
10. 浏览器渲染过程
参照浏览器渲染原理
CSRF攻击
CSRF (Cross-site request forgery,跨站请求伪造) 攻击者利用了用户的身份信息,执行了用户非本意的操作
用户在请求正常的网站时会获取到cookie并保存在本地,后续再次请求该网站就把对应网站的cookie携带过去。 危险网站中的某个资源的链接(不用js执行请求是因为有跨域问题)指向要攻击的网站的请求以及设置请求头中携带的参数(因为是get请求只能使用请求头传参)。用户访问到危险网址时页面渲染到该元素就会发送请求,访问要攻击的网站,而在访问的时候用户本地存有cookie就会携带用户的cookie,而服务器就会误以为是用户在操作
防御方式
不使用cookie 防御力高,兼容性略差。ssr会遇到困难,但可解决
使用sameSite 防御力较高。兼容性差。容易挡住自己人
即使将敏感操作使用post请求也还是可以攻击到: 在页面中放一个表单,表单中填入网站和参数,使用表单也是可以发送post请求的。但是这样会跳转到目标页面,用户会看到,可以使用iframe标签包裹,这样只会在iframe标签中跳转,将iframe标签设为不可见用户就看不到了
sameSite是一个请求头的字段,该字段有三个取值:
- none:无作用
- sameSite-Strict:严格模式,只有源网站和请求的网址都一致(和cookie所属的网站一致)才会携带cookie。但这样会阻挡其他正常网站的访问
- sameSite-Lax:只有get请求才会携带cookie,post请求不会携带cookie
- csrf token 防御力高,获取到token后未进行操作仍然会被攻击
用户请求服务器时,服务器会生成一个随机的token发送给用户(只有通过自己的网站访问才会使用这个token),且该token只能使用一次,并将该token保存在服务器上。当用户进行操作时会携带该token。如果不是自己的网站会使用保存的token就无法通过验证。使用后这个token就失效了
但用户获取到一次性toeken后再次发送请求还没有到达服务器,而在这期间又访问了危险网址,危险网站的请求先自己的请求到达服务器就也无法成功防护
- referer防护 防御力低,过去很常用,现在已经发现漏洞
请求头中携带referer字段(和origin字段很像都保存请求的源网站),如果referer的源网址不在服务器的白名单内就拒绝访问
但是将恶意代码使用base64编码后可以绕过
XSS攻击
XSS(Cross Site Scripting,跨站脚本攻击),攻击者利用站点的漏洞,表单提交 时,在表单内容中加入一些恶意脚本,当其他正常用户浏览页面,而页面中刚好出现攻击者的恶意脚本时,脚本被执行,从而使得页面遭到破坏,或者用户信息被窃取。 攻击者在正常的网址中发布所有人都可以访问的内容,如:文章。在写文章时在里面加入script等危险的标签,并在里面设置脚本代码。将该文件提交给服务器,服务器保存下来。正常用户访问时就会将这些内容发送给用户,用户浏览器渲染时就会将script标签中包裹的脚本执行
防御方式
服务器端对用户提交的内容进行过滤或编码
- 过滤:去掉一些危险的标签,去掉一些危险的属性 由于前端如果过滤的话还有可能被篡改,或者发送未经过滤的标签,所以还需要后端处理。与其处理两次不如直接让后端处理
- 编码:标签进行HTML实体编码
<srcipt>...</script>
编码后浏览器就不会识别成srcipt标签了,而是直接当成文本展现
网络性能优化
- 优化打包体积 利用一些工具压缩、混淆最终打包代码,减少包体积
- 多目标打包 利用一些打包插件,针对不同的浏览器打包出不同的兼容性版本,这样一来,每个版本中的兼容性代码就会大大减少,从而减少包体积
- 压缩 现代浏览器普遍支持压缩格式,因此服务端的各种文件可以压缩后再响应给客户端,只要解压时间小于优化的传输时间,压缩就是可行的
- CDN 利用CDN可以大幅缩减静态资源的访问时间,特别是对于公共库的访问,可以使用知名的CDN资源,这样可以实现跨越站点的缓存
- 缓存 对于除HTML外的所有静态资源均可以开启协商缓存,利用构建工具打包产生的文件hash值来置换缓存
- http2 开启http2后,利用其多路复用、头部压缩等特点,充分利用带宽传递大量的文件数据
- 雪碧图 对于不使用HTTP2的场景,可以将多个图片合并为雪碧图,以达到减少文件的目的
- defer、async 通过defer和async属性,可以让页面尽早加载js文件
- prefetch、preload 通过prefetch属性,可以让页面在空闲时预先下载其他页面可能要用到的资源 通过preload属性,可以让页面预先下载本页面可能要用到的资源
- 多个静态资源域 将相对独立的静态资源分到多个域中保存,可以让浏览器同时开启多个TCP连接,并行下载
WebSocket
短轮询
每隔一段时间就给服务器发送一下请求,服务器收到后响应结果 缺点:
- 会产生大量无意义的请求
- 会频打开关闭连接
长轮询
服务器收到请求后会先不响应,等一段时间后查看是否有结果,如果有结果就响应给客户端,客户端可能拿到结果。如果没结果就返回没有结果的响应,客户端收到后就会进行下一次轮询 长轮询有效的解决了话痨问题」,让每一次请求和响应都是有意义的
缺点:
- 客户端长时间收不到购应会会导致超时,从而主动断开和服务器的连接 这种情况是可以处理的,但ajax请求因为超时而结束时,立即重新发送请求到服务器。虽然这种做法会让之前的请求变得无意义,但毕竟比短轮询好多了
- 由于客户端可能「过早的」请求了服务器,服务器不得不挂起这个请求直到新消息的出现。这会让服务器长时间的占用资源却没什么实际的事情可做
WebSocket
WebSocket也是建立在TCP协议之上的,利用的是TCP全双工通信的能力 使用WebSocket,会经历两个阶段:握手阶段、通信阶段
虽然优于轮询方案,但WebSocket仍然是有缺点的:
- 兼容性 WebSocket是HTML5新增的内容,因此古董版本的浏览器并不支持
- 维持TCP连接需要耗费资源 对于那些消息量少的场景,维持TCP连接确实会造成资源的浪费
当客户端需要和服务器使用WebSocket进行通信时,首先会使用HTTP协议完成一次特殊的请求-响应,这一次请求-响应就是WebSocket握手
- 创建连接
let ws=new WebSocket('ws://localhost:8080')
- 设置回调函数
ws.onopen=()=>{
// 连接成功触发
}
ws.onmessage=(e)=>{
// 收到服务器的消息后触发
}
ws.onclose=()=>{
// 连接关闭后触发
}
- 发送消息
ws.send('msg')
实例的readyState属性可以获取到连接状态
- 0:正在连接
- 1:已连接
- 2:正在关闭
- 3:已关闭
npm安装机制
- npm会检查本地的node_modules目录中是否已经安装过该模块,如果已经安装,则不再重新安装
- npm检查缓存中是否有相同的模块,如果有,直接从缓存中读取安装
- 如果本地和缓存中均不存在,npm会从registry指定的地址下载安装包,然后将其写入到本地的node_modules目录中,同时缓存起来。
贡献者
版权所有
版权归属:PinkDopeyBug