总结
- 对于框架原理只能说个大概,真的深入某一部分具体的代码和实现方式就只能写出一个框架,许多细节注意不到。
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
-
算法方面还是很薄弱,好在面试官都很和蔼可亲,擅长发现人的美哈哈哈…(最好多刷一刷,不然影响你的工资和成功率???)
-
在投递简历之前,最好通过各种渠道找到公司内部的人,先提前了解业务,也可以帮助后期优秀 offer 的决策。
-
要勇于说不,对于某些 offer 待遇不满意、业务不喜欢,应该相信自己,不要因为当下没有更好的 offer 而投降,一份工作短则一年长则 N 年,为了幸福生活要慎重选择!!!
第一次跳槽十分忐忑不安,和没毕业的时候开始找工作是一样的感受,真的要相信自己,有条不紊的进行。如果有我能帮忙的地方欢迎随时找我,比如简历修改、内推、最起码,可以把烦心事说一说,人嘛都会有苦恼的~
祝大家都有美好的未来,拿下满意的 offer。
网络请求相关
======
这部分旨在实现需求的前提下尽量减少http请求的开销,或者减少响应时间
CDN
将第三方的类库放到CDN上,能够大幅度减少生产环境中的项目体积,另外CDN能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上
另外因为CDN和服务器的域名一般不是同一个,可以缓解同一域名并发http请求的数量限制,有效分流以及减少多余的cookie的发送(CDN上面的静态资源请求时不需要携带任何cookie)
通俗的来说就是使用CDN会一定程度上提升项目中的静态文件的传输速度,在vue-cli3中可以通过externals配置项,将第三方的类库的引用地址从本地指向你提供的CDN地址
externals只适用于ES Module的默认导入
这里通过环境变量来判断生产环境才启用CDN,除了需要开启CDN外,你还需要在index.html注入CDN的域名,所以我这里通过html-webpack-plugin根据cdn域名动态的注入script标签,同时需要在index.html中通过模版的语法声明循环的数组和注入的元素
打包前的index.html:
打包后的index.html:
可以看到通过这个插件可以将cdn域名动态的注入到打包后的index.html中
还有一点要注意的是,externals对象的属性为你引入包的名字,而属性值是对应的全局变量名称(CDN引入的类库文件会自动挂载到window对象下面,而挂载时的属性名需要去对应的CDN在源码中寻找,一般在开头行都会有声明,除此之外导入还有困难的还可以看下这篇博客webpack externals 深入理解)
这里还是建议尽量放到公司专用的CDN上,不推荐使用公共的CDN,因为容易挂,生产环境还是以稳定为主吧
合理的缓存策略
将长时间不会改变的第三方类库或者静态资源设置为强缓存,将max-age设置为一个非常长的时间,再将访问路径加上哈希达到哈希值变了以后保证获取到最新资源(vue-cli3会自动构建,自己搭建的webpack脚手架需要自行配置contentHash,chunkHash)
CDN上的缓存策略,可以看到max-age的值非常大,这样下次访问就只会读取本地磁盘/内存中缓存的资源:
对于index.html和一些图片等多媒体资源,可以选择协商缓存(max-age<=0,Last-Modified,ETag),保证返回服务器最新的资源
一个好的缓存策略,有助于减轻服务器的压力,并且显著的提升用户的体验
gzip
为你的文件开启gzip压缩是一个不错的选择,通常开启gzip压缩能够有效的缩小传输资源的大小,如果你的项目是用nginx作为web服务器的话,只需在nginx的配置文件中配置相应的gzip选项就可以让你的静态资源服务器开启gzip压缩
#开启和关闭gzip模式
gzip on;
#gizp压缩起点,文件大于1k才进行压缩
gzip_min_length 1k;
# gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间
gzip_comp_level 6;
# 进行压缩的文件类型。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript ;
#nginx对于静态文件的处理模块,开启后会寻找以.gz结尾的文件,直接返回,不会占用cpu进行压缩,如果找不到则不进行压缩
gzip_static on
# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;
# 设置gzip压缩针对的HTTP协议版本
gzip_http_version 1.1;
但是我们这里要说的是前端输出gzip文件,利用compression-webpack-plugin让webpack在打包的时候输出.gz后缀的压缩文件
这样不需要服务器主动压缩我们就已经可以得到gzip文件,在上面的nginx配置项中可以发现这一行
#nginx对于静态文件的处理模块,开启后会寻找以.gz结尾的文件,直接返回,不会占用cpu进行压缩,如果找不到则不进行压缩
gzip_static on
只要把.gz的文件放到服务器上,开始gzip_static就可以让服务器优先返回.gz文件,在面对高流量时,也能一定程度减轻对服务器的压力,属于用空间来换时间(.gz文件会额外占有服务器的空间)
资源嗅探
对于现代浏览器来说,可以给link标签添加preload,prefetch,dns-prefetch属性
preload
对于SPA应用来说,当浏览器解析完script脚本才会生成DOM节点,如果你的项目中没有使用服务端渲染的话且需要加载一个比较耗时的首屏图片时,可以考虑将这个首屏图片放在preload标签中让浏览器预先请求并加载执行,这样当script脚本执行完毕后就会瞬间加载图片(否则需要等脚本执行完毕后再向后台请求图片)
另外使用preload预加载首屏需要的css样式也是一个不错的选择,类似的库有critical
没有使用preload
使用preload
通过Waterfall可以看到这个webp图片需要等到脚本加载完之后才回去请求,如果这个图片比较大就会浪费不必要的时间
在工程中,利用一些preload的webpack插件可以很方便的给打包后的index.html注入预加载的资源标签,有兴趣的朋友可以试着搜索一下相关的插件
prefetch
prefetch可以让浏览器提前加载下个页面可能会需要的资源,vue-cli3默认会给所有懒加载的路由添加prefetch属性,这样可以在你访问使用到懒加载的路由页面时能够获得更快的加载速度
preload和prefetch的区别在于,preload的资源会和页面需要的静态资源并行加载,而prefetch则会等到浏览器加载完必要的资源后,在空闲时间加载被标记为prefetch的资源
dns-prefetch
dns-prefetch可以让浏览器提前对域名进行解析,减少DNS查找的开销,如果你的静态资源和后端接口不是同一个服务器的话,可以将考虑你后端的域名放入link标签加入dns-prefetch属性
京东首页也使用到了dns-prefetch技术
http2
http2从2015年问世以来已经走过了4个年头,如今在国内也有超过50%的覆盖率,得益于http2的分帧传输,它能够极大的减少http(s)请求开销
http2和http1.1的性能差异对比
如果系统首屏同一时间需要加载的静态资源非常多,但是浏览器对同一域名的tcp连接数量是有限制的(chrome为6个)超过规定数量的tcp连接,则必须要等到之前的请求收到响应后才能继续发送,而http2则可以在一个tcp连接中并发多个请求没有限制,在一些网络较差的环境开启http2性能提升尤为明显
这里极力推荐在支持https协议的服务器中使用http2协议,可以通过web服务器Nginx配置,或是直接让服务器支持http2
nginx开启http2非常简单,在nginx.conf中只需在原来监听的端口后面加上http2就可以了,前提是你的nginx版本不能低于1.95,并且已经开启了https
listen 443 ssl http2;
在network中通过protocol可以查看到当前的资源是通过哪个版本的http协议传输的
h2代表http2
构建相关
====
构建方面通过合理的配置构建工具,达到减少生产环境的代码的体积,减少打包时间,缩短页面加载时间
路由懒加载
传统的路由组件是通过import静态的打包到项目中,这样做的缺点是因为所有的页面组件都打包在同一个脚本文件中,导致生产环境下首屏因为加载的代码量太多会有明显的卡顿(白屏)
通过import()使得ES6的模块有了动态加载的能力,让url匹配到相应的路径时,会动态加载页面组件,这样首屏的代码量会大幅减少,webpack会把动态加载的页面组件分离成单独的一个chunk.js文件
当然懒加载也有缺点,就是会额外的增加一个http请求,如果项目非常小的话可以考虑不使用路由懒加载
预渲染
由于浏览器在渲染出页面之前,需要先加载和解析相应的html,css和js文件,为此会有一段白屏的时间,如何尽可能的减少白屏对用户的影响,目前我选择的是在html模版中,注入一个loading动画,这里我拿D2-Admin中的loading动画举例
很抱歉,如果没有 JavaScript 支持,D2Admin 将不能正常工作。请启用浏览器的 JavaScript 然后继续。
<img
class=“d2-home__loading”
src=“./image/loading/loading-spin.svg”
alt=“loading”>
正在加载资源
初次加载资源可能需要较多时间 请耐心等待
<a
href=“https://github.com/d2-projects/d2-admin”
target=“_blank”>
https://github.com/d2-projects/d2-admin
在打包完成后,在这个index.html下方还会注入页面的脚本,当用户访问你的项目时,脚本还没有执行,但是可以显示loading动画,因为它是直接注入在html中的,等到脚本执行完毕后,Vue会新生成一个app的节点然后将旧的同名节点删除,这样可以有效的过渡白屏的时间
loading动画只是一个让用户感知到你程序正在启动的效果,只是一个静态页面没有任何的功能
另外预渲染还可以使用服务端渲染(SSR),通过后端输出一个首页的模版,或者使用骨架屏的方案,这里本人没有深入的了解过,有兴趣的朋友可以去实践一下
升级到最新的webpack版本
webpack4相对于webpack3来说在打包优化方面性能提升还是比较明显的,如果觉得自己配置脚手架比较复杂的话,可以使用vue-cli3来构建你的项目,同样是基于webpack4搭建的
DllPlugin
当没有一个稳定的CDN时,使用DllPlugin这个webpack插件同样可以将类库从业务代码中分离出去,其原理是预先将类库文件打包,随后创建一个关联表,在业务代码依赖第三方类库时,会直接去关联表中获取已经打包好的类库文件。这样做的好处在于因为业务代码会常常需要打包上线,而第三方类库基本不会改变,所以每次打包可以跳过这些类库文件,减少不必要的重复打包
DllPlugin是一个webpack内置的插件,无需安装,但是要让打包后的index.html注入这些打包后第三方类库,需要额外安装add-asset-html-webpack-plugin
插件
当你需要在index.html中注入多个类库时,需要实例化多次add-asset-html-webpack-plugin
,这里我们可以利用nodejs的fs模块,遍历DllPlugin打包后的目录,根据类库的数量决定需要生成多少个实例,非常的灵活,具体的配置项可以查看我底部的链接
合理使用第三方库
如果项目中有一些日期操作的需求,不妨将目光从moment转移到day,相对于笨重的moment,它只有2kb,day和moment的api完全一样,并且中文文档也比较友好
另外对于lodash这类的库如果只需要部分功能,则只要引入其中一部分,这样webpack在treeshaking后在生产环境也只会引入这一部分的代码
对于UI库(element-ui)打包后的体积也会非常大,尽量使用按需加载,官方文档上也有详细教程
element-ui的压缩后的体积竟然是Vue的十倍
常用的路径创建文件别名
给常用的模块路径创建一个别名是一个不错的选择,可以减少模块查找时耗费的时间,项目越大收益也就越明显
vue-cli3中的配置和使用方法(webpack链式调用文档)
使用可视化工具分析打包后的模块体积
我通过webpack-bundle-analyzer这个插件在每次打包后能够更加直观的分析打包后模块的体积,再对其中比较大的模块进行优化
这是我在优化前的各模块体积:
因为业务需求,要求前端导出pdf和excel文件,我这里引入了xlsx和pdf.js这2个包,但是打包后通过可视化工具发现光着2个文件就占了一半的项目体积,另外elementui和moment也非常的大
这是优化后通过可视化工具观察到的各模块体积,通过将这些类库放到CDN上或者使用dllPlugin将类库和业务文件分离,可以看到没有明显特别大的模块了
静态资源优化
======
这部分旨在减少请求一些图片资源所造成的影响
图片懒加载
如果你的系统是一个偏展示的项目需要给用户展示大量图片,是否启用图片懒加载可能是你需要考虑的一个点,不在用户视野中的图片是没有必要加载的,图片懒加载通过让图片先加载成一张统一的图片,再给进入用户视野的图片替换真正的图片地址,可以同一时间减少http请求开销,避免显示图片导致的画面抖动,提高用户体验
下面我提供2种图片懒加载的思路,这2个方案最终都是用将占位的图片替换成真正的图片,然后给img标签设置一个自定义属性src存放真正的图片地址,src存放占位图片的地址
getBoundingClientRect
DOM元素包含一个getBoundingClientRect方法,执行该方法返回当前DOM节点相关的CSS边框集合
最后
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
就答题情况而言,第一问100%都可以回答正确,第二问大概只有50%正确率,第三问能回答正确的就不多了,第四问再正确就非常非常少了。其实此题并没有太多刁钻匪夷所思的用法,都是一些可能会遇到的场景,而大多数人但凡有1年到2年的工作经验都应该完全正确才对。
只能说有一些人太急躁太轻视了,希望大家通过此文了解js一些特性。
并祝愿大家在新的一年找工作面试中胆大心细,发挥出最好的水平,找到一份理想的工作。