# 有没有了解HTTP的缓存
- 硬性缓存是对比的哪个header值?
- 说一下什么是协商缓存?协商缓存会在什么时候读?
- 有没有了解资源的缓存策略?html、css、js的缓存怎么设置?
链接:前端缓存相关
html、css、js的缓存:不缓存html,只缓存js和css,因为css,js文件有hash值,但是html文件没有,html如果不更新,那么我们在指定时间内永远没法取到更新后的js和css值。
# fetch发送2次请求的原因
跨源资源共享(Cross-Origin Resource Sharing,CORS)是一种机制,允许在受控的条件下,不同源的网页能够请求和共享资源。由于浏览器的同源策略限制了跨域请求,CORS提供了一种方式来解决在Web应用中进行跨域数据交换的问题。
CORS的基本思想是,服务器在响应中提供一个标头(HTTP头),指示哪些源被允许访问资源。浏览器在发起跨域请求时会先发送一个预检请求(OPTIONS请求)到服务器,服务器通过设置适当的CORS标头来指定是否允许跨域请求,并指定允许的请求源、方法、标头等信息。
不会触发CORS预检请求。这样的请求为简单请求。若请求满足所有下述条件,则该请求可视为简单请求:
- HTTP方法限制:只能使用GET、HEAD、POST这三种HTTP方法之一。如果请求使用了其他HTTP方法,就不再被视为简单请求。
- 自定义标头限制:请求的HTTP标头只能是以下几种常见的标头:Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type(仅限于application/x-www-form-urlencoded、multipart/form-data、text/plain)。HTML头部header field字段:DPR、Download、Save-Data、Viewport-Width、WIdth。如果请求使用了其他标头,同样不再被视为简单请求。
- 请求中没有使用ReadableStream对象。
- 不使用自定义请求标头:请求不能包含用户自定义的标头。
- 请求中的任意XMLHttpRequestUpload对象均没有注册任何事件监听器;XMLHttpRequestUpload对象可以使用XMLHttpRequest.upload属性访问。
因此非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为预检请求。需预检的请求要求必须首先使用OPTIONS方法发起一个预检请求到服务器(第一次状态码是204),以获知服务器是否允许该实际请求。
- 预检请求是在进行跨域资源共享CORS时,由浏览器自动发起的一种OPTIONS请求。它的存在是为了保障安全,并允许服务器决定是否允许跨域请求。
- 跨域请求是指在浏览器中向不同域名、不同端口或不同协议的资源发送请求。出于安全原因,浏览器默认禁止跨域请求,只允许同源策略。而当网页需要进行跨域请求时,浏览器会自动发送一个预检请求,以确定是否服务器允许实际的跨域请求。
- 预检请求中包含了一些额外的头部信息,如Origin和Access-Control-Request-Method等,用于告知服务器实际请求的方法和来源。服务器收到预检请求后,可以根据这些头部信息,进行验证和授权判断。如果服务器认可该跨域请求,将返回一个包含Access-Control-Allow-Origin等头部信息的响应,浏览器才会继续发送实际的跨域请求。
- 使用预检请求机制可以有效地防范跨域请求带来的安全风险,保护用户数据和隐私。
# HTTPS协议是如何保证安全的
# 浏览器的核心进程和线程
- 浏览器进程:浏览器的主进程(负责协调、主控),只有一个,负责浏览器主界面、用户加护、子进程管理等。
- 网络进程:负责加载网络资源。内部会启动多个线程来处理不同的网络任务。
- 浏览器渲染进程(内核(Renderer进程)):默认每个Tab页面一个进程,互不影响,控制页面渲染,脚本执行,事件处理等(有时候会优化,如多个空白tab会合并成一个进程),启动后会默认开启一个渲染主线程。
- 第三方插件进程:每种类型的插件对应一个进程,仅当使用该插件时才创建。
- GPU进程:最多一个,用于3D绘制。
浏览器通常由以下常驻线程组成:
- GUI渲染主线程:负责渲染浏览器界面,解析HTML,CSS,构建DOM树和RenderObject树,布局和绘制等。当界面需要重绘(Repaint)或由于某种操作引发回流(Reflow)时,该线程就会执行。注意,GUI渲染线程与JS引擎线程是互斥的。当JS引擎执行时GUI线程会被挂起(相当于被冻结了),GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。
- 事件触发线程:归属于浏览器而不是JS引擎,用来控制事件循环。当对应的事件符合触发条件被触发时,该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理。注意,由于JS的单线程关系,所以这些待处理队列中的事件都得排队等待JS引擎处理(当JS引擎空闲时才会去执行)。
- 定时器线程:setInterval与setTimeout所在线程。浏览器定时计数器并不是由JS引擎计数的,因为JS引擎是单线程的,如果处于阻塞线程状态就会影响记计时的准确,因此通过单独线程来计时并触发定时是更为合理的方案。
- JS引擎线程:也称为JS内核,负责处理Javascript脚本程序。(例如V8引擎)。JS引擎线程负责解析Javascript脚本,运行代码。
- 网络请求线程:在XMLHttpRequest在连接后是通过浏览器新开一个线程请求。将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中。再由JavaScript引擎执行。
# 性能优化方式有哪些
HTML&CSS
- 减少DOM数量,减轻浏览器渲染计算负担。
- 使用异步和延迟加载js文件,避免js文件阻塞页面渲染。
- 压缩HTML、CSS代码体积,删除不要的代码,合并CSS文件,减少HTTP请求次数和请求大小。
- 减少CSS选择器的复杂程度,复杂度越高浏览器解析时间越长。
- 避免使用CSS表达式在javascript代码中。
- 使用css渲染合成层如
transform、opacity、will-change等,提高页面相应速度减少卡顿现象。动画使用CSS3过渡,减少动画复杂度,如使用transform和opacity来实现动画,不要使用left和top属性。 - 合并icon到雪碧图,小图片转Base64。
JS
- 减少DOM操作或者尽量缓存DOM查找,查找器尽量简洁。
- 避免使用
with语句、eval函数,避免引擎难以优化。 - 尽量使用原生方法,执行效率高。
- 将js文件放到文件页面底部,避免阻塞页面渲染。
- 使用事件委托,减少事件绑定次数。
- 合理使用缓存,避免重复请求数据。
- 动画尽量使用在绝对定位或固定定位的元素上,隐藏在屏幕外,或在页面滚动时,尽量停止动画。
- 图片懒加载,虚拟列表。
Vue
- 合理使用
watch和computed,数据变化就会执行,避免使用太多,减少不必要的开销。 - 合理使用组件,提高代码可维护性的同时也会降低代码组件的耦合性。
- 使用路由懒加载,在需要的时候才会进行加载,避免一次性加载太多路由,导致页面阻塞。
- 使用Vuex缓存数据。
- 合理使用
mixins,抽离公共代码封装成模块,避免重复代码。 - 合理使用
v-if、v-show。 v-for不要和v-if一起使用,v-for的优先级会比v-if高。v-for中不要用index做key,要保证key的唯一性。- 使用异步组件,避免一次性加载太多组件。
- 避免使用
v-html,存在安全问风险和性能问题,可以使用v-text。 - 使用
keep-alive缓存组件,避免组件重复加载。
- 合理使用
React
- 合理使用
PureComponent、shouldComponentUpdate、React.memo跳过不必要的组件更新。 useMemo、useCallback实现稳定的props值,避免使用内联函数,防止传给子组件的props每次都是新的引用。- 状态下放,缩小状态影响范围。
- 列表项使用
key属性。 - 动画库直接修改DOM属性,动画启动后,每次动画属性改变不会引起组件重新Render,而是直接修改了DOM上相关属性值。
- 使用
<Fragment>组件避免额外标记。 - 懒加载组件:
React.lazy(() => import())+Suspense。 - 服务端渲染。
- 合理使用
Webpack优化
- 压缩代码体积。
- 优化静态资源,使用字体图标、雪碧图、webp格式的图片、svg图标等。
- 代码切割,使用SplitChunksPlugin配置
optimization.splitChunks将代码进行分割,避免将所有代码打包到一个文件,减少响应体积。 - 内联代码到html文件中。使用InlineChunkHtmlPlugin。
- 按需加载代码,在使用使用的时候加载代码。
- 使用Tree Shaking删除未被引用的代码(在生产模式下才有效):
optimization { usedExports: true }:通过标记某些函数是否被使用,之后通过Terser来进行优化的。被标记为unused的代码会被Terser插件移除。sideEffects(是在package.json中配置):标记模块是否有副作用。更为有效,是因为它允许跳过整个模块/文件和整个文件子树。
网络优化
- 使用HTTP/2(升级nginx版本并配置:
listen 443 ssl http2;)。 - 减少、合并HTTP请求,通过合并CSS、JS文件、精灵图等方式减少请求数量。
- 压缩文件,开启nginx,Gzip对静态资源压缩。
- 使用HTTP缓存,如强缓存、协商缓存。
- 使用CDN,将网站资源分布到各地服务器上,减少访问延迟。
- 涉及多域名的网站,可以开启域名预解析。
- 使用HTTP/2(升级nginx版本并配置:
性能指标:
- TTFB:从资源的请求到响应第一个字节的时间跨度。
- FP:用户发起请求到浏览器开始渲染页面内第一个像素点所经过的时间(白屏时间)。
- FCP:页面从开始加载到页面内容的任何部分在屏幕上完成渲染的时间(首次内容绘制)。
- LCP:页面中最大的内容完成绘制的时间(最大内容渲染时间)。
- TTI:页面从加载资源到页面渲染,最早可以与用户进行完全可交互的时间,也可以用来描述页面的响应快慢,如果TTI过长容易被用户将页面当成已失败处理(最早可交互时间)。
- DCL:当HTML文档被完全加载和解析完成之后,DOMContentLoaded事件被触发,无需等待样式,图像和子框架的完成加载的时间。