1.从输入url到显示页面,都经历了什么?
1、DNS解析,将域名解析成IP地址:
依次查找:浏览器DNS缓存,操作系统DNS缓存,路由器DNS缓存,网络运营商DNS缓存。如果都没有,会从DNS域名系统中获取IP地址。
2、获取IP地址后, 向服务器发起tcp连接,tcp三次握手。
3、向服务器发送http请求。
4、服务器处理收到的请求,返回 HTTP
报文。
5、浏览器收到HTTP响应之后,读取页面内容,解析html代码。
6、TCP四次挥手
2. DNS是什么?
DNS是一个域名系统(Domain Name System), 是一个将域名和IP地址相互映射的分布式数据库,能够使人们更方便的访问互联网,而不用去记住IP地址。
3.TCP是什么?TCP请求分为哪三个部分:
TCP是传输控制协议,是互联网连接协议集的一种。
三个部分:TCP三次握手、http请求响应、TCP四次挥手
三次握手原因:防止已失效的请求报文段传送到服务端,从而产生错误。
三次握手:
第一次握手,由浏览器发起,告诉服务器我要发送请求了
第二次握手,由服务器发起,告诉浏览器我可以接收,你发送吧。
第三次握手,由浏览器发送,告诉服务器,我现在就开始发,准备接收吧。
四次挥手:
第一次挥手:浏览器发送给服务器,我请求报文发完了。
第二次挥手:服务器告诉浏览器,我接收完了。
第三次挥手:服务器告诉浏览器,我响应报文发送完了,你准备关闭吧。
第四次挥手:浏览器告诉服务器,我接收完了,要关闭了,你也关闭吧。
4.http、http2、https是什么?有何区别?
http(HyperText Transfer Protocol)是基于TCP协议的超文本传输协议,就是一种发送和接收HTML文件的方法。http是以文本格式传输的,且传输内容都是明文,没有经过任何加密,客户端和服务器端都无法验证对方的身份。如果攻击者截取了浏览器和服务器之间的传输报文,就可以直接读懂其中的信息,因此,http协议不适合传输一些敏感信息。
HTTP2是超文本传输协议2.0,它没有改动http的语义、方法、状态码、URI及首部字段等等,它在核心概念上一如往常。它致力于突破上一代标准的性能限制,改进传输性能,实现低延迟和高吞吐量。它新增了二进制分帧层,不再以文本格式传输,它将所有传输的信息分割为更小的消息和帧,并对它们采用二进制格式的编码。http2可以多路复用,它可以用同一个连接传输多个资源,进而使得以前在http1上所做一些优化就没有必要了,如:(使用雪碧图技术,把多张小图合成一张大图,减少请求数;合并JS和CSS,减少请求数)。HTTP2仍采用未加密的传输模式,这容易导致数据在传输过程中被截取或篡改,不能保证数据的完整性。
https是HTTP协议的安全版本,基于SSL协议(也叫TLS协议)。SSL运行在TCP之上,对整个通信线路进行了加密,防止内容被窃听、篡改或伪装。
5. 有状态协议与无状态协议
无状态协议的上一次请求和下一次请求之间没有任何关联,有状态协议的每次网络请求之间是相互联系的。
例:http协议是无状态协议,下一次http请求与上一次的http请求没有任何关系,是相互独立的。TCP是有状态的协议,TCP下一次传输的报文段和上一次传输的报文段是有顺序关系的,最终要按照报文段里的序列号对所有报文段进行重新排序。
6.常见http状态码
100 (继续) 服务器已收到请求的一部分,正在等待其余部分。
200 (成功) 服务器已成功处理了请求,这表示服务器成功返回了请求数据。
301 (永久移动) 请求的网页已永久移动到新位置。服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。
302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
304 (未修改) 自从上次请求后,请求的网页未修改过。服务器返回此响应时,表示使用缓存, 不会返回内容。
403 (禁止) 服务器拒绝请求。
404 (未找到) 服务器找不到请求的网页。
500 (服务器内部错误) 服务器遇到错误,无法完成请求,一般是后端代码有误。
502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。
503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。通常,这只是暂时状态。
504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。
7. 301和302重定向
301是永久重定向,将旧网页永久导向新网页。301跳转会把页面流量和页面权重都导向新页面。搜索引擎会认为旧网页已经不复存在,会移除其收录,旧网页也会失去排名。
302是临时重定向,将网页暂时转移到其他页面。302跳转仅将旧网页的流量移转到新网页,并不会移转页面权重。因此使用302跳转时,旧网页并不会被移除收录以及失去排名。
if ($host != ‘abc.com’) {
rewrite ^/(.*)$ http://www.abc.com/$1 permanent; // 301重定向
}
f ($host != ‘abc.me’) {
rewrite ^/(.*)$ http://www.abc.com/$1 redirect; // 302重定向
}
8.常见http请求头
Content-Type,发送post请求时经常用到,用于设置参数的数据类型。
Pragma:指定“no-cache”值表示服务器必须返回一个刷新后的文档。
Cache-Control:指定请求和响应遵循的缓存机制。
Cache-Control: no-cache 所有内容都不会被缓存
Cache-Control: no-store 用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存。
9.一次http请求一般哪些地方会有缓存处理?
浏览器缓存,操纵系统DNS缓存,cdn缓存(服务器缓)。
10.浏览器缓存怎么解决?
1.设置meta标签禁止缓存
<meta http-equiv="Pragma" content="no-cache">禁止浏览器读取本地缓存
<meta http-equiv="Cache-Control" content="no-cache">指定请求和响应的缓存机制
<meta http-equiv="Expires" content="0">设定网页的到期时间
2.给静态资源文件设置版本号
3.在服务器端配置
add_header Cache-Control no-cache;
add_header Pragma no-cache;
expires -1d;
etag on;
access_log on;
11.浏览器是如何渲染页面的?
1.解析HTML文件,创建DOM树。
自上而下深度遍历dom树,当前节点的所有子节点都构建好之后, 才会去构建当前节点的下一个兄弟节点。遇到任何js文件和内部css样式都会阻塞,外部样式不阻塞。因此,最好使用外部样式, js文件不管内部外部的都阻塞, 最好把js放到文档的最下方。
2.解析CSS
优先级:浏览器默认样式 < 外部或内部样式 < 内联样式
3.将CSS与DOM合并,构建渲染树(Render Tree)。
4.遍历render树,绘制每个节点。
注意: 上述过程是逐步完成的,为了更好的用户体验,渲染引擎会尽可能早的将内容呈现到屏幕上, 并不会等到所有的html都解析完成之后再去构建和布局渲染树。它是解析完一部分内容就显示一部分内容。
12.web开发中常见的漏洞有哪些?
1、sql注入
提交数据时注入非法SQL语句。解决方案一般是增加SQL过滤器,检测前端传过来的内容是否含有非法字符。
2、校验逻辑放到前端
所有的校验逻辑,尽可能的放到后台验证,前端的任何校验都是有可能被绕过的。
3、攻击短信验证码接口,模拟用户注册,频繁的攻击短信发送接口。
解决方案:
1.对同一手机号,同一IP地址的请求进行次数限制。
2.在请求发送验证码之前,需要用户先输入图片验证码,验证码校验成功后(切记,要在后台校验),再发送短信验证码,这样攻击者就需要一定的攻击成本。
4、XSS跨站脚本注入
提交数据时注入非法代码(如:js代码),解决办法与防止SQL注入类似,对于用户提交的数据进行检测。
5、大量请求压力
向服务器发送超大量的请求,对服务器会造成一定的压力甚至瘫痪。
一般服务器都应该对承受的能力有一个预估,然后在硬件或者软件层做并发控制。防止出现此此种情况。
6、验证码爆破
一般是通过爆破的方式,碰撞用户收到的真实手机验证码。目前验证码一般是4位~5位,一般的爆破工具,几分钟就可以试完。解决方案比较简单,对于同一手机号,尝试次数大于几次之后,验证码自动失效。
7、CSRF漏洞(跨站请求伪造)
举一个例子:
受害者Bob有一笔存款,通过对银行的接口(/withdraw?account=bob&amount=1000000&for=bob)发送请求,可以使Bob 把1000000转给bob2。通常情况下,该请求发送到网站后,服务器会验证该请求是否来自一个合法的session,并且该session的用户Bob已经成功登录。黑客Mallory知道上文中的URL可以把钱进行转帐操作,Mallory可以自己发送一个请求给银行:/withdraw?account=bob& amount=1000000&for=Mallory。但是这个请求来自Mallory而非Bob,他不能通过安全认证,因此该请求不会起作用。这时,Mallory想到使用CSRF的攻击方式,他先自己做一个网站,在网站中放入如下代码:src=”http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory”,并且通过广告等诱使Bob来访问他的网站。当Bob访问该网站时,上述url就会从Bob的浏览器发向银行,而这个请求会附带Bob浏览器中的cookie一起发向银行服务器。大多数情况下,该请求会失败,因为他要求Bob的认证信息。但是,如果Bob当时恰巧刚访问他的银行后不久,他的浏览器与银行网站之间的session尚未过期,浏览器的cookie之中含有Bob的认证信息。这时,悲剧发生了,这个url请求就会得到响应,钱将从Bob的账号转移到Mallory的账号,而Bob当时毫不知情。等以后Bob发现账户钱少了,即使他去银行查询日志,他也只能发现确实有一个来自于他本人的合法请求转移了资金,没有任何被攻击的痕迹。而Mallory则可以拿到钱后逍遥法外。
8、权限控制漏洞
一般网站需要有一个完善的权限管理体系,理论上应该对所有的URL路径都进行权限控制,千万不要以为页面没有入口,就不能访问了。
13.前端方面做过哪些加密?
1.js内置加密方法
escape/unescape
encodeURIComponent/decodeURIComponent
2.md5加密
import md5 from 'js-md5';
md5('中文'); // a7bac2239fcdcb3a067903d8077c4a07
3.base64加密
import { Base64 } from 'js-base64';
Base64.encode('dankogai'); // ZGFua29nYWk=
Base64.encode('小飼弾'); // 5bCP6aO85by+
Base64.decode('ZGFua29nYWk='); // dankogai
Base64.decode('5bCP6aO85by+'); // 小飼弾
14. 什么是HTML5 Plus?
HTML5 Plus指的是HTML5加原生APP,是基于HTML、JS、CSS编写运行于手机端的App。这种App可以通过扩展的JS API任意调用手机的原生能力,实现与原生App同样强大的功能和性能。
plus不能在浏览器环境下使用,必须在手机APP上才能使用,因为它操控的是APP原生功能。开发H5+ App可以使用MUI框架,MUI是Dcloud官方推出的一个基于html5+标准的框架,同时拥有h5组件和原生组件,是最接近原生APP体验的高性能前端框架。
15. pc端与移动端适配方案?
1) 响应式
做一个响应式的页面,用媒体查询来控制样式。
2) 做两套页面
打开页面时根据视口宽度跳转到不同的页面。
16.XML、HTML、XHTML的区别?
XML指可扩展标记语言(EXtensible Markup Language), 类似于HTML, 不过HTML是用来显示数据的, XML是用来传输和存储数据的。
HTML是超文本标记语言,是基本的WEB网页设计语言;XHTML是HTML更严格、更纯净的版本。XHTML对于HTML,就相当于ts对于js,只不过XHTML可以直接在浏览器上运行,而ts是js的预编译语言,ts不能直接在浏览器上运行。XHTML的表现方式与HTML类似,不过语法更加严格:
1)HTML标签不区分大小写, XHTML所有标签都必须小写。
2)XHTML标签必须成双成对出现, 必须拥有根元素,所有属性都必须使用双引号。
3)html对标签顺序要求不严格,XHTML标签顺序要求严格, 必须被正确地嵌套。
17.xml和json的区别?
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。JSON是JS对象的字符串表示法,它使用文本表示一个JS对象的信息,本质是一个字符串。它与js交互更加方便,容易阅读和解析处理。数据体积小,传递速度更快些。
XML对数据描述性比较好。
18.你做过哪些性能优化?
按需引入第三方库,或不打包第三方库,通过cnd引入
路由懒加载:借助import()实现
提取公共代码
无限滚动或分页,先渲染一个屏幕范围内的东西
减少页面回流
开启gzip压缩
骨架屏
使用服务端渲染ssr
图片性能优化:
1)使用webp格式;小图采用base64编码注入html中、雪碧图,减少http请求。
2)如果对色彩要求不高, 可以使用svg格式的图片。
3)使用字体图标
4)图片压缩
使用TinyPNG压缩: TinyPNG是一个知名的在线压缩图片的网站,可以压缩PNG和JPG格式的图片,可以同时上传20张图片,每张最大不能超过5M,这个工具压缩的效果很理想,尤其对于PNG格式的图片。地址:https://tinypng.com/
5)图片懒加载,对于图片过多的页面,为了加快页面加载速度,只加载页面可视区域内的图片, 其它图片等到滚动到可视区域后再去加载。
6)css预加载: 用CSS样式设置一批背景图片,暂时用不到的先隐藏, 需要的时后再显示。
7)js预加载
// 用js的new Image(),可以实现异步加载图片,即不阻断html代码的执行。
const image = new Image();
image.src = url;
image.onload = function() {
document.body.appendChild(image);
}
使用浏览器缓存:
强缓存(200),是最快速的一种缓存方式,只要资源还在缓存有效期内,浏览器就会直接读取本地的缓存,不会请求服务器。
协商缓存(304),协商缓存就是经过浏览器与服务器之间协商之后,再决定是否读取本地缓存。如果服务器通知浏览器可以读取本缓存,就会返回304状态码,并且协商过程很简单,只会发送头信息,不会发送响应体。
html性能优化:
1)减少标签嵌套, 减少节点数量。
2)把script标签移到HTML文件末尾,因为JS会阻塞后面的代码的执行。
3)避免空的src与href
css性能优化:
1)避免复杂的选择器, 层级越少越好, 尽量使用具体的类写样式, 因为css是一层一层的检索的, 层级过多会把检索速度拖的很慢。
2)尽量使用外部样式, 减少样式重写, 利用css继承性减少代码量。
3)能用css实现的样式就不要用图片, 减少项目体积。
js性能优化:
1)采用事件委托绑定, 减少事件注册。
2)使用语句判断, 减少不必要的操作, 用三目运算替代条件分支可以减少解释器对条件的探测次数。
3)js设置样式的时候, 尽量不使用style去设置, 因为维护性、可读性差, 通过添加class的方式去设置。
4)尽量不使用eval函数, 因为eval是先转义一遍, 再执行一遍, 消耗了大量时间, 而且Eval还带来的安全性问题。
5)提高代码复用性
6)循环语句配合break使用, 减少循环次数。
7)避免内存泄漏, 不再使用的变量及时解除引用, 以便于垃圾回收机制回收。
19. react和vue有哪些不同,说说你对这两个框架的看法?
相同点:
都采用虚拟dom,diff算法的核心思想都一样
都是数据驱动
都是组件化开发
组件都提供了生命周期函数,方便开发者处理业务逻辑。
新版本都支持hooks
不同点:
1.框架不一样。vue是mvvm框架,React是MVC中的View。
2.虚拟dom的diff算法具体实现不一样。
vue diff对比时,声明一个map对象保存新节点,遍历老节点;而react声明的map对象保存老节点,遍历新节点。vue是一边比较一边给真实的DOM打补丁;react会生成一个副作用链表,记录所有的新增、删除、更新、移动操作,最后统一处理。
3.虚拟dom性能优化方案不一样。
vue通过patchFlag标记节点、hoistStatic静态提升、cacheHandlers事件缓存、预解析字符串等方案对虚拟dom做性能优化。react把虚拟dom处理成fiber,通过任务分割和分散执行提升性能。
4.数据管理不一样。
mvvm一个最显著的特征是数据双向绑定,无需优化就能达到良好的性能。React是单向数据流,是用状态和属性来驱动视图改变的。在react中,只要父组件重新渲染,不管子组件的属性和状态有没有改变,都会重新渲染,如果不优化(pureComponent/ shouldComponentUpdate )可能导致大量不必要的虚拟dom重新渲染。
4.事件机制不一样。
Vue原生事件使用标准Web事件;Vue组件的自定义事件是通过发布订阅模式实现的。React根据事件委托原理把原生事件包装了一下,所有事件都冒泡到顶层容器,然后在这里进行合成事件下发。基于这套,react可以跨端使用事件机制,而不是和Web DOM强绑定。Vue通过自定义事件实现子组件向父组件通信;React组件上无事件,父子组件通信使用props。
5.模版编译的不一样。
React用jsx渲染模板,使用babel编译jsx,最终生成虚拟dom。Vue用.vue渲染模板,是自己实现了compile-core、编译vue模板,最终生成虚拟dom,vue3也支持了jsx。
6.组件间共享代码的不一样。
vue组件之间通过mixin共享代码,而React组件之间通过HOC(高阶组件)共享代码。vue3也能使用高阶组件了,因为支持jsx
7.组件通信的区别。
react父子组件传值直接传即可,vue则需要通过自定义属性、自定义方法。React不支持自定义事件,Vue是使用自定义事件实现子向父传值的。
20.回流与重绘
回流:
当render tree中的一部分(或全部)元素的尺寸、位置、隐藏/显示等改变时,页面的布局需要重新构建,这就称为回流(reflow)。每个页面至少需要一次回流,就是在页面第一次加载的时候,因为要构建render tree。常见引起回流的操作:
1.DOM的增删
2.元素几何属性或位置的变化
3.获取元素的偏移量属性:获取元素的clientWidth、clientHeight、clientTop、clientLeft、offsetWidth、offsetHeight、offsetTop、offsetLeft、scrollWidth、scrollHeight、scrollTop、scrollLeft之类的属性,浏览器为了保证值的正确,会回流取得最新的值,所以如需要多次操作,最好做个缓存。
4.浏览器窗口尺寸改变
重绘:
当render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局时,比如background-color,就会重绘。
区别:
回流必将引起重绘,而重绘不一定会引起回流。比如:只有颜色改变的时候,就只会发生重绘而不引起回流。当页面布局和几何属性发生改变时就需要回流,比如:添加或者删除可见的DOM元素,元素位置改变,元素尺寸改变等。
如何减少页面回流
1、CSS优化法
(1)使用transform替代top/left
(2)避免使用table布局,可能很小的一个小改动会造成整个 table 的重新布局。
(3)限制回流的范围,尽可能在最内层的DOM元素上修改,减少影响的节点。
(4)给频繁重绘或者回流的节点设置一个BFC容器,让内部的布局不会影响到外面。
(5)CSS3硬件加速(GPU加速),使用css3硬件加速,可以让transform、opacity、filters这些动画不会引起回流重绘。
2、JavaScript优化法
(1)避免频繁操作样式,最好一次性重写style属性,或者一次性更改class属性。
(2)避免频繁操作DOM。
(3)避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。
21. nodejs如何设置cors?
返回数据时在头信息里设置
response.writeHead(200, { /* 设置头信息和状态码 */
"Access-Control-Allow-Origin": "*", // cors跨域资源共享
});
22. nodejs有哪些常用的模块?
path模块:用于处理文件和目录的路径
fs模块:用于文件操作
http模块:创建服务器
url模块:用来解析url地址的
body-parser模块:解析post请求参数
querystring模块:解析字符出
23. nodejs的fs模块有哪些API?
fs.mkdir 创建文件夹
fs.rmdir 删除文件夹
fs.writeFile 写入文件
fs.appendFile 文件追加内容
fs.readFile 读取文件
24. nodejs是什么?
是运行在服务端的js,node是一个js的运行环境。
25. node和浏览器有什么区别?
node只有js引擎 ,只能解析js代码。浏览器有渲染引擎(解析html、css、img...)和js引擎。
26.说说模块化commonjs、AMD、CMD不同?
CommonJs/AMD/CMD都是JS模块化开发的标准,CommonJs: nodeJs,AMD: RequireJs,CMD: SeaJs。CommonJs针对服务端,AMD/CMD针对浏览器端。
AMD/CMD区别:
1.AMD是预加载,在并行加载js文件同时,还会解析执行该模块, 因为还需要执行,所以在加载某个模块前,这个模块的依赖模块需要先加载完成。CMD是懒加载,虽然会一开始就加载js文件,但是不会执行,而是在需要的时候才执行。
2.AMD加载快速,尤其遇到多个大文件,因为异步解析,所以同一时间可以解析多个文件。CMD执行等待时间会叠加。因为每个文件执行时是同步执行,因此时间是所有文件解析执行时间之和,尤其在文件较多较大时,这种缺点尤为明显。
3.AMD并行加载,异步处理,加载顺序不一定,可能会造成一些困扰,甚至为程序埋下大坑。CMD因为只有在使用的时候才会解析执行js文件,因此,每个JS文件的执行顺序在代码中是有体现的,是可控的。
27.微前端技术
什么是微前端
通过多个团队独立发布其子应用,来共同构建web应用的一种技术手段及方法策略。它旨在解决一个大型应用,由于参与的人员、团队及运用的技术栈较多,开发维护困难的问题。
微前端架构的核心价值:
1.技术栈无关,主子应用都不限制接入的技术栈
2.相互独立,微应用仓库独立,独立开发、独立部署、独立运行(微应用之间、微应用与主应用之间状态隔离,运行时状态不共享)
3.子应用部署完成后主框架自动同步更新
4.渐进式升级:我们通常很难对一个已经存在的系统做全量的技术栈升级或重构,而微前端是一种非常好的实施渐进式重构的策略。
微前端框架是怎么导入子应用的?
通过fetch请求,获取子应用的html文件,然后转换成字符串,最后渲染到基座html文件中的一个div标签内。
qiankun怎么处理样式污染的?
1.子应用之间:
qiankun将会自动隔离子应用之间的样式(开启沙箱的情况下)。
子应用不同时存在时,可采用动态样式表的方式,加载子应用时添加样式,卸载子应用时移除样式。
2.主应用与子应用之间
手动确保主应用与微应用之间的样式隔离,比如给主应用的所有样式添加一个前缀。如果使用了ant-design这样的组件库,可以给主应用样式配置自动添加前缀。
shadowDOM(影子DOM)的方式隔离样式。
qiankun怎么处理window污染的?
通过js沙箱处理。如果浏览器支持Proxy,就用Proxy沙箱,不支持就用快照沙箱。
28.组件库创建并发布到npm的流程
1.创建项目
2.在项目里执行lerna init初始化packages包和lerna.json;执行lerna create,在packages文件的lib文件里创建包名;执行lerna bootstrap,把所有包安装到根node_modules
3.在lib里开发组件、再把组件做成插件导出,在项目里测试完毕并打包
4.(终端上登录git账号)提交代码的github
5.(终端上登录npm账号)执行lerna publish就可以将组件库发布到npm官网
29.性能监控
- 性能监控可以很好的帮助开发者了解在各种真实环境下,页面的性能情况是如何的。
- 对于性能监控来说,我们可以直接使用浏览器自带的
Performance API
来实现这个功能。 - 只需要调用
performance.getEntriesByType('navigation')
这行代码就行了。对,你没看错,一行代码我们就可以获得页面中各种详细的性能相关信息
30.异常监控
- 对于异常监控来说,以下两种监控是必不可少的,分别是代码报错以及接口异常上报。
- 对于代码运行错误,通常的办法是使用
window.onerror
拦截报错。该方法能拦截到大部分的详细报错信息,但是也有例外
- 对于跨域的代码运行错误会显示
Script error
. 对于这种情况我们需要给script
标签添加crossorigin
属性 - 对于某些浏览器可能不会显示调用栈信息,这种情况可以通过
arguments.callee.caller
来做栈递归
- 对于异步代码来说,可以使用
catch
的方式捕获错误。比如Promise
可以直接使用catch
函数,async await
可以使用try catch
- 但是要注意线上运行的代码都是压缩过的,需要在打包时生成
sourceMap
文件便于debug
- 对于捕获的错误需要上传给服务器,通常可以通过
img
标签的src
发起一个请求。 - 另外接口异常就相对来说简单了,可以列举出出错的状态码。一旦出现此类的状态码就可以立即上报出错。接口异常上报可以让开发人员迅速知道有哪些接口出现了大面积的报错,以便迅速修复问题。
31.页面埋点
页面埋点应该是大家最常写的监控了,一般起码会监控以下几个数据:
PV
/UV
- 停留时长
- 流量来源
- 用户交互
对于这几类统计,一般的实现思路大致可以分为两种,分别为手写埋点和无埋点的方式。
相信第一种方式也是大家最常用的方式,可以自主选择需要监控的数据然后在相应的地方写入代码。这种方式的灵活性很大,但是唯一的缺点就是工作量较大,每个需要监控的地方都得插入代码。
另一种无埋点的方式基本不需要开发者手写埋点了,而是统计所有的事件并且定时上报。这种方式虽然没有前一种方式繁琐了,但是因为统计的是所有事件,所以还需要后期过滤出需要的数据。
32.前后端通信方案
-
Ajax 同源下的通信方式
-
CORS
-
反向代理
-
WebSocket 不受同源限制
WebSocket
HTTP 协议有一个缺陷:通信只能由客户端发起。所以出现了 WebSocket,它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
其他的特点包括:
-
建立在 TCP 协议之上,服务器端的实现比较容易
-
与 HTTP 协议有着良好的兼容性。默认端口也是 80 和 443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
-
数据格式比较轻量,性能开销少,通信高效
-
可以发送文本,也可以发送二进制数据
-
没有同源限制,客户端与服务器可以任意通信
-
协议标识符是 ws(如果是加密,则为 wss),服务器网址就是 URL
/*
声明一个WebSocket对象,参数是服务端地址,同http协议使用http://开头一样,
WebSocket协议的url使用ws://开头,另外安全的WebSocket协议使用wss://开头
*/
var ws = new WebSocket("ws://localhost:8080");
ws.onopen = function(){
// 当WebSocket创建成功时,触发onopen事件
console.log("open");
ws.send("hello"); // 将消息发送到服务端
}
ws.onmessage = function(e){
// 当客户端收到服务端发来的消息时,触发onmessage事件,参数e.data包含server传递过来的数据
console.log(e.data);
}
ws.onclose = function(e){
// 当客户端收到服务端发送的关闭连接请求时,触发onclose事件
console.log("close");
}
ws.onerror = function(e){
// 如果出现连接、处理、接收、发送数据失败的时候触发onerror事件
console.log(error);
}
CORS
CORS 是由服务器配置,允许网页跨域访问其资源。CORS 就是为了让 ajax 可以实现可控的跨域访问而生的。
33.浏览器都有哪些进程,渲染进程中都有什么线程?
浏览器组成
-
早期浏览器是单进程的,由于单进程容易卡死、奔溃等,现在浏览器就有了多进程架构。
-
浏览器进程架构包含:浏览器主进程、渲染进程、GPU进程、网络进程、其它插件进程等
-
每个页面或者同站点将分配一个渲染进程。渲染进程是由多个线程相互协同。
-
渲染进程包含:渲染主线程、js引擎线程、io线程、定时器线程、事件触发线程等
浏览器进程
- 浏览器主进程
负责地址栏、书签栏、前进后退按钮等内容的工作
- 渲染进程
负责一个tab内关于网页呈现的所有事情
- GPU进程
负责处理GPU相关的任务
- 网络进程
负责处理浏览器的一些不可见的底层操作,比如网络请求和文件访问
- 其他插件进程
负责控制一个网页用到的所有插件,如flash
渲染进程
-
GUI渲染线程
- 负责渲染浏览器界面,解析HTML、CSS、构建DOM树和渲染树、布局和绘制等
- 当界面需要重绘或由于某种操作引发回流时,该线程就会执行
- 注意:GUI渲染线程和JS引擎线程是互斥的,JS引擎线优先级高于GUI渲染线程,当JS引擎执行时GUI线程会被挂起,GUI更新会保存在一个队列中等到JS引擎空闲时间被执行
-
JS引擎线程
- 也称之为JS内核,负责处理和解析JavaScript脚本程序,运行代码,如V8引擎等;
- JS引擎一直等待着任务队列中的任务,然后加以处理,render进程中永远只有一个JS线程在运行js程序
- 同样注意:GUI渲染线程和JS引擎线程是互斥的,JS执行时间过长,就会造成页面的渲染不连贯,导致页面渲染加载阻塞
-
事件触发线程
- 归属于浏览器而不是JS引擎,用来控制事件循环;
- 当JS引擎执行代码块如:鼠标点击,会将对应的任务添加到事件线程中
- 当对应的事件服务触发条件时,该线程会把事件添加到待处理队列的队尾,等到JS引擎来处理
-
定时处理线程
- setInterval与setTimeout所在的线程;
- 浏览器定时计数器并不是由JavaScript引擎计数的,它是通过单独线程来计时并触发定时;
- 注意:W3C在HTML标准中规定,要求setTimeout中低于4ms的时间间隔算为4ms
-
异步http请求线程
- 在XMLHttpRequest在连接后通过浏览器新开的一个线程请求
- 将检测到状态变更时,如果设置有回调函数,异步线程就会产生状态变更事件,将这个回调在放入事件队列中,再由JavaScript引擎执行
34.把 10 万次 for 循环的代码插到 html 中间,会有什么现象?
页面会出现卡顿现象,代码后的 DOM 节点加载不出来
出现卡顿现象怎么解决?
1.外部加载的js,可以给 script 标签设置 defer 属性,浏览器其他线程将下载脚本,待到dom解析完成脚本才会执行。
2.使用虚拟列表,实现方案如下:
1.拿到所有数据,但只展示可视范围内的数据,可视范围数据通过 allData.slice(start, end) 获取,start是开始截取的下标,end是结束下标。
2.首先创建一个外层容器,外层容器的高为可视区域的高,可视区域的高为item高的整数倍(本案例是10倍)。
3.外层容器包裹一个内层容器,内层容器的高为所有item高之和
4.内层容器里包裹一个可视容器,可视容器的高等于外层容器的高,可视容器的 transform: translateY 等于外层容器的 scrollTop
5.外层容器绑定scroll事件,滚动时重新设置start和end,并重新获取可视范围数据。
start = Math.floor(scrollTop / itemHeight); end = start + 10;
35.vue hooks 与 react hooks的区别
从 React Hook 的实现角度看,React Hook 是根据 hooks api 的调用顺序来确定下一次重渲染时,hook链表中的数据对应哪个 hooks api,所以出现了以下限制:
-
不能再循环、条件、嵌套函数中调用 Hook
-
必须确保总是在 React 函数的顶层调用 Hook
-
useEffect、useMemo 等函数必须手动确定依赖关系
而 Composition API 是基于 Vue 的响应式系统实现的,与 React Hook 相比:
-
声明在 setup 函数内,一次组件实例化只调用一次 setup,而 React Hook 每次重渲染都需要重新调用 Hook,浪费了性能。
-
Composition API 的调用不需要考虑调用顺序,也可以在循环、条件、嵌套函数中使用
-
响应式系统自动实现依赖收集原理,进而组件部分的性能优化由 Vue 内部自己完成,而 React Hook 需要手动传入依赖,且必须保证依赖的顺序,让 useEffect、useMemo 等函数正确的捕获依赖变量,否则会由于依赖不正确使得组件性能下降
虽然 Composition API 比 React Hook 好用,但其设计思想也是借鉴 React Hook 的