一、设备与浏览器环境检测
1.1 用户设备类型判断
在跨端开发中,准确识别用户设备类型是实现响应式布局的基础。传统方案依赖navigator.userAgent字符串解析,但存在维护成本高、容易被篡改的问题。现代方案推荐使用User-Agent Client Hints API,通过响应头Accept-CH: Sec-CH-UA-Platform获取标准化设备信息。
// 示例:通过Client Hints获取设备类型async function getDeviceType() {const hints = await fetch('/api/hints', {headers: { 'Accept-CH': 'Sec-CH-UA-Platform' }});const platform = hints.headers.get('Sec-CH-UA-Platform');return /Android|iPhone/i.test(platform) ? 'mobile' : 'desktop';}
1.2 页面可见性检测
Page Visibility API可有效监测用户是否处于当前标签页,常用于视频播放暂停、数据上报优化等场景。通过监听visibilitychange事件,结合document.visibilityState属性实现:
document.addEventListener('visibilitychange', () => {if (document.visibilityState === 'hidden') {console.log('页面进入后台');// 暂停非关键任务} else {console.log('页面回到前台');// 恢复任务执行}});
二、性能优化实战
2.1 长任务(Long Task)监控
主线程阻塞超过50ms的任务会被标记为长任务,直接影响页面响应速度。使用PerformanceObserver监听longtask条目:
const observer = new PerformanceObserver((list) => {list.getEntries().forEach(entry => {console.warn(`Long task detected: ${entry.duration}ms`);// 可上报至监控系统});});observer.observe({ entryTypes: ['longtask'] });
2.2 静态资源加载耗时统计
全站资源性能监控需结合PerformanceResourceTiming接口,通过performance.getEntriesByType('resource')获取所有资源加载数据:
function logResourceTimings() {const resources = performance.getEntriesByType('resource');resources.forEach(res => {console.log({name: res.name,duration: res.duration,initiatorType: res.initiatorType});});}// 在页面卸载前触发window.addEventListener('beforeunload', logResourceTimings);
2.3 大文件分片上传优化
分片上传需解决三个核心问题:分片大小选择、并发控制、断点续传。推荐采用动态分片策略:
const CHUNK_SIZE = 5 * 1024 * 1024; // 初始5MBasync function uploadFile(file) {const totalChunks = Math.ceil(file.size / CHUNK_SIZE);const uploadTasks = [];for (let i = 0; i < totalChunks; i++) {const start = i * CHUNK_SIZE;const end = Math.min(start + CHUNK_SIZE, file.size);const chunk = file.slice(start, end);uploadTasks.push(fetch('/upload', {method: 'POST',body: chunk,headers: { 'Content-Range': `bytes ${start}-${end-1}/${file.size}` }}));}await Promise.all(uploadTasks);}
三、工程化实践方案
3.1 防重复请求机制
实现请求防重需结合请求标识与锁机制。推荐使用AbortController取消重复请求:
const pendingRequests = new Map();async function fetchWithLock(url, options) {if (pendingRequests.has(url)) {pendingRequests.get(url).abort();}const controller = new AbortController();pendingRequests.set(url, controller);try {const response = await fetch(url, {...options,signal: controller.signal});pendingRequests.delete(url);return response;} catch (err) {if (err.name !== 'AbortError') {pendingRequests.delete(url);throw err;}}}
3.2 精准埋点数据上报
浏览器关闭前的埋点上报需使用navigator.sendBeacon(),该方法允许在页面卸载阶段可靠发送小数据量请求:
window.addEventListener('beforeunload', () => {const analyticsData = JSON.stringify({event: 'page_exit',timestamp: Date.now()});const success = navigator.sendBeacon('/api/analytics',analyticsData);if (!success) {// 降级方案:使用同步XMLHttpRequest或localStorage暂存localStorage.setItem('pendingAnalytics', analyticsData);}});
3.3 Git错误定位技巧
当需要定位引入错误的commit时,可使用git bisect进行二分查找:
# 启动二分查找git bisect start# 标记已知的正确commitgit bisect good v1.0.0# 标记已知的错误commitgit bisect bad main# 自动测试脚本(需自定义)git bisect run ./test-script.sh
四、进阶资源推荐
- 刷题平台:某代码托管平台提供的前端面试题库(含200+场景题)
- 性能工具:行业常见技术方案的Lighthouse集成方案
- 监控系统:开源APM工具集,支持自定义Long Task监控
- 学习路径:前端性能优化专项课程(涵盖Resource Timing API深度解析)
掌握这些核心场景题的解决思路,不仅能应对面试挑战,更能在实际项目中提升开发质量。建议结合具体业务场景进行实践验证,持续优化技术方案。