前端性能监控(面试常见)

本文介绍了WebVitals中的核心网络指标,如FCP、LCP、INP和CLS,以及如何通过Chrome工具、JavaScript库进行测量和优化。同时强调了前端项目稳定性的保障措施,包括开发流程规范、架构设计、质量保证和性能优化等方面。
摘要由CSDN通过智能技术生成

1. 用户体验优化

2. Web Vitals提取了几个核心网络指标

哇一头死 FCL 三大指标 FID被 INP干点

  • Largest Contentful Paint (LCP)最大内容绘制 衡量加载性能。 为了提供良好的用户体验,LCP 必须在网页首次开始加载后的 2.5 秒内发生。
  • Interaction to Next Paint (INP):替代首次输入延迟 (FID) 衡量互动。为了提供良好的用户体验,网页的 INP 不得超过 200 毫秒INP测量的是从用户与网页发生交互那一刻起到浏览器完成与该交互相关的下一个渲染帧(Paint)的时间间隔。
    • INP 是 First Input Delay (FID) 的继任指标。虽然两者都是响应能力指标,但 FID 仅测量了页面上首次互动的输入延迟。INP 通过考虑所有页面互动(从输入延迟到运行事件处理程序所需的时间,再到浏览器绘制下一帧)来改进 FID。
    • 这些差异意味着 INP 和 FID 是不同类型的响应能力指标。FID 是一项旨在评估网页对用户的首次展示的加载响应能力指标,而无论网页互动的生命周期是何时发生,INP 都是更可靠的整体响应能力指标。
  • Cumulative Layout Shift (CLS)累计布局偏移,衡量视觉稳定性。为了提供良好的用户体验,必须将 CLS 保持在 0.1. 或更低。

3. 测量工具

野外工具

实验工具

4. 如何优化FCP

5. 如何优化 INP

  • 识别并减少输入延迟
    • 启动期间脚本评估和耗时较长的任务之间的关系
  • 优化事件回调
    • 频繁让出主线程
    • 避免布局抖动
  • 最大限度减少展示延迟时间
    • 遵从请求,以便更快执行渲染工作
    • 尽可能减小 DOM 大小
    • 使用 content-visibility 延迟渲染屏幕外元素
    • 注意使用 JavaScript 呈现 HTML 时的性能开销

6. 如何优化CLS

  • 没有尺寸的图片
  • 广告、嵌入内容和其他延迟加载的内容预留空间
  • 动画
  • 网络字体(使用无样式文本的 flash、将后备字体与网页字体交换)

7. 纯 js 如何检查当前页面是否白屏

检测当前页面是否出现白屏现象,可以采用以下几种纯 JavaScript 方法:

  1. 利用window.onloadDOMContentLoaded事件
    当页面加载完成或初始HTML文档解析完毕时,触发相关事件,然后检查页面是否为空白。这可以通过检查页面上是否存在非空白内容来实现,比如检查是否有可见的非空DOM元素或者特定类别的元素。
document.addEventListener('DOMContentLoaded', function() {
  const isEmpty = checkIfPageIsEmpty();
  if (isEmpty) {
    handleWhiteScreen(); // 定义处理白屏的函数
  }
});

function checkIfPageIsEmpty() {
  // 检查页面中是否存在非空白内容,如可见的非空DOM元素
  // 这里仅作为示例,实际逻辑可能需要更精细的判断
  return !document.querySelector(':not(script):not(style):not(noscript)');
}

function handleWhiteScreen() {
  console.error('Page appears to be blank.');
  // 可以在此处添加具体的白屏处理逻辑,如上报异常、显示提示信息等
}

  1. 利用requestAnimationFrame循环检测
    如果担心单纯依赖DOMContentLoaded事件可能无法捕捉到某些动态加载内容导致的白屏情况,可以使用requestAnimationFrame循环检查页面视觉上的空白状态。这种方法尤其适用于那些依赖异步加载内容填充页面的场景。
function detectWhiteScreen() {
  const bodyRect = document.body.getBoundingClientRect();
  const bodyIsWhite = bodyRect.width > 0 && bodyRect.height > 0 &&
                    window.getComputedStyle(document.body).backgroundColor === 'white';

  if (bodyIsWhite) {
    console.error('Page appears to be visually blank.');
    // 可能需要停止循环检测并执行处理逻辑
  } else {
    // 页面非白屏,继续监测下一帧
    requestAnimationFrame(detectWhiteScreen);
  }
}

// 在页面加载完成后开始检测
document.addEventListener('DOMContentLoaded', function() {
  requestAnimationFrame(detectWhiteScreen);
});

  1. 使用Canvas或getImageData进行像素级检测
    对于更为严格的白屏检测,可以利用canvas元素将页面内容绘制到画布上,然后通过getImageData获取像素数据,检查其中白色像素的比例。这种方法较为复杂,且可能受到跨域限制,但对于需要精确识别页面是否完全空白的应用场景可能有帮助。
async function checkPageForBlankness() {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');

  // 设置canvas大小与视口一致
  canvas.width = document.documentElement.clientWidth;
  canvas.height = document.documentElement.clientHeight;

  // 将整个页面内容绘制到canvas上
  ctx.drawWindow(window, 0, 0, canvas.width, canvas.height, 'rgb(255,255,255)', false);

  // 获取像素数据
  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  const data = imageData.data;

  let whitePixels = 0;
  for (let i = 0; i < data.length; i += 4) {
    // 检查是否为白色像素(通常为R=G=B=255,A不为0)
    if (data[i] === 255 && data[i + 1] === 255 && data[i + 2] === 255 && data[i + 3] !== 0) {
      whitePixels++;
    }
  }

  const whiteRatio = whitePixels / (data.length / 4);
  if (whiteRatio >= 0.95) { // 设置一个阈值判断是否接近全白
    console.error('Page appears to be visually blank.');
    // 处理白屏逻辑
  }
}

document.addEventListener('DOMContentLoaded', function() {
  // 注意:drawWindow方法需要浏览器提供特定权限,可能无法在所有环境下运行
  // 若支持,可在此处调用checkPageForBlankness()
});

注意:上述使用canvasdrawWindow的方法可能需要特定的浏览器权限(如chrome://flags/#enable-experimental-web-platform-features在Chrome中),并且可能不适用于所有浏览器环境。此外,这种方法可能因跨域问题导致无法获取到页面内容。

  1. 结合性能指标与MutationObserver
    利用浏览器提供的性能指标,如First Contentful Paint(FCP)或Largest Contentful Paint(LCP),结合MutationObserver来观察页面DOM的变化。如果这些关键渲染时间点过晚或者DOM变化不足以形成有意义的内容,可以视为白屏。
// 监听性能指标
if ('PerformanceObserver' in window) {
  const observer = new PerformanceObserver((entries) => {
    entries.forEach((entry) => {
      if (entry.entryType === 'paint') {
        if (entry.name === 'first-contentful-paint') {
          const fcpTime = entry.startTime;
          console.log(`First Contentful Paint at ${fcpTime.toFixed(2)}ms`);
          if (fcpTime > someThreshold) { // 设置一个阈值判断FCP是否过晚
            console.error('Possible white screen due to late FCP.');
          }
        }
      }
    });
  });
  observer.observe({ type: 'paint', buffered: true });
}

// 使用MutationObserver监测DOM变化
const targetNode = document.body;
const config = { childList: true, subtree: true };
const observer = new MutationObserver(checkForContent);

function checkForContent(mutationsList) {
  for (const mutation of mutationsList) {
    if (mutation.type === 'childList') {
      const hasVisibleContent = !!mutation.addedNodes.find(
        node => node.nodeType === Node.ELEMENT_NODE && node.offsetWidth > 0 && node.offsetHeight > 0
      );
      if (!hasVisibleContent) {
        console.warn('DOM changes did not introduce visible content.');
      }
    }
  }
}

observer.observe(targetNode, config);

综上所述,根据具体需求和应用场景,可以选择合适的方法或结合多种方法来检测当前页面是否白屏。请注意,由于浏览器兼容性和安全策略的差异,某些方法可能需要调整或无法在所有环境中使用。

8. 纯 js 如何实现检测当前可视区域渲染完成

检测当前可视区域(viewport)渲染完成,通常是指确认页面或其某个部分(如一个复杂的子组件)已完全呈现在用户视野内,并且所有相关的资源(如图片、字体、脚本等)已经加载完毕,动画效果已完成,用户可以进行无阻碍的交互。以下是一些使用纯JavaScript实现可视区域渲染完成检测的方法:

8.1. 1. 监听 load 事件

对于整个页面的渲染完成,可以监听 window 对象的 load 事件,它会在所有资源(包括图片、样式表、脚本等)加载完毕后触发。

window.addEventListener('load', function () {
  console.log('The entire page and its resources have finished rendering.');
});

8.2. 2. 监听 DOMContentLoaded 事件

如果关心的是初始HTML文档结构的加载和解析完成,而不是所有资源加载完毕,可以使用 DOMContentLoaded 事件。这通常发生在 load 事件之前,当DOM树构建完成且可被脚本操作时触发。

document.addEventListener('DOMContentLoaded', function () {
  console.log('The initial HTML document has been fully parsed and rendered.');
});

8.3. 3. 使用 IntersectionObserver API

对于检测特定元素是否进入可视区域且完全渲染,可以利用 IntersectionObserver API。它会异步观察目标元素与祖先元素或视口的交叉状态,并在状态改变时触发回调函数。设置合适的阈值(如1.0,表示完全可见),可以在元素完全进入可视区域时得到通知。

function handleIntersection(entries) {
  entries.forEach(entry => {
    if (entry.isIntersecting && entry.intersectionRatio === 1) {
      console.log('The observed element is fully visible within the viewport.');
      // 停止观察,避免重复触发
      observer.unobserve(entry.target);
    }
  });
}

const targetElement = document.querySelector('#your-element');
const observer = new IntersectionObserver(handleIntersection, { threshold: 1.0 });

observer.observe(targetElement);

8.4. 4. 配合 requestAnimationFrame 循环检查

对于更复杂的场景,比如需要确保某个元素内的所有子元素(包括动态加载的内容)都已完成渲染,可以结合 requestAnimationFrame 创建一个循环,定期检查元素及其子元素的状态。当所有预期条件满足时,停止循环。

function checkRenderCompletion(element) {
  // 在这里定义您的检查逻辑,比如检查子元素数量、计算布局、检查特定CSS属性等
  const isRendered = /* ... */;
  
  if (isRendered) {
    console.log('The targeted element and its content have finished rendering.');
    // 停止循环
    return;
  }

  requestAnimationFrame(() => checkRenderCompletion(element));
}

const targetElement = document.querySelector('#your-element');
checkRenderCompletion(targetElement);

8.5. 5. 监听特定资源加载事件

对于依赖特定资源(如图片、字体、异步脚本等)完成渲染的元素,可以监听这些资源的加载事件。例如,对于图片,可以监听 img 元素的 load 事件。

const images = document.querySelectorAll('img');
images.forEach(img => {
  img.addEventListener('load', function () {
    console.log('An image has finished loading.');
    // 根据需要,检查所有图片是否已加载完成,以确定整个区域渲染完成
  });
});

8.6. 6. 使用自定义加载指示器/回调

对于自定义加载逻辑(如使用加载库或组件),如果它们提供了加载完成的回调函数或状态指示器,可以直接使用这些接口来判断渲染完成。

const customLoader = new YourCustomLoader();
customLoader.onLoadComplete = function () {
  console.log('Custom loader has finished rendering its content.');
};

综上所述,选择合适的方法取决于具体的应用场景和需求。您可以单独使用或组合上述方法来准确检测当前可视区域的渲染完成状态。

9. 如何保障项目稳定性

从前端视角来看,保障项目稳定性主要关注以下几个方面:

  1. 规范化的前端开发流程
    • 遵循前端最佳实践和编码规范:如使用语义化的HTML,遵循CSS命名约定,编写可维护的JavaScript代码,确保代码风格统一,易于阅读和理解。
    • 代码审查:实施严格的代码审查制度,确保代码质量,及时发现并修正潜在问题,如DOM操作异常、内存泄漏、性能瓶颈等。
    • 版本控制与分支管理:使用Git进行版本控制,遵循明确的分支策略(如主干开发、特性分支、热fix分支等),确保代码合并过程中的稳定性。
  1. 健壮的前端架构设计
    • 模块化与组件化:采用模块化和组件化开发方式(如使用Webpack、Rollup进行模块打包,React、Vue等框架进行组件化开发),提高代码复用性,降低模块间耦合,便于维护和升级。
    • 状态管理:合理使用状态管理库(如Redux、Vuex、MobX等),确保应用程序状态的一致性和可预测性,减少因状态管理不当导致的UI渲染异常或数据混乱问题。
    • 路由管理:清晰的路由规划和管理(如React Router、Vue Router),确保页面跳转逻辑正确,避免路由冲突或未定义路由引发的错误。
  1. 全面的前端质量保证
    • 自动化测试
      • 单元测试:为关键逻辑、组件方法、钩子函数等编写单元测试,使用Jest、Mocha等测试框架,确保代码变更不影响既有功能。
      • 端到端测试:使用Cypress、Puppeteer等工具进行E2E测试,验证完整的用户交互流程和跨组件通信,确保整个应用的功能完整性和一致性。
      • 性能测试:利用Lighthouse、WebPageTest等工具进行性能基准测试和优化建议,关注加载速度、首屏渲染时间、可交互时间等关键指标。
    • 静态代码分析与 linting:使用ESLint、Stylelint等工具进行代码风格检查和潜在问题检测,预防常见的语法错误、未使用的变量、潜在的安全漏洞等。
    • 浏览器兼容性测试:使用Browserslist、Autoprefixer等工具确保代码兼容目标浏览器范围,利用BrowserStack、Sauce Labs等服务进行多浏览器、多设备的实际测试。
  1. 优化前端性能与用户体验
    • 资源优化:压缩、合并、懒加载、预加载等手段优化CSS、JavaScript、图片等资源,减少网络请求次数和体积,提升加载速度。
    • 响应式设计与无障碍访问:确保界面在不同屏幕尺寸和设备上适配良好,遵循WCAG标准提升无障碍性,提升用户体验的同时降低因兼容性问题引发的投诉或故障。
    • 错误捕获与用户反馈:使用try-catch、window.onerror、unhandledrejection等机制捕获并上报前端异常,提供用户反馈渠道,及时发现并修复问题。
  1. 监控与日志
    • 前端监控:集成RUM(Real User Monitoring)工具(如Google Analytics、 Sentry、Datadog等),收集用户端性能数据、异常信息、用户行为数据等,用于分析性能瓶颈、定位问题源头。
    • 前端日志:通过console.log、console.error、专门的日志库等方式记录关键操作、异常情况等信息,便于问题排查。
  1. 持续集成与部署
    • CI/CD流程:配置自动化构建、测试、部署流水线(如GitHub Actions、Jenkins、Travis CI等),确保每次代码变更经过充分验证后再发布到生产环境。
    • 版本控制与包管理:使用npm、yarn等包管理工具,遵循语义化版本控制,锁定依赖版本,防止第三方库更新引发的兼容性问题。

通过以上措施,从前端视角出发,可以系统性地保障项目的稳定性,确保用户在使用过程中获得流畅、一致且无明显故障的体验。同时,也为后续的维护、升级和扩展打下坚实基础。

  • 20
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值