微派社招前端一面面经
前言:工作 2 年,我写的不一定对,如有错误,望评论区大佬指正,共同成长
- 自我介绍
- 介绍完后,面试官深挖项目 5 分钟
- 项目中提到了性能优化,看的是哪个指标?
- 如果让你来做,你怎么监听 dom 变化?
- 除了首屏耗时,还有别的评价性能的指标吗?
- 帧率怎么计算?
- 如果一个动画播放卡顿,应该如何解决?
- 异步请求不会阻塞动画吧?
- 如果是遍历巨大的数组,怎么样避免阻塞动画呢?
- 如果遍历巨大的数组伴随 dom 操作,就没法用 worker 了,怎么办?
- 还有别的办法吗?想想 react ?(思考了半分钟,沉默中……)
- 看过源码吗?有了解过 react fiber 吗?
- 面试官:其实思想是一样的
- 你刚刚说的是 fiber 增量更新的原理,那 reconciler 在面对长任务时是怎么处理的呢?
- 面试官:所以刚刚说的长任务也可以分批处理,避免阻塞渲染
- 简历上有提到缓存,那你说说 http 状态码 304 含义,什么情况下返回 304
- Options 请求是什么
- WebGL渲染过程(因为简历写了解WebGL)
- 小程序分包加载时,各个包之间是如何避免命名冲突的?
答:首屏耗时,业界衡量首屏性能一般有FCP(First Contenful Paint)、LCP(Largest Contentful Paint),公司内部用的是体感耗时,指的是从打开页面到 dom 不再变化的耗时。
(不知道,事后查了是 Mutation Observer)
答:FPS:帧率,每秒渲染的帧数,在简历写的 3D 项目中用的这个指标衡量性能
答:公司内部引擎暴露了一个生命周期函数,会在每一帧时调用,形参是当前帧的耗时,可以依据这个来算。我理解底层依赖的应该是 requestAnimationFrame。因为 requestAnimationFrame 会在浏览器渲染下一帧之前执行。
答:用 Chrome 的 lighthouse 面板分析是哪些帧卡顿,看是不是因为在这段时间用开销巨大的 js 任务在执行。比如如果页面中有很多串行的异步请求,改成并行。
答:确实,我刚刚说错了,异步请求线程和 GUI 渲染线程是独立的,不影响,JS 线程才会阻塞 GUI 线程。如果有开销巨大的 js 任务,比如可能是遍历一个巨大的数组
答:用 web worker 单独开一个线程执行这个任务。
答:看这个数组里哪些项的遍历和可视区内的 dom 有关,就先执行这部分,其他部分等用户滑动页面,可视区 dom 变化了再执行其他任务。(事后看感觉这里就是在胡扯)
答:了解过,但这跟刚刚的问题好像没有关系诶
答:react 会解析 jsx 生成 fiber 树,当需要更新时,reconciler 会构建新的 fiber 树,每个 fiber 节点保存了当前节点需要更新的 props 和更新的方式。然后将 rootFiberNode 指向这个新的 fiber 树。
答:reconciler 会把长任务拆分成多个子任务,每一帧作为一个时间切片,每个时间切片里默认预留 5ms 去渲染视图(这里事后复盘发现说错了,应该是预留 5ms 执行拆分出的子任务,直到所有子任务执行完)
(内心 OS: 三流前端学技术,二流前端学方法,一流前端学思想,面试官不愧是大佬)
答了协商缓存的过程
答:复杂请求(比如 PUT、DELETE 请求)跨域时会客户端先发起一个 options 预检请求,响应头里 access-control-allow-origin 如果包含请求方的域名,则表示可以跨域,接下来正式发起请求,否则直接在这一步被拦下,后续不再发起请求。
(不知道,简历上提到了分包加载,但是没了解背后原理,是自己的问题)
以下是 ChatGPT 的回答:
小程序分包加载机制设计时,为了避免不同包之间的变量命名冲突,主要依靠以下几种策略:
- 模块化封装:每个分包内的代码应当遵循模块化编程的原则,使用ES6的import/export或者CommonJS的require/module.exports(取决于使用的开发环境和规范),将功能封装在模块内部。这样,只有通过明确的导入语句才能访问到其他模块或包中的变量,减少了全局作用域污染的风险。
- 命名空间或包名前缀:为每个分包内部的全局变量添加特定的前缀或使用命名空间(Namespace)模式,这样即便两个分包中有相同名字的变量,由于前缀或命名空间的不同,它们也是唯一的。
- 严格模式:在开发环境中启用严格模式(use strict),这有助于检测潜在的变量作用域问题,鼓励开发者遵循更安全的编码习惯。
- 编译时静态检查:使用TypeScript等静态类型检查工具,可以在编译阶段发现潜在的命名冲突问题。TypeScript通过定义模块和接口,可以在编译时就强制实施命名规则,减少运行时冲突的可能性。
- 分包隔离:小程序的分包机制本身设计为相对独立的空间。每个分包有自己的全局作用域,主包和分包之间、分包与分包之间不共享全局变量。因此,只要不在全局作用域定义变量,而是通过模块导入导出,就能有效避免冲突。
- 配置明确的依赖关系:在小程序的配置文件(如uni-app的pages.json)中明确指定各分包的依赖关系和入口,通过清晰的配置管理各个包的加载顺序和范围,进一步减少冲突可能。
最后:两个 easy 数组题
反问环节:问了面试官组内负责的业务
#前端面经#