LogoLogo
github
  • 💪Upupup
  • React
    • hook
    • redux
    • Router
    • umimax+nest.js 实现 权限管理系统
    • umimax + Nest.js 实现权限管理系统
  • Vue
    • effectScope 是干啥的
    • Object.assign()
    • 响应式理解
    • @babel/preset-env 问题
    • 自定义指令
    • 问题及解决
    • 🧐权限管理(动态路由)
  • docker
    • Docker 常用命令
    • Docker部署遇到的问题
    • Docker Compose 常用命令
    • docker修改daemon.json
    • jenkins
    • Jenkinsfile 语法进阶
    • nginx配置
    • 问题
    • 玩转Nginx:轻松为Docker部署的服务添加域名的完美指南
    • Docker部署前后端项目:经验分享与问题解决
  • git
    • command
    • problem
    • rebase实践
  • 前端开发面试题集
    • CSS 面试题
    • 前端工程化面试题
    • HTML 面试题
    • JavaScript 面试题
    • NestJS 面试题
    • Node.js 面试题
    • 性能优化面试题
    • React 面试题
    • 安全面试题
    • Vue 面试题
  • interviewer
    • 计算机网络
    • 性能优化
  • leetcode
    • 算法
      • 分治算法
      • 滑动窗口与双指针
        • 🦸定长滑动窗口
        • 🚴不定长滑动窗口
        • 🚴‍♂️单序列双指针
      • 回溯
      • 二分法
  • nestjs
    • mail
    • mini-order
    • nestjs
    • prisma
    • 登录注册
  • nextjs
    • 用 V0 和 Cursor 实现全栈开发:从小白到高手的蜕变
  • tauri
    • 思路
    • 自动通知应用升级
  • vite
    • vite实现原理
  • webpack
    • 资料
  • 工具
    • Eslint
    • jenkins
    • 关于cicd
  • 微信小程序
    • ScoreDeck
    • h5跳转小程序问题
  • 思路
    • carTool
  • 操作系统学习
    • Linux命令
    • 计算机是如何计数的
    • nginx
      • location
      • try_files
  • 浏览器
    • session、location
    • web crypto
    • 性能监控和错误收集与上报
    • 预请求
  • 知识点整理
    • 知识点整理
  • 面试
    • Promise
    • 备战
    • 数码3
    • 腾娱
    • 腾讯云智
    • 重复请求合并
  • 前端工程化
    • 在 pnpm Monorepo 中使用公共方法包
由 GitBook 提供支持
在本页
  • 1. 前端性能指标
  • 性能指标概述
  • 性能监控方案
  • 2. 加载优化
  • 懒加载实现
  • 预加载策略
  • 缓存优化

这有帮助吗?

在GitHub上编辑
  1. 前端开发面试题集

性能优化面试题

1. 前端性能指标

性能指标概述

  • 概念解释:

    • FCP (First Contentful Paint): 首次内容绘制

    • LCP (Largest Contentful Paint): 最大内容绘制

    • TTI (Time to Interactive): 可交互时间

    • TBT (Total Blocking Time): 总阻塞时间

    • CLS (Cumulative Layout Shift): 累积布局偏移

// 1. Performance API 使用
// 性能指标监控
const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (entry.entryType === "largest-contentful-paint") {
      console.log("LCP:", entry.startTime);
    }
    if (entry.entryType === "first-contentful-paint") {
      console.log("FCP:", entry.startTime);
    }
  }
});

observer.observe({
  entryTypes: ["largest-contentful-paint", "first-contentful-paint"],
});

// 2. Web Vitals 库使用
import { getLCP, getFID, getCLS } from "web-vitals";

function sendToAnalytics({ name, delta, id }) {
  // 发送性能数据到分析服务
  fetch("/analytics", {
    method: "POST",
    body: JSON.stringify({ name, delta, id }),
  });
}

getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getLCP(sendToAnalytics);

性能监控方案

// 1. 自定义性能监控
class PerformanceMonitor {
  constructor() {
    this.metrics = {};
    this.init();
  }

  init() {
    // 记录页面加载时间
    window.addEventListener("load", () => {
      const timing = performance.timing;
      this.metrics.loadTime = timing.loadEventEnd - timing.navigationStart;
      this.metrics.domReady =
        timing.domContentLoadedEventEnd - timing.navigationStart;
      this.sendMetrics();
    });

    // 记录资源加载时间
    const observer = new PerformanceObserver((list) => {
      const entries = list.getEntries();
      entries.forEach((entry) => {
        if (entry.entryType === "resource") {
          this.metrics[entry.name] = entry.duration;
        }
      });
    });

    observer.observe({ entryTypes: ["resource"] });
  }

  sendMetrics() {
    // 发送性能数据
    navigator.sendBeacon("/analytics", JSON.stringify(this.metrics));
  }
}

// 2. 错误监控
window.addEventListener("error", (event) => {
  const error = {
    message: event.message,
    filename: event.filename,
    lineno: event.lineno,
    colno: event.colno,
    stack: event.error?.stack,
  };

  // 发送错误信息
  navigator.sendBeacon("/error", JSON.stringify(error));
});

// 3. 资源加载监控
const resourceObserver = new PerformanceObserver((list) => {
  list.getEntries().forEach((entry) => {
    if (entry.initiatorType === "img" || entry.initiatorType === "script") {
      console.log(`${entry.name} loaded in: ${entry.duration}ms`);
    }
  });
});

resourceObserver.observe({ entryTypes: ["resource"] });

2. 加载优化

懒加载实现

// 1. 组件懒加载
const LazyComponent = React.lazy(() => import("./LazyComponent"));

function App() {
  return (
    <Suspense fallback={<Loading />}>
      <LazyComponent />
    </Suspense>
  );
}

// 2. 路由懒加载
const routes = [
  {
    path: "/dashboard",
    component: () => import("./views/Dashboard"),
  },
];

// 3. 图片懒加载
function LazyImage({ src, alt }) {
  const [isLoaded, setIsLoaded] = useState(false);
  const imgRef = useRef();

  useEffect(() => {
    const observer = new IntersectionObserver(([entry]) => {
      if (entry.isIntersecting) {
        setIsLoaded(true);
        observer.disconnect();
      }
    });

    observer.observe(imgRef.current);
    return () => observer.disconnect();
  }, []);

  return (
    <img ref={imgRef} src={isLoaded ? src : "placeholder.jpg"} alt={alt} />
  );
}

预加载策略

// 1. 资源预加载
document.head.appendChild(Object.assign(
  document.createElement('link'),
  {
    rel: 'preload',
    href: 'heavy-component.js',
    as: 'script'
  }
));

// 2. DNS预解析
<link rel="dns-prefetch" href="//example.com">

// 3. 预连接
<link rel="preconnect" href="https://example.com">

// 4. 条件预加载
const prefetchComponent = () => {
  const link = document.createElement('link');
  link.rel = 'prefetch';
  link.href = '/component.js';
  document.head.appendChild(link);
};

// 在空闲时预加载
if (requestIdleCallback) {
  requestIdleCallback(prefetchComponent);
} else {
  setTimeout(prefetchComponent, 1000);
}

缓存优化

// 1. Service Worker 缓存
// sw.js
const CACHE_NAME = 'v1';
const urlsToCache = [
  '/',
  '/styles.css',
  '/app.js'
];

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => cache.addAll(urlsToCache))
  );
});

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request)
      .then(response => {
        if (response) {
          return response;
        }
        return fetch(event.request).then(
          response => {
            if (!response || response.status !== 200) {
              return response;
            }
            const responseToCache = response.clone();
            caches.open(CACHE_NAME)
              .then(cache => {
                cache.put(event.request, responseToCache);
              });
            return response;
          }
        );
      })
  );
});

// 2. HTTP 缓存配置
// Nginx配置
location /static/ {
  expires 1y;
  add_header Cache-Control "public, no-transform";
}

// 3. 内存缓存
const cache = new Map();

function memoize(fn) {
  return function (...args) {
    const key = JSON.stringify(args);
    if (cache.has(key)) {
      return cache.get(key);
    }
    const result = fn.apply(this, args);
    cache.set(key, result);
    return result;
  };
}
上一页Node.js 面试题下一页React 面试题

最后更新于5个月前

这有帮助吗?