「前端996」阿⾥智能事业-达摩院-机器智能技术部-秋招⾯试经历(整理)阿⾥智能事业-达摩院-机器智能技术部
⼀⾯
⾃我介绍
聊实习经历
主要⼯作内容,⽐如申请前端⼩组组长,与项⽬负责⼈沟通,完成模块发布⼯具前端框架。每⽇完成⼯作进度汇报,前端⼯作主要是表格页⾯渲染,⽐如树形表格,分组表格结合等,实现基本的增删改查功能…
项⽬中有⽤到SSR,说说对SSR的理解,⽬前为什么要⽤SSR?
页⾯的渲染流程
浏览器通过请求得到⼀个HTML⽂本
渲染进程解析HTML⽂本,构建DOM树
解析HTML的同时,如果遇到内联样式或者样式脚本,则下载并构建样式规则(stytle rules),若遇到JavaScript脚本,则会下载执⾏脚本。
DOM树和样式规则构建完成之后,渲染进程将两者合并成渲染树(render tree)
渲染进程开始对渲染树进⾏布局,⽣成布局树(layout tree)
渲染进程对布局树进⾏绘制,⽣成绘制记录
渲染进程的对布局树进⾏分层,分别栅格化每⼀层,并得到合成帧
渲染进程将合成帧信息发送给GPU进程显⽰到页⾯中
可以看到,页⾯的渲染其实就是浏览器将HTML⽂本转化为页⾯帧的过程。⽽如今我们⼤部分WEB应⽤都是使⽤ JavaScript 框架(Vue、React、Angular)进⾏页⾯渲染的,也就是说,在执⾏ JavaScript 脚本的时候,HTML页⾯已经开始解析并且构建DOM树
了,JavaScript 脚本只是动态的改变 DOM 树的结构,使得页⾯成为希望成为的样⼦,这种渲染⽅式叫动态渲染,也可以叫客户端渲染(client side rende)。
那么什么是服务端渲染(server side render)?顾名思义,服务端渲染就是在浏览器请求页⾯URL的时候,服务端将我们需要的HTML⽂本组装好,并返回给浏览器,这个HTML⽂本被浏览器解析之后,不需要经过 JavaScript 脚本的执⾏,即可直接构建出希望的 DOM 树并展⽰到页⾯中。这个服务端组装HTML的过程,叫做服务端渲染。
服务端渲染的由来
Web1.0
在没有AJAX的时候,也就是web1.0时代,⼏乎所有应⽤都是服务端渲染(此时服务器渲染⾮现在的服务器渲染),那个时候的页⾯渲染⼤概是这样的,浏览器请求页⾯URL,然后服务器接收到请求之后,到数据库查询数据,将数据丢到后端的组件模板(php、asp、jsp等)中,并渲染成HTML⽚段,接着服务器在组装这些HTML⽚段,组成⼀个完整的HTML,最后返回给浏览器,这个时候,浏览器已经拿到了⼀个完整的被服务器动态组装出来的HTML⽂本,然后将HTML渲染到页⾯中,过程没有任何JavaScript代码的参与。
客户端渲染
在WEB1.0时代,服务端渲染看起来是⼀个当时的最好的渲染⽅式,但是随着业务的⽇益复杂和后续AJAX的出现,也渐渐开始暴露出了WEB1.0服务器渲染的缺点。
每次更新页⾯的⼀⼩的模块,都需要重新请求⼀次页⾯,重新查⼀次数据库,重新组装⼀次HTML
前端JavaScript代码和后端(jsp、php、jsp)代码混杂在⼀起,使得⽇益复杂的WEB应⽤难以维护
⽽且那个时候,根本就没有前端⼯程师这⼀职位,前端js的活⼀般都由后端同学 jQuery ⼀把梭。但是随着前端页⾯渐渐地复杂了之后,后端开始发现js好⿇烦,虽然很简单,但是坑太多了,于是让公司招聘了⼀些专门写js的⼈,也就是前端,这个时候,前后端的鄙视链就出现了,后端鄙视前端,因为后端觉得js太简单,⽆⾮就是写写页⾯的特效(JS),切切图(CSS),根本算不上是真正的程序员。
随之 nodejs 的出现,前端看到了翻⾝的契机,为了摆脱后端的指指点点,前端开启了⼀场前后端分离的运动,希望可以脱离后端独⽴发展。前后端分离,表⾯上看上去是代码分离,实际上是为了前后端⼈员分离,也就是前后端分家,前端不再归属于后端团队。
前后端分离之后,⽹页开始被当成了独⽴的应⽤程序(SPA,Single Page Application),前端团队接管了所有页⾯渲染的事,后端团队只负责提供所有数据查询与处理的API,⼤体流程是这样的:⾸先浏览器请求URL,前端服务器直接返回⼀个空的静态HTML⽂件(不需要任何查数据库和模板组装),这个HTML⽂件中加载了很多渲染页⾯需要的 JavaScript 脚本和 CSS 样式表,浏览器拿到 HTML ⽂件后开始加载脚本和样式表,并且执⾏脚本,这个时候脚本请求后端服务提供的API,获取数据,获取
完成后将数据通过JavaScript脚本动态的将数据渲染到页⾯中,完成页⾯显⽰。
这⼀个前后端分离的渲染模式,也就是客户端渲染(CSR)。
服务端渲染
随着单页应⽤(SPA)的发展,程序员们渐渐发现SEO(Search Engine Optimazition,即搜索引擎优化)出了问题,⽽且随着应⽤的复杂
化,JavaScript 脚本也不断的臃肿起来,使得⾸屏渲染相⽐于 Web1.0时候的服务端渲染,也慢了不少。
⾃⼰选的路,跪着也要⾛下去。于是前端团队选择了使⽤ nodejs 在服务器进⾏页⾯的渲染,进⽽再次出现了服务端渲染。⼤体流程与客户端渲染有些相似,⾸先是浏览器请求URL,前端服务器接收到URL请求之后,根据不同的URL,前端服务器向后端服务器请求数据,请求完成后,前端服务器会组装⼀个携带了具体数据的HTML⽂本,并且返回给浏览器,浏览器得到HTML之后开始渲染页⾯,同时,浏览器加载并执⾏ JavaScript 脚本,给页⾯上的元素绑定事件,让页⾯变得可交互,当⽤户与浏览器页⾯进⾏交互,如跳转到下⼀个页⾯时,浏览器会执⾏ JavaScript 脚本,向后端服务器请求数据,获取完数据之后再次执⾏ JavaScript 代码动态渲染页⾯。
服务端渲染的利弊
利于SEO
有利于SEO,其实就是有利于爬⾍来爬你的页⾯,然后在别⼈使⽤搜索引擎搜索相关的内容时,你的⽹页排⾏能靠得更前,这样你的流量就有越⾼。那为什么服务端渲染更利于爬⾍爬你的页⾯呢?其实,爬⾍也分低级爬⾍和⾼级爬⾍。
低级爬⾍:只请求URL,URL返回的HTML是什么内容就爬什么内容。
⾼级爬⾍:请求URL,加载并执⾏JavaScript脚本渲染页⾯,爬JavaScript渲染后的内容。
也就是说,低级爬⾍对客户端渲染的页⾯来说,简直⽆能为⼒,因为返回的HTML是⼀个空壳,它需要执⾏ JavaScript 脚本之后才会渲染真正的页⾯。⽽⽬前像百度、⾕歌、微软等公司,有⼀部分年代⽼旧的爬⾍还属于低级爬⾍,使⽤服务端渲染,对这些低级爬⾍更加友好⼀些。
⽩屏时间更短
相对于客户端渲染,服务端渲染在浏览器请求URL之后已经得到了⼀个带有数据的HTML⽂本,浏览器只需要解析HTML,直接构建DOM 树就可以。⽽客户端渲染,需要先得到⼀个空的HTML页⾯,这
个时候页⾯已经进⼊⽩屏,之后还需要经过加载并执⾏ JavaScript、请求后端服务器获取数据、JavaScript 渲染页⾯⼏个过程才可以看到最后的页⾯。特别是在复杂应⽤中,由于需要加载 JavaScript 脚本,越是复杂的应⽤,需要加载的 JavaScript 脚本就越多、越⼤,这会导致应⽤的⾸屏加载时间⾮常长,进⽽降低了体验感。
服务端渲染缺点
并不是所有的WEB应⽤都必须使⽤SSR,这需要开发者⾃⼰来权衡,因为服务端渲染会带来以下问题:
代码复杂度增加。为了实现服务端渲染,应⽤代码中需要兼容服务端和客户端两种运⾏情况,⽽⼀部分依赖的外部扩展库却只能在客户端运⾏,需要对其进⾏特殊处理,才能在服务器渲染应⽤程序中运⾏。
需要更多的服务器负载均衡。由于服务器增加了渲染HTML的需求,使得原本只需要输出静态资源⽂件的nodejs服务,新增了数据获取的IO和渲染HTML的CPU占⽤,如果流量突然暴增,有可能导致服务器down机,因此需要使⽤响应的缓存策略和准备相应的服务器负载。
涉及构建设置和部署的更多要求。与可以部署在任何静态⽂件服务器上的完全静态单页⾯应⽤程序 (SPA) 不同,服务器渲染应⽤程序,需要处于 Node.js server 运⾏环境。
所以在使⽤服务端渲染SSR之前,需要开发者考虑投⼊产出⽐,⽐如⼤部分应⽤系统都不需要SEO,⽽且⾸屏时间并没有⾮常的慢,如果使⽤SSR反⽽⼩题⼤做了。
同构
在服务端渲染中,有两种页⾯渲染的⽅式:
前端服务器通过请求后端服务器获取数据并组装HTML返回给浏览器,浏览器直接解析HTML后渲染页⾯
浏览器在交互过程中,请求新的数据并动态更新渲染页⾯
这两种渲染⽅式有⼀个不同点就是,⼀个是在服务端中组装html的,⼀个是在客户端中组装html的,运⾏环境是不⼀样的。所谓同构,就是让⼀份代码,既可以在服务端中执⾏,也可以在客户端中执⾏,并且执⾏的效果都是⼀样的,都是完成这个html的组装,正确的显⽰页⾯。也就是说,⼀份代码,既可以客户端渲染,也可以服务端渲染。
同构的条件
为了实现同构,我们需要满⾜什么条件呢?
⾸先,我们思考⼀个应⽤中⼀个页⾯的组成,假如我们使⽤的是Vue.js,当我们打开⼀个页⾯时,⾸先是打开这个页⾯的URL,这
个URL,可以通过应⽤的路由匹配,到具体的页⾯,不同的页⾯有不同的视图,那么,视图是什么?从应⽤的⾓度来看,视图 = 模板 +数据,那么在 Vue.js 中, 模板可以理解成组件,数据可以理解为数据模型,即响应式数据。所以,对于同构应⽤来说,我们必须实现客户端与服务端的路由、模型组件、数据模型的共享。
总结
浏览器渲染
单页应⽤⽤的基本都是浏览器渲染。优点很明确,后端只提供数据,前端做视图和交互逻辑,分⼯明确。服务器只提供接⼝,路由以及渲染都丢给前端,服务器计算压⼒变轻了。但是弱点就是⽤户等待时间变长了,尤其在请求数多⽽且有⼀定先后顺序的时候。
客户端渲染路线:1. 请求⼀个html -> 2. 服务端返回⼀个html -> 3. 浏览器下载html⾥⾯的js/css⽂件 -> 4. 等待js⽂件下载完成 -> 5. 等待js加载并初始化完成 -> 6. js代码终于可以运⾏,由js代码向后端请求数据( ajax/fetch ) -> 7. 等待后端数据返回 -> 8. 客户端从⽆到完整地,把数据渲染为响应页⾯
服务器渲染
服务器接到⽤户请求之后,计算出⽤户需要的数据,然后将数据更新成视图(也就是⼀串dom字符)发给客户端,客户端直接将这串字符塞进页⾯即可。这样做的好处是响应很快,⽤户体验会⽐较好,另外对于搜索引擎来说也是友好的,有SEO优化。nodejs层的服务器渲染,还有⼀个明显的好处就是前端性能优化更顺⼿了,可操作的空间⼤了。但是缺点也很明显,如果不是增加⼀个node层的话,前后端责任分⼯不明,不能很好的并⾏开发。另外也增加了服务器计算压⼒(虽然可以做渲染缓存,但毕竟是多做了计算)。
服务端渲染路线:2. 请求⼀个html -> 2. 服务端请求数据( 内⽹请求快 ) -> 3. 服务器初始渲染(服务端性能好,较快) -> 4. 服务端返回已经有正确内容的页⾯ -> 5. 客户端请求js/css⽂件 -> 6. 等待js⽂件下载完成 -> 7. 等待js加载并初始化完成 -> 8. 客户端把剩下⼀部分渲染完成( 内容⼩,渲染快 )
对CDN的理解
github ⾥⾯有做cdn仓库,于是扯到了cdn,之后挂钩上http缓存,浏览器缓存相关,回源那⼀块。
说⼀个最近刷的印象⽐较深刻的 leetcode 题⽬,讲讲思路
leetcode 200 岛屿问题 讲了怎么dfs 沉岛
⼤学⾥⾯学的⼀些课程哪门最熟悉?
算法、数据结构、计算机⽹络、操作系统
选了计算机⽹络,毕竟是班主任教的(orz)
说说五层、七层计算机⽹络模型
举例传输层和应⽤层
传输层:TCP / UDP
应⽤层:HTTP / HTTPS 、FTP、SMTP等
HTTP1.0 和 HTTP2.0区别有了解吗?
简要概括⼀下 HTTP 的特点?HTTP 有哪些缺点?
HTTP 特点
灵活可扩展
主要体现在两个⽅⾯。⼀个是语义上的⾃由,只规定了基本格式,⽐如空格分隔单词,换⾏分隔字段,其他的各个部分都没有严格的语法限制。另⼀个是传输形式的多样性,不仅仅可以传输⽂本,还能传输图⽚、视频等任意数据,⾮常⽅便。
可靠传输
HTTP 基于 TCP/IP,因此把这⼀特性继承了下来。
请求-应答
也就是⼀发⼀收、有来有回, 当然这个请求⽅和应答⽅不单单指客户端和服务器之间,如果某台服务器作为代理来连接后端的服务端,那么这台服务器也会扮演请求⽅的⾓⾊。
⽆状态
这⾥的状态是指通信过程的上下⽂信息,⽽每次 http 请求都是独⽴、⽆关的,默认不需要保留状态信息。
HTTP 缺点
⽆状态
所谓的优点和缺点还是要分场景来看的,对于 HTTP ⽽⾔,最具争议的地⽅在于它的⽆状态。
在需要长连接的场景中,需要保存⼤量的上下⽂信息,以免传输⼤量重复的信息,那么这时候⽆状态就是 http 的缺点了。
但与此同时,另外⼀些应⽤仅仅只是为了获取⼀些数据,不需要保存连接上下⽂信息,⽆状态反⽽减少了⽹络开销,成为了 http 的优点。
明⽂传输
即协议⾥的报⽂(主要指的是头部)不使⽤⼆进制数据,⽽是⽂本形式。
这当然对于调试提供了便利,但同时也让 HTTP 的报⽂信息暴露给了外界,给攻击者也提供了便利。WIFI陷阱就是利⽤ HTTP 明⽂传输的缺点,诱导你连上热点,然后疯狂抓你所有的流量,从⽽拿到你的敏感信息。
队头阻塞问题
当 http 开启长连接时,共⽤⼀个 TCP 连接,同⼀时刻只能处理⼀个请求,那么当前请求耗时过长的情况下,其它的请求只能处于阻塞状态,也就是著名的队头阻塞问题。
HTTP1.1 如何解决 HTTP 的队头阻塞问题?
什么是 HTTP 队头阻塞?
HTTP 传输是基于请求-应答的模式进⾏的,报⽂必须是⼀发⼀收,但值得注意的是,⾥⾯的任务被放在⼀个任务队列中串⾏执⾏,⼀旦队⾸的请求处理太慢,就会阻塞后⾯请求的处理。这就是著名的HTTP队头阻塞问题。
并发连接
对于⼀个域名允许分配多个长连接,那么相当于增加了任务队列,不⾄于⼀个队伍的任务阻塞其它所有任务。在RFC2616规定过客户端最多并发 2 个连接,不过事实上在现在的浏览器标准中,这个上限要多很多,Chrome 中是 6 个。
但其实,即使是提⾼了并发连接,还是不能满⾜⼈们对性能的需求。
域名分⽚
⼀个域名不是可以并发 6 个长连接吗?那我就多分⼏个域名。
⽐如 content1.sanyuan 、content2.sanyuan。
前端页面模板
这样⼀个sanyuan域名下可以分出⾮常多的⼆级域名,⽽它们都指向同样的⼀台服务器,能够并发的长连接数更多了,事实上也更好地解决了队头阻塞的问题。
HTTP/2 有哪些改进?
由于 HTTPS 在安全⽅⾯已经做的⾮常好了,HTTP 改进的关注点放在了性能⽅⾯。对于 HTTP/2 ⽽⾔,它对于性能的提升主要在于两点:头部压缩
多路复⽤
当然还有⼀些颠覆性的功能实现:
设置请求优先级
服务器推送
这些重⼤的提升本质上也是为了解决 HTTP 本⾝的问题⽽产⽣的。接下来我们来看看 HTTP/2 解决了哪些问题,以及解决⽅式具体是如何的。
头部压缩
在 HTTP/1.1 及之前的时代,请求体⼀般会有响应的压缩编码过程,通过Content-Encoding头部字段来指定,但你有没有想过头部字段本⾝的压缩呢?当请求字段⾮常复杂的时候,尤其对于 GET 请求,请求报⽂⼏乎全是请求头,这个时候还是存在⾮常⼤的优化空间的。
HTTP/2 针对头部字段,也采⽤了对应的压缩算法——HPACK,对请求头进⾏压缩。
HPACK 算法是专门为 HTTP/2 服务的,它主要的亮点有两个:
⾸先是在服务器和客户端之间建⽴哈希表,将⽤到的字段存放在这张表中,那么在传输的时候对于之前出现过的值,只需要把索引(⽐如0,1,2,…)传给对⽅即可,对⽅拿到索引查表就⾏了。这种传索引的⽅式,可以说让请求头字段得到极⼤程度的精简和复⽤。
HTTP/2 当中废除了起始⾏的概念,将起始⾏中的请求⽅法、URI、状态码转换成了头字段,不过这些字段都有⼀个":"前缀,⽤来和其它请求头区分开。
其次是对于整数和字符串进⾏哈夫曼编码,哈夫曼编码的原理就是先将所有出现的字符建⽴⼀张索引表,然后让出现次数多的字符对应的索引尽可能短,传输的时候也是传输这样的索引序列,可以达到⾮常⾼的压缩率。
多路复⽤
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论