第六章:性能优化与摆设 - 第五节 - Tailwind CSS 性能监控和优化

[复制链接]
发表于 2025-10-24 13:52:07 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
性能监控监控和优化是确保 Tailwind CSS 项目高效运行的关键。本节将详细先容怎样实行性能监控监控和举行相应的优化。
性能指标监控监控

Web Vitals 监控

  1. // utils/vitals.ts
  2. import { getCLS, getFID, getLCP, getTTFB, getFCP } from 'web-vitals';
  3. const reportWebVitals = (onPerfEntry: (metric: any) => void) => {
  4.   if (onPerfEntry && onPerfEntry instanceof Function) {
  5.     getCLS(onPerfEntry);  // Cumulative Layout Shift
  6.     getFID(onPerfEntry);  // First Input Delay
  7.     getLCP(onPerfEntry);  // Largest Contentful Paint
  8.     getTTFB(onPerfEntry); // Time to First Byte
  9.     getFCP(onPerfEntry);  // First Contentful Paint
  10.   }
  11. };
  12. export const setupVitalsReporting = () => {
  13.   reportWebVitals((metric) => {
  14.     // 发送到分析服务
  15.     console.log(metric);
  16.    
  17.     // 可以发送到 Google Analytics
  18.     const analytics = (window as any).ga;
  19.     if (analytics) {
  20.       analytics('send', 'event', {
  21.         eventCategory: 'Web Vitals',
  22.         eventAction: metric.name,
  23.         eventValue: Math.round(metric.value),
  24.         eventLabel: metric.id,
  25.         nonInteraction: true,
  26.       });
  27.     }
  28.   });
  29. };
复制代码
自界说性能监控

  1. // utils/performance.ts
  2. export class PerformanceMonitor {
  3.   private marks: Map<string, number> = new Map();
  4.   
  5.   startMark(name: string) {
  6.     this.marks.set(name, performance.now());
  7.     performance.mark(`${name}-start`);
  8.   }
  9.   
  10.   endMark(name: string) {
  11.     const startTime = this.marks.get(name);
  12.     if (startTime) {
  13.       const duration = performance.now() - startTime;
  14.       performance.mark(`${name}-end`);
  15.       performance.measure(name, `${name}-start`, `${name}-end`);
  16.       
  17.       return {
  18.         name,
  19.         duration,
  20.         timestamp: new Date().toISOString()
  21.       };
  22.     }
  23.   }
  24.   
  25.   getMeasurements() {
  26.     return performance.getEntriesByType('measure');
  27.   }
  28.   
  29.   clearMeasurements() {
  30.     performance.clearMarks();
  31.     performance.clearMeasures();
  32.     this.marks.clear();
  33.   }
  34. }
  35. // 使用示例
  36. const monitor = new PerformanceMonitor();
  37. monitor.startMark('componentRender');
  38. // 组件渲染
  39. monitor.endMark('componentRender');
复制代码
样式性能分析

样式加载监控

  1. // utils/styleMonitor.ts
  2. export const monitorStyleLoading = () => {
  3.   const observer = new PerformanceObserver((list) => {
  4.     list.getEntries().forEach((entry) => {
  5.       if (entry.entryType === 'resource' && entry.name.endsWith('.css')) {
  6.         console.log('CSS Performance:', {
  7.           name: entry.name,
  8.           duration: entry.duration,
  9.           startTime: entry.startTime,
  10.           transferSize: entry.transferSize
  11.         });
  12.       }
  13.     });
  14.   });
  15.   
  16.   observer.observe({ entryTypes: ['resource'] });
  17. };
  18. // 监控样式变化
  19. const styleChangeObserver = new MutationObserver((mutations) => {
  20.   mutations.forEach((mutation) => {
  21.     if (mutation.attributeName === 'class') {
  22.       console.log('Style Change:', {
  23.         element: mutation.target,
  24.         oldValue: mutation.oldValue,
  25.         newValue: (mutation.target as HTMLElement).className
  26.       });
  27.     }
  28.   });
  29. });
  30. // 开始监控
  31. styleChangeObserver.observe(document.body, {
  32.   attributes: true,
  33.   attributeOldValue: true,
  34.   attributeFilter: ['class'],
  35.   subtree: true
  36. });
复制代码
样式分析工具

  1. // utils/styleAnalyzer.ts
  2. export class StyleAnalyzer {
  3.   analyzeDuplicateClasses() {
  4.     const elements = document.querySelectorAll('*');
  5.     const classCount = new Map<string, number>();
  6.    
  7.     elements.forEach((element) => {
  8.       const classes = element.className.split(' ');
  9.       classes.forEach((className) => {
  10.         classCount.set(
  11.           className,
  12.           (classCount.get(className) || 0) + 1
  13.         );
  14.       });
  15.     });
  16.    
  17.     return Array.from(classCount.entries())
  18.       .filter(([_, count]) => count > 1)
  19.       .sort(([_, a], [__, b]) => b - a);
  20.   }
  21.   
  22.   analyzeUnusedStyles() {
  23.     const styleSheets = Array.from(document.styleSheets);
  24.     const usedSelectors = new Set();
  25.    
  26.     // 收集使用的选择器
  27.     styleSheets.forEach((sheet) => {
  28.       try {
  29.         const rules = Array.from(sheet.cssRules);
  30.         rules.forEach((rule) => {
  31.           if (rule instanceof CSSStyleRule) {
  32.             const elements = document.querySelectorAll(rule.selectorText);
  33.             if (elements.length > 0) {
  34.               usedSelectors.add(rule.selectorText);
  35.             }
  36.           }
  37.         });
  38.       } catch (e) {
  39.         console.warn('Cannot read cssRules from stylesheet', e);
  40.       }
  41.     });
  42.    
  43.     return usedSelectors;
  44.   }
  45. }
复制代码
优化计谋

样式优化

  1. // utils/styleOptimizer.ts
  2. export class StyleOptimizer {
  3.   // 合并相似的类名
  4.   optimizeClassNames(element: HTMLElement) {
  5.     const classes = element.className.split(' ');
  6.     const optimized = new Set<string>();
  7.    
  8.     // 处理边距和内边距
  9.     const spacingClasses = {
  10.       margin: [] as string[],
  11.       padding: [] as string[]
  12.     };
  13.    
  14.     classes.forEach((cls) => {
  15.       if (cls.startsWith('m-')) {
  16.         spacingClasses.margin.push(cls);
  17.       } else if (cls.startsWith('p-')) {
  18.         spacingClasses.padding.push(cls);
  19.       } else {
  20.         optimized.add(cls);
  21.       }
  22.     });
  23.    
  24.     // 合并边距类
  25.     if (spacingClasses.margin.length > 0) {
  26.       optimized.add(this.mergeSpacingClasses(spacingClasses.margin));
  27.     }
  28.    
  29.     // 合并内边距类
  30.     if (spacingClasses.padding.length > 0) {
  31.       optimized.add(this.mergeSpacingClasses(spacingClasses.padding));
  32.     }
  33.    
  34.     return Array.from(optimized).join(' ');
  35.   }
  36.   
  37.   private mergeSpacingClasses(classes: string[]): string {
  38.     // 实现边距类合并逻辑
  39.     return classes[classes.length - 1];
  40.   }
  41. }
复制代码
运行时优化

  1. // utils/runtimeOptimizer.ts
  2. export class RuntimeOptimizer {
  3.   private styleCache = new Map<string, HTMLStyleElement>();
  4.   
  5.   // 缓存动态生成的样式
  6.   cacheStyles(className: string, styles: string) {
  7.     if (!this.styleCache.has(className)) {
  8.       const styleElement = document.createElement('style');
  9.       styleElement.textContent = styles;
  10.       document.head.appendChild(styleElement);
  11.       this.styleCache.set(className, styleElement);
  12.     }
  13.     return className;
  14.   }
  15.   
  16.   // 清理未使用的样式
  17.   cleanupUnusedStyles() {
  18.     const usedClasses = new Set<string>();
  19.    
  20.     // 收集当前使用的类名
  21.     document.querySelectorAll('*').forEach((element) => {
  22.       element.className.split(' ').forEach((cls) => {
  23.         usedClasses.add(cls);
  24.       });
  25.     });
  26.    
  27.     // 清理未使用的缓存样式
  28.     this.styleCache.forEach((style, className) => {
  29.       if (!usedClasses.has(className)) {
  30.         style.remove();
  31.         this.styleCache.delete(className);
  32.       }
  33.     });
  34.   }
  35. }
复制代码
性能陈诉

陈诉天生器

  1. // utils/reportGenerator.ts
  2. export class PerformanceReportGenerator {
  3.   generateReport() {
  4.     const report = {
  5.       timestamp: new Date().toISOString(),
  6.       webVitals: this.collectWebVitals(),
  7.       resourceMetrics: this.collectResourceMetrics(),
  8.       styleMetrics: this.collectStyleMetrics(),
  9.       recommendations: this.generateRecommendations()
  10.     };
  11.    
  12.     return report;
  13.   }
  14.   
  15.   private collectWebVitals() {
  16.     // 收集 Web Vitals 指标
  17.   }
  18.   
  19.   private collectResourceMetrics() {
  20.     // 收集资源加载指标
  21.     return performance.getEntriesByType('resource')
  22.       .filter(entry => entry.name.endsWith('.css'))
  23.       .map(entry => ({
  24.         name: entry.name,
  25.         duration: entry.duration,
  26.         size: entry.transferSize
  27.       }));
  28.   }
  29.   
  30.   private collectStyleMetrics() {
  31.     // 收集样式相关指标
  32.     const styleSheets = document.styleSheets;
  33.     return {
  34.       styleSheetCount: styleSheets.length,
  35.       totalRules: Array.from(styleSheets).reduce((count, sheet) => {
  36.         try {
  37.           return count + sheet.cssRules.length;
  38.         } catch (e) {
  39.           return count;
  40.         }
  41.       }, 0)
  42.     };
  43.   }
  44.   
  45.   private generateRecommendations() {
  46.     // 生成优化建议
  47.     const recommendations = [];
  48.    
  49.     // 检查样式表数量
  50.     if (document.styleSheets.length > 5) {
  51.       recommendations.push({
  52.         type: 'warning',
  53.         message: '考虑合并样式表以减少请求数'
  54.       });
  55.     }
  56.    
  57.     // 检查大型样式规则
  58.     Array.from(document.styleSheets).forEach((sheet) => {
  59.       try {
  60.         if (sheet.cssRules.length > 1000) {
  61.           recommendations.push({
  62.             type: 'warning',
  63.             message: `样式表 ${sheet.href} 包含过多规则`
  64.           });
  65.         }
  66.       } catch (e) {}
  67.     });
  68.    
  69.     return recommendations;
  70.   }
  71. }
复制代码
监控面板

性能仪表盘

  1. // components/PerformanceDashboard.tsx
  2. interface PerformanceMetrics {
  3.   cls: number;
  4.   fid: number;
  5.   lcp: number;
  6.   ttfb: number;
  7.   fcp: number;
  8. }
  9. const PerformanceDashboard: React.FC = () => {
  10.   const [metrics, setMetrics] = useState<PerformanceMetrics>();
  11.   
  12.   useEffect(() => {
  13.     getCLS((metric) => {
  14.       setMetrics(prev => ({ ...prev, cls: metric.value }));
  15.     });
  16.    
  17.     getFID((metric) => {
  18.       setMetrics(prev => ({ ...prev, fid: metric.value }));
  19.     });
  20.    
  21.     getLCP((metric) => {
  22.       setMetrics(prev => ({ ...prev, lcp: metric.value }));
  23.     });
  24.    
  25.     getTTFB((metric) => {
  26.       setMetrics(prev => ({ ...prev, ttfb: metric.value }));
  27.     });
  28.    
  29.     getFCP((metric) => {
  30.       setMetrics(prev => ({ ...prev, fcp: metric.value }));
  31.     });
  32.   }, []);
  33.   
  34.   return (
  35.     <div className="grid grid-cols-3 gap-4 p-4">
  36.       {metrics && Object.entries(metrics).map(([key, value]) => (
  37.         <div key={key} className="p-4 bg-white rounded-lg shadow">
  38.           <h3 className="text-lg font-semibold">{key.toUpperCase()}</h3>
  39.           <p className="text-2xl">{value.toFixed(2)}</p>
  40.         </div>
  41.       ))}
  42.     </div>
  43.   );
  44. };
复制代码
最佳实践


  • 监控计谋

    • 一连监控关键指标
    • 设置性能预警
    • 定期天生陈诉

  • 优化发起

    • 定期清算未使用样式
    • 归并重复样式类
    • 优化样式加载次序

  • 开辟发起

    • 使用性能分析工具
    • 遵照优化发起
    • 一连改进监控体系

  • 维护计谋

    • 定期查抄性能陈诉
    • 更新优化计谋
    • 相应性能预警


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告
回复

使用道具 举报

×
登录参与点评抽奖,加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表