抖音前端三面面经
概括
过去一年跳槽了两次,最近的一年都在面试,失败了很多次,也拿了很多offer,腾讯,字节,虾皮,滴滴都oc,最终人生的第三方份工作选择了腾讯,工作空闲之余,把最近一年的面经整理一下。
联系我:Chan-FE 可 腾讯内推~
抖音三面面经title list
- 介绍一个项目难点,如何解决的
- 介绍一下webpack tapable模块
- loader pitch有使用过吗,介绍一个它的应用
- style-loader原理
- 简单介绍一下SSR的原理
- SSR内存泄漏的话如何排查
- 项目FCP、CLS的统计标准是什么,具体做了什么使得CLS指标得到下降
- 除了技术上的优化,业务上有什么设计使得整体架构更合理吗(结合技术和业务来说)
- https的主动推送主要推送什么资源,需要全部都推送吗
- 怎么检测客户端是否兼容webp格式
- 技术选型
- React fiber的优势在哪里
- loadsh get的实现
- 实现一个const
- 1万张图片,并发下载10张,最快的方法下载完成
项目+八股
1.介绍一个项目难点,如何解决的
项目打包过慢,排查原因:输出缓存的tapable同步钩子报错,导致缓存失效
2.介绍一下webpack tapable模块
- 同步和异步两种
- 提供了阻断、瀑布、循环等流程控制
- 异步提供了串型、并行两种控制方式和 回调、promise两种实现方式
- https://www.cnblogs.com/dennisj/p/14538668.html
3.loader pitch有使用过吗,介绍一个它的应用
- 四种loader: post、inline、normal、pre
- 两种执行阶段 pitching和normal阶段
- Pitching 阶段: loader 上的 pitch 方法,按照
后置(post)、行内(inline)、普通(normal)、前置(pre)
的顺序调用。 - Normal 阶段: loader 上的 常规方法,按照
前置(pre)、普通(normal)、行内(inline)、后置(post)
的顺序调用。模块源码的转换, 发生在这个阶段。 - 应用style-loader
- 参考:https://juejin.cn/post/7037696103973650463
4.style-loader原理
css-loader 负责解析 CSS 文件的 @import 和 url()
依赖,并将 CSS 转换为 JavaScript 模块;style-loader 则负责将模块内容注入 DOM。如果不使用pitch,style得到的入参将是js代码,而不是处理好的css代码,style-loader 通过 Webpack 的 pitch
方法实现熔断。默认情况下,loader 从右向左执行(如 css-loader → style-loader
),但 pitch
方法允许从左向右执行。style-loader 的 pitch
方法会先执行,先直接跳过后续 loader 的默认处理流程,转而通过 require
手动调用 css-loader 获取 CSS 内容(后面loader将通过inline loader的形式执行)
5.简单介绍一下SSR的原理
将传统单页面应用(SPA)的渲染过程从客户端转移到服务器端,通过动态生成完整的 HTML 页面解决首屏加载性能与 SEO 问题。服务器在渲染可以执行组件定义的 数据预取逻辑,将异步获取的数据直接嵌入 HTML 中。客户端收到 HTML 后,会先快速展示静态内容(提升首屏速度),随后加载客户端 JavaScript 文件。框架通过 Hydration 机制 将事件绑定、状态管理等逻辑“注入”已渲染的静态 DOM,使其具备交互能力。
6.SSR内存泄漏的话如何排查
比较堆栈信息,第三方工具实时监控内存变化
7.项目FCP、CLS的统计标准是什么,具体做了什么使得CLS指标得到下降
- FCP:用户首次看到页面中元素的时间
- CLS:页面渲染过程中非预期布局波动的计算分数
- 降低cls
8.除了技术上的优化,业务上有什么设计使得整体架构更合理吗(结合技术和业务来说)
业务:
- 关键资源去配置化,减少网络请求
- 简化业务流程
技术:
- 优化打包机制,均衡切割chunk
- 合并接口,减少网络请求
- 整合全局token,减少非必要的鉴权校验
- https做资源推送,搭配容器做缓存
9.https的主动推送主要推送什么资源,需要全部都推送吗
- 首屏关键资源(字体、样式等),动态资源需要谨慎推送
- 若推送的资源已被浏览器缓存,会造成重复传输。
- 推送过多资源会占用带宽,反而拖慢页面加载速度。
10.怎么检测客户端是否兼容webp格式
- canvas的toDataURL判断
- 请求头Accept字段判断
- 加载一个1像素的空白webp图片判断
- 使用picture标签做兼容
- https://juejin.cn/post/6844903858028675079
11.技术选型
- hybird架构
- RN原生控件渲染
- flutter自研渲染引擎
- 其他跨段方案
12.React fiber的优势在哪里
- 大任务拆分成小任务
- 两颗diff树相互引用,减少diff导致的崩溃
- 增加指针指向父元素、兄弟元素,空间换时间
- 闭包+链表使得函数组件拥有了数据持久化的能力,hook开始发展
算法
13.loadsh get的实现
//lodash的get方法 function get(object, path, defaultValue = 'undefined') { //构造数组,将'['和']'替换成'.' let newPath = []; newPath = path.replace(/\[/g, '.').replace(/\]/g, '').split('.'); return newPath.reduce((a, b) => { return (a || {})[b] }, object) || defaultValue } //测试 const obj = { a: { b: [{ c: 1 }] } } console.log(get(obj, 'a.b[0].c[1].e[2][1].e', 0)); console.log(get(obj, 'a.b[0].c', 0)); console.log(get(obj, 'a.b.c', 0)); console.log(get(obj, 'a', 0));
14.实现一个const
function _const(key, value) { const desc = { value, writable:false }; Object.defineProperty(window, key, desc); } _const('obj', {a: 1}); //定义obj obj.b = 2; //可以正常给obj的属性赋值 obj = {} //抛出错误,提示对象read-only
15.1万张图片,并发下载10张,最快的方法下载完成
const data = [ { url: '/a', time: 200 }, { url: '/b', time: 1000 }, { url: '/c', time: 100 }, { url: '/d', time: 800 }, { url: '/e', time: 300 }, ] const loadUrl = (item) => { return new Promise((resolve, reject) => { setTimeout(resolve, item.time, item.url); }); } const downLoad = (data, limit) => { // 截取前 limit 个数据, const promiseList = data.splice(0, limit).map((item, index) => { return loadUrl(item).then((res) => { console.log(res); return index; }); }); (async () => { let p = Promise.race(promiseList); for(let i = 0; i < data.length; i++) { p = p.then(index => { promiseList[index] = loadUrl(data[i]).then((res) => { console.log(res); return index; }); return Promise.race(promiseList); }) } })() } downLoad(data, 2);
搞了个公 众 号*********,感兴趣的可以关注一下~
#面经#