当前位置: 首页 > java >正文

得物前端二面面经总结

1.倒计时组件

2.如何实现精确计时(setInterval 1s先就update以前知道写但没考虑到为什么,时间戳同步)

3. React代码查看潜在错误

3.1 组件嵌套定义在组件内(不推荐,提到外面或者至少要一个useCallback防止重新渲染)

4. 弱网环境下,PerformaceObserver connection.effectType,是4G但真实网络不好(如何做?)

5.Next优点(服务端渲染,渲染策略,SEO【总忘记!!!】)

6.高端设备电量低时也可能出现卡顿(如何解决?监测渲染帧数,帧数过低采样降级方案)

7.TTFB如何降低时间(CDN【知道又没说出来!!!】、Next流式渲染)


下面按你列的 1–7 条逐条给出实战建议 + 可复制代码 + 常见坑 & 解决方案,尽量把设计思路、实现要点和可落地的步骤都写清楚(会标注重要参考文档)。我直接给出可用代码与执行步骤,你可以直接复制到项目里试验。


1. React 倒计时组件(推荐实现 — 抗抖/无漂移)

核心思路:不要把“每次 -1s”当作真时间;用绝对时间戳Date.now()performance.now())去算剩余时间,然后按到下一个秒边界调度下一次更新(或在最后 1s 内用 requestAnimationFrame 平滑更新)。这样即便某次 tick 延迟,下一次仍会与真实时间同步,避免累计漂移。

示例(可直接用):

// Countdown.jsx
import React, { useEffect, useState, useRef } from 'react';/*** props:*  - endAt: number (timestamp ms) 或 Date*  - onFinish?: () => void*  - tickMs?: number (minimal tick granularity, default 1000)*/
export default function Countdown({ endAt, onFinish, tickMs = 1000 }) {const endTs = typeof endAt === 'number' ? endAt : endAt.getTime();const [remaining, setRemaining] = useState(Math.max(0, endTs - Date.now()));const mounted = useRef(true);useEffect(() => {mounted.current = true;// initial syncfunction update() {const now = Date.now();const rem = Math.max(0, endTs - now);if (!mounted.current) return;setRemaining(rem);if (rem === 0) {onFinish?.();return;}// Align next update to wall-clock second boundary (or tickMs)const delay = Math.min(tickMs,1000 - (now % 1000) // align to next second for nicer UX);// If <1s left, use requestAnimationFrame for smoothnessif (rem <= 1000) {requestAnimationFrame(update);} else {setTimeout(update, delay);}}update();return () => {mounted.current = false;};}, [endTs, onFinish, tickMs]);const sec = Math.ceil(remaining / 1000);const mm = Math.floor(sec / 60);const ss = sec % 60;return (<div>{mm}:{String(ss).padStart(2, '0')}</div>);
}

要点与扩展:

  • 如果需要 跨客户端精确一致(比如活动倒计时),由服务端提供 serverNow + endAt,客户端计算 offset = serverNow - Date.now(),把 endAt - offset 当作本地目标时间(校准时钟偏差)。
  • 如果你使用 setInterval(1000) 直接修改 state,会出现“漂移” —— 正确做法是像上面那样每次由绝对时间计算剩余。参见 Dan Abramov 关于 setInterval 的经典建议(hooks 模式)。(overreacted.io)

2. 如何实现精确计时(为什么 setInterval(1000) 会漂移)

原因简述:

  • setInterval/setTimeout 只能保证“至少”在指定延迟后调用;主线程被占用或浏览器节流会推迟执行,导致误差并累积。
  • 解决方案:基于时间戳计算差值Date.now()performance.now()),不要依赖累计加法。若需要更高分辨率(短时间量测),用 performance.now()。有关实现细节与 Hook 模式可参考 Dan Abramov 的文章(声明式 setInterval 写法)。(overreacted.io)

另外两种常用技巧:

  • 初次马上渲染:组件 mount 时立即 tick(),避免第一次要等 1s 才看到 UI。
  • 合并更新:把频率高但可合并的 state 更新(比如秒数显示)统一到一个计时器里,减少 render 次数。

3. React 代码中常见潜在错误(并举例 & 修复)

3.1 在组件内嵌套定义子组件(你已提到)

问题:在父组件函数体内定义子组件会在每次 render 时重新创建函数(组件身份改变),会导致:

  • 传给 React.memo 的子组件无法复用(因为引用不稳定);
  • 可能触发额外的 DOM diff / 挂载开销;
  • 且如果把该子组件作为 prop 传入别处,比较会失败。

示例(反模式)

function Parent() {const Child = ({onClick}) => <button onClick={onClick}>A</button>;return <Child onClick={() => console.log('hi')} />;
}

修复:把 Child 抽出到外层模块(同文件也可以,但在组件外部定义),如果传回调要避免每次产生新引用,使用 useCallback。如果必须在组件内依据 props 动态生成函数/JSX,考虑用 useMemo 或用 key 控制挂载,但通常把组件移出最简单有效。多参考 Kent C. Dodds 的最佳实践。(kentcdodds.com)

其他常见问题:

  • Interval 回调闭包“stale”:在 useEffect 中直接用闭包会拿不到最新 state。解决:Dan 的 useInterval 模式,用 useRef 保存最新回调(见上方链接)。(overreacted.io)
  • 没 cleanup:忘了 clearInterval / cancelAnimationFrame 导致内存泄漏或多次计时器。
  • 依赖数组写错useEffect 依赖不到位会导致奇怪重建或没重建,避免把函数体内的临时计算也放入依赖,或用 useCallback 稳定引用。
  • 在开发环境误测:React dev-mode 会做额外渲染(Strict Mode double invoke),性能测试要在生产构建下进行。

4. 弱网环境下的策略(navigator.connection.effectiveType / PerformanceObserver)

要点:

  • 浏览器提供 Network Information API(navigator.connection.effectiveType / saveData),可以用作初步判定网络“感知质量”,但这并非在所有浏览器都可靠(支持度不统一)——要有降级方案。(MDN Web Docs)
  • 更可靠的做法是 主动探测(短小的 HEAD/fetch 请求测 RTT / 下载几个小资源测速),并结合真实 RUM 数据动态调整策略。
  • Save-Data(客户端提示/HTTP header)可用于服务端决定返回低流量版本。可以在服务端接收 Save-Data(或 navigator.connection.saveData)并 adaptive serve。(web.dev)

示例检测代码(客户端):

// quick network sniff
const conn = navigator.connection || {};
const effective = conn.effectiveType; // '4g'|'3g'|...
const saveData = conn.saveData;// fallback measure RTT
async function measureRtt(url = '/rtt-ping') {const t0 = performance.now();await fetch(`${url}?_=${Math.random()}`, { method: 'HEAD', cache: 'no-store' });return performance.now() - t0;
}

自适应策略示例:

  • 当检测为 poor(effectiveType 小于 ‘4g’ 或 RTT 很高)或 saveData 为 true:

    • 推迟或不加载大图 / 替换为低质量占位图(LQIP);
    • 取消自动视频播放,延迟加载第三方脚本(analytics、chatbot);
    • 将 polling 频率降级、合并网络请求。
  • 服务端:基于 client hints / Save-Data / Accept-CH 做“内容协商” -> 返回更轻量 HTML/图片/压缩格式(webp/avif)或更简单版页面。

另外:可以用 PerformanceObserver 监听 longtask / long-animation-frame 来判断主线程是否被卡住,从而在 UI 侧做降级(暂停动画、降低刷新频率)。示例:PerformanceObserver 观察 longtask(如果浏览器支持)。(MDN Web Docs)


5. Next.js 优点(把“SEO”这点一定记住!!!)

Next.js 的核心优势总结(用于说服产品/写 PR 的要点):

  • 多种渲染策略:SSG(静态生成)、SSR(每次请求服务端渲染)、ISR(增量静态再生)——能针对不同页面选择最佳策略以兼顾首屏速度与数据新鲜度。适用场景:静态营销页用 SSG,用户仪表盘用 SSR,海量内容目录用 ISR。(nextjs.org)
  • Streaming / Suspense 支持:App Router + React 18 Streaming 能把页面分块逐步发送,降低感知首屏时间(可先显示关键内容,再流式挂载非关键块)。对复杂页面展示体验提升大。(nextjs.org)
  • SEO(非常重要):服务端或静态渲染能让搜索引擎直接抓取完整 HTML、元信息、OG 标签,从而改善索引和展示;并且 Next.js 提供 metadata 管理、自动优化(image、fonts)、更好的 Core Web Vitals。别忘了以 SSR/SSG 帮助 SEO 这一点向产品方强调。(nextjs.org)
  • 内建优化:image optimization、自动分包、next/script 优化加载顺序、支持 Edge runtimes 等,能直接提升 LCP/TTFB 等指标。(nextjs.org)

落地建议(Next.js 项目):

  • 将非个性化页面尽可能 SSG(getStaticProps + revalidate),并用 CDN 缓存;
  • 对用户个性化页面考虑 SSR 或 Edge Functions(把轻量化逻辑放到边缘,缩短网络往返);
  • 在需要时采用 streaming + Suspense 加速感知首屏。

6. 高端设备电量低也会卡顿 —— 怎么做(监测帧率 + 采样降级方案)

原因回顾:很多平台/浏览器在“省电/节能”模式下会降低刷新率或 CPU 调度(Chrome 的 Energy Saver、移动设备的省电模式,或设备热控降频),这会使即便是高端设备在低电量时也出现卡顿/掉帧。浏览器会通过限制 requestAnimationFrame 调用频率、降低渲染刷新来节能。(Chrome for Developers, community.arm.com)

推荐做法(检测 + 自动降级):

  1. 实时测 FPS(采样)。简单 hook:
import { useEffect, useRef, useState } from 'react';
export function useFPS(interval = 1000) {const [fps, setFps] = useState(60);const frames = useRef(0);const last = useRef(performance.now());useEffect(() => {let raf;function loop(now) {frames.current++;const delta = now - last.current;if (delta >= interval) {const _fps = Math.round((frames.current * 1000) / delta);setFps(_fps);frames.current = 0;last.current = now;}raf = requestAnimationFrame(loop);}raf = requestAnimationFrame(loop);return () => cancelAnimationFrame(raf);}, [interval]);return fps;
}
  1. 采样 + 阈值:例如,如果 fps < 30 且持续 2 秒 -> 切换降级模式(全局 feature flag)。

  2. 降级动作(从温和到激进):

    • 关闭或简化动画(CSS 替代 JS 动画,或 prefers-reduced-motion 检测);
    • 降低 canvas/WebGL 渲染分辨率(render scale)与粒子数;
    • 减少轮询/长轮询频率,合并请求;把复杂任务移到 Web Worker;
    • 延迟或取消非关键组件渲染(懒加载、placeholder);
    • 在低帧率下暂停高频 UI 更新(如可视化的帧率控制)。
  3. 告知用户(如果合适):当设备进入省电模式可考虑显示“省电模式,已降级效果”的小提示。

你还可以结合 PerformanceObserverlong-animation-frame / longtask entry 来侦测卡顿热点并回收/优化对应 JS 代码。(Chrome for Developers, MDN Web Docs)


7. TTFB 如何降低(最详细的对策和对应方案,优先级 + 具体实现)

TTFB(Time To First Byte)反映服务器准备并开始发送响应的速度,改善它对 FCP/LCP 与 SEO 都有重要帮助。web.dev 的优化建议可作为基准:争取 TTFB ≤ ~800ms(75%用户),理想更低。(web.dev)

下面把可执行方案按优先级(高 → 中 → 低)列出,并给出 Next.js / infra 对应实现建议。

优先级:高(先做能最快见效的)

  1. 使用 CDN,缓存 HTML/静态资源到边缘

    • 静态页面尽量用 SSG 并缓存到 CDN(静态资源直接由 CDN 提供,靠近用户显著降低网络时延)。web.dev 指出 CDN 对 TTFB 有直接帮助。(web.dev)
    • Next.js:使用 getStaticPropsexport 的页面由 CDN 缓存;在服务端渲染时设置合适 Cache-Control(s-maxage + stale-while-revalidate)。
    • 示例 next.config.js headers(设置 s-maxage / stale-while-revalidate):
// next.config.js
module.exports = {async headers() {return [{source: '/(.*)',headers: [{ key: 'Cache-Control', value: 'public, s-maxage=60, stale-while-revalidate=86400' }]}]}
}
  1. 把能静态化的页面静态化(SSG/ISR)

    • 对于能提前构建的页面用 SSG;对大规模内容用 ISR(revalidate)来兼顾速度与更新。Next.js 的 ISR 可以让很多页面在 CDN 缓存下直接命中,显著降低 TTFB/后端负载。(nextjs.org)
    • 示例:
export async function getStaticProps() {const data = await fetchSomeData();return { props: { data }, revalidate: 60 }; // revalidate every 60s
}
  1. 减少服务端阻塞时间(优化后端)

    • 检查最慢的 DB 查询、网络调用,增加缓存(Redis / memcache)、加索引、改进查询、使用异步批处理。
    • 把非关键路径工作改为“异步后台作业”(不要在请求上做 heavy CPU 或 IO)。
  2. 启用 HTTP/2 或 HTTP/3(QUIC)

    • 减少握手与复用 TCP 连接的延迟(许多 CDN/云端默认支持 HTTP/2/3)。

优先级:中(需要工程/infra 协同)

  1. Early Hints (HTTP 103) — 给浏览器预热子资源

    • Server 发送 103 Early Hints 提醒浏览器提前 preload/preconnect,浏览器可并行拉关键资源即使主 HTML 还未到达,从而缩短感知首屏。不是所有平台都支持,但主流浏览器支持 103 以提升性能(Cloudflare / CDN 也可做)。(MDN Web Docs, Cloudflare Docs)
  2. 开启边缘/Edge Rendering

    • 把简单的 SSR / 个性化逻辑移到 CDN edge(如 Cloudflare Workers / Vercel Edge)可缩短往返时延,从而降低 TTFB(尤其是跨地域用户)。
  3. 压缩与传输优化

    • 启用 Brotli / gzip,缩小 payload;
    • 设置 Keep-Alive,合理TTL,避免不必要的重定向;
    • preconnectdns-prefetch 加速第三方域连接(配合 Early Hints 更好)。

优先级:低(收益但实现量大)

  1. Server-side streaming(流式 SSR)

    • 在 Next.js App Router + React 18 中,Streaming 能把首要部分尽快发送(降低感知首次可见时间),但要写好 Fallback/Loading 组件和 Suspense。(nextjs.org)
  2. HTTP/2 server push(谨慎) — 现在基本由 Early Hints + preload 替代,推送管理复杂。

  3. 边缘缓存与更细粒度的缓存策略

    • 针对用户会话或个性化做 smart cache key;用 stale-while-revalidate 提高命中率。

验证与监控(必须)

  • 用 Lab 和 RUM 双管齐下

    • Lab:WebPageTest / Lighthouse(测 TTFB、FCP、LCP);
    • RUM:采集真实用户的 TTFB(PerformanceNavigationTiming RUM + Back-end traces)。
  • 持续化:设置阈值告警(TTFB P75/P95),把改动和测量做成 CI gate。

实战示例:Next.js 上把 TTFB 降低的快速 checklist

  1. 把静态内容放 CDN(或启用 Vercel/Netlify 的边缘缓存);
  2. 把尽量多的页面改为 getStaticProps/ISR(或 Edge static);
  3. 为 SSR 路由减少后端计算:预热缓存,缓存 DB 查询,使用 Redis;
  4. 在 server 层(Node 或 edge)发送 103 Early Hints 提示 preload(若 CDNs 支持,则在 CDN 配置里开启);
  5. 启用 Brotli 压缩、开启 HTTP/3、减少重定向;
  6. 测量与回归:WebPageTest/Lighthouse before/after,并用 RUM 确认真实用户体验。

参考资料(官方/权威):

  • web.dev 的 TTFB 优化指南与 CDN 建议。(web.dev)
  • MDN 的 103 Early Hints 描述(如何工作,浏览器行为)。(MDN Web Docs)

结语 + 我可以立刻提供的交付物

我把关键点、具体代码和可落地的行动清单都给你了。下一步我可以立刻(任选其一):

  • 把上面的倒计时组件改成你项目里的样式并做 unit tests;
  • 为你项目写一个 “TTFB 改善 PR checklist + next.config.js 示例”;
  • 给出一个 FPS 监测 + 自动降级的全局 hook 并示例集成到你的 App Shell。

你想先要哪一种输出?(或者把你现有的 Countdown / next.config.js 贴出来,我直接在你现有代码上改写并把差异给你)


主要参考

  • Dan Abramov — Making setInterval Declarative with React Hooks(定时器/Hook 模式). (overreacted.io)
  • MDN — Network Information API / navigator.connection(effectiveType / saveData). (MDN Web Docs)
  • web.dev — Save-Data / Adaptive loading(客户端与服务端自适应). (web.dev)
  • Next.js 官方文档 — Streaming(App router)与 SSR/SSG/ISR 说明. (nextjs.org)
  • web.dev — Optimize TTFB(TTFB 优化实践). (web.dev)

如果你要我立刻把其中某一项(比如倒计时组件或 FPS hook)改成你项目的“即插即用”版本,贴你当前代码 / 说明目标(样式、时区、server time sync)我就直接给出 PR-ready 的修改。

http://www.xdnf.cn/news/20375.html

相关文章:

  • LeetCode_数学
  • 解析、创建Excel文件的开源库OpenXLSX介绍
  • ES06-SpringData集成
  • Valgrind检测内存泄漏入门指南
  • ClickHouse 中的物化列与物化视图
  • SpringBoot01-配置文件
  • 未来教育行业的 Go 服务开发解决方案与实践
  • 【PyTorch实战:Tensor】4、NumPy与PyTorch Tensor指南:深度学习中的数据操作与转换
  • Python基础(①⑧Queue)
  • 机床夹具设计 +选型
  • 持续集成和持续交付 (CI/CD) 工具——Jenkins
  • `objdump`与`addr2line`工具详解
  • 新服务器初始化:Git全局配置与SSH密钥生成
  • 【Canvas与图标】古铜色“HTML”图标
  • eclipse 安装 lombok
  • 【基础-单选】下列哪一项不属于ArkUI组件的公共事件?
  • JVM调优总结
  • ECharts Gallery:Apache官方数据可视化模板库,助你快速制作交互图表并实现深度定制
  • 微服务的编程测评系统22-项目部署结束
  • 基于Echarts+HTML5可视化数据大屏展示-图书馆大屏看板
  • 软考 系统架构设计师系列知识点之杂项集萃(142)
  • JVM中如何调优新生代和老生代?
  • 基于LSTM深度学习的网络流量测量算法matlab仿真
  • C++ 内存模型:用生活中的例子理解并发编程
  • linux C 语言开发 (三) 建立云服务器
  • C++ 小游戏:拍桌子
  • Nmap网络扫描工具详细使用教程
  • 算法学习路径
  • 基于 Gemini 的 CI/CD 自动化测评 API 集成实战教程
  • Browser Use:打造你的浏览器自动化助手