H5页面性能监控工具

21 阅读6分钟

<!DOCTYPE html>                                                                                            |
| ---------------------------------------------------------------------------------------------------------- |
| <html lang="zh-CN">                                                                                        |
| <head>                                                                                                     |
| <meta charset="UTF-8">                                                                                     |
| <meta name="viewport" content="width=device-width, initial-scale=1.0">                                     |
| <title>H5页面性能监控工具</title>                                                                                  |
| <script src="<https://cdn.jsdelivr.net/npm/chart.js>"></script>                                            |
| <style>                                                                                                    |
| * {                                                                                                        |
| margin: 0;                                                                                                 |
| padding: 0;                                                                                                |
| box-sizing: border-box;                                                                                    |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;                                              |
| }                                                                                                          |
|                                                                                                            |
| body {                                                                                                     |
| background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);                                            |
| color: #fff;                                                                                               |
| min-height: 100vh;                                                                                         |
| padding: 20px;                                                                                             |
| }                                                                                                          |
|                                                                                                            |
| .container {                                                                                               |
| max-width: 1200px;                                                                                         |
| margin: 0 auto;                                                                                            |
| }                                                                                                          |
|                                                                                                            |
| header {                                                                                                   |
| text-align: center;                                                                                        |
| margin-bottom: 30px;                                                                                       |
| padding: 20px;                                                                                             |
| background: rgba(0, 0, 0, 0.3);                                                                            |
| border-radius: 15px;                                                                                       |
| box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);                                                                |
| }                                                                                                          |
|                                                                                                            |
| h1 {                                                                                                       |
| font-size: 2.5rem;                                                                                         |
| margin-bottom: 10px;                                                                                       |
| text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);                                                               |
| }                                                                                                          |
|                                                                                                            |
| .subtitle {                                                                                                |
| font-size: 1.2rem;                                                                                         |
| opacity: 0.9;                                                                                              |
| }                                                                                                          |
|                                                                                                            |
| .dashboard {                                                                                               |
| display: grid;                                                                                             |
| grid-template-columns: 1fr 1fr;                                                                            |
| gap: 20px;                                                                                                 |
| margin-bottom: 30px;                                                                                       |
| }                                                                                                          |
|                                                                                                            |
| @media (max-width: 768px) {                                                                                |
| .dashboard {                                                                                               |
| grid-template-columns: 1fr;                                                                                |
| }                                                                                                          |
| }                                                                                                          |
|                                                                                                            |
| .card {                                                                                                    |
| background: rgba(255, 255, 255, 0.1);                                                                      |
| backdrop-filter: blur(10px);                                                                               |
| border-radius: 15px;                                                                                       |
| padding: 20px;                                                                                             |
| box-shadow: 0 8px 25px rgba(0, 0, 0, 0.2);                                                                 |
| transition: transform 0.3s ease;                                                                           |
| }                                                                                                          |
|                                                                                                            |
| .card:hover {                                                                                              |
| transform: translateY(-5px);                                                                               |
| }                                                                                                          |
|                                                                                                            |
| .card h2 {                                                                                                 |
| font-size: 1.5rem;                                                                                         |
| margin-bottom: 15px;                                                                                       |
| border-bottom: 2px solid rgba(255, 255, 255, 0.3);                                                         |
| padding-bottom: 10px;                                                                                      |
| }                                                                                                          |
|                                                                                                            |
| .metrics {                                                                                                 |
| display: grid;                                                                                             |
| grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));                                               |
| gap: 15px;                                                                                                 |
| margin-bottom: 30px;                                                                                       |
| }                                                                                                          |
|                                                                                                            |
| .metric-card {                                                                                             |
| background: rgba(255, 255, 255, 0.15);                                                                     |
| border-radius: 10px;                                                                                       |
| padding: 15px;                                                                                             |
| text-align: center;                                                                                        |
| transition: all 0.3s ease;                                                                                 |
| }                                                                                                          |
|                                                                                                            |
| .metric-card:hover {                                                                                       |
| background: rgba(255, 255, 255, 0.25);                                                                     |
| transform: scale(1.05);                                                                                    |
| }                                                                                                          |
|                                                                                                            |
| .metric-value {                                                                                            |
| font-size: 1.8rem;                                                                                         |
| font-weight: bold;                                                                                         |
| margin: 10px 0;                                                                                            |
| }                                                                                                          |
|                                                                                                            |
| .metric-label {                                                                                            |
| font-size: 0.9rem;                                                                                         |
| opacity: 0.8;                                                                                              |
| }                                                                                                          |
|                                                                                                            |
| .chart-container {                                                                                         |
| height: 300px;                                                                                             |
| margin-top: 20px;                                                                                          |
| }                                                                                                          |
|                                                                                                            |
| .timeline {                                                                                                |
| margin-top: 20px;                                                                                          |
| }                                                                                                          |
|                                                                                                            |
| .timeline-item {                                                                                           |
| display: flex;                                                                                             |
| justify-content: space-between;                                                                            |
| margin-bottom: 10px;                                                                                       |
| padding: 8px 15px;                                                                                         |
| background: rgba(255, 255, 255, 0.1);                                                                      |
| border-radius: 8px;                                                                                        |
| }                                                                                                          |
|                                                                                                            |
| .timeline-label {                                                                                          |
| font-weight: bold;                                                                                         |
| }                                                                                                          |
|                                                                                                            |
| .timeline-value {                                                                                          |
| color: #fdbb2d;                                                                                            |
| }                                                                                                          |
|                                                                                                            |
| .buttons {                                                                                                 |
| display: flex;                                                                                             |
| gap: 15px;                                                                                                 |
| margin-top: 20px;                                                                                          |
| }                                                                                                          |
|                                                                                                            |
| button {                                                                                                   |
| background: #fdbb2d;                                                                                       |
| color: #1a2a6c;                                                                                            |
| border: none;                                                                                              |
| padding: 12px 25px;                                                                                        |
| border-radius: 8px;                                                                                        |
| font-weight: bold;                                                                                         |
| cursor: pointer;                                                                                           |
| transition: all 0.3s ease;                                                                                 |
| flex: 1;                                                                                                   |
| }                                                                                                          |
|                                                                                                            |
| button:hover {                                                                                             |
| background: #ffcc44;                                                                                       |
| transform: translateY(-2px);                                                                               |
| box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);                                                                 |
| }                                                                                                          |
|                                                                                                            |
| button:active {                                                                                            |
| transform: translateY(0);                                                                                  |
| }                                                                                                          |
|                                                                                                            |
| .resources {                                                                                               |
| margin-top: 20px;                                                                                          |
| max-height: 300px;                                                                                         |
| overflow-y: auto;                                                                                          |
| }                                                                                                          |
|                                                                                                            |
| .resource-item {                                                                                           |
| display: flex;                                                                                             |
| justify-content: space-between;                                                                            |
| padding: 10px;                                                                                             |
| border-bottom: 1px solid rgba(255, 255, 255, 0.1);                                                         |
| }                                                                                                          |
|                                                                                                            |
| .resource-name {                                                                                           |
| flex: 2;                                                                                                   |
| overflow: hidden;                                                                                          |
| text-overflow: ellipsis;                                                                                   |
| white-space: nowrap;                                                                                       |
| }                                                                                                          |
|                                                                                                            |
| .resource-size, .resource-time {                                                                           |
| flex: 1;                                                                                                   |
| text-align: right;                                                                                         |
| }                                                                                                          |
|                                                                                                            |
| footer {                                                                                                   |
| text-align: center;                                                                                        |
| margin-top: 30px;                                                                                          |
| padding: 20px;                                                                                             |
| font-size: 0.9rem;                                                                                         |
| opacity: 0.8;                                                                                              |
| }                                                                                                          |
|                                                                                                            |
| .good {                                                                                                    |
| color: #4CAF50;                                                                                            |
| }                                                                                                          |
|                                                                                                            |
| .medium {                                                                                                  |
| color: #FFC107;                                                                                            |
| }                                                                                                          |
|                                                                                                            |
| .poor {                                                                                                    |
| color: #F44336;                                                                                            |
| }                                                                                                          |
| </style>                                                                                                   |
| </head>                                                                                                    |
| <body>                                                                                                     |
| <div class="container">                                                                                    |
| <header>                                                                                                   |
| <h1>H5页面性能监控工具</h1>                                                                                        |
| <p class="subtitle">基于浏览器Performance API的页面性能分析</p>                                                        |
| </header>                                                                                                  |
|                                                                                                            |
| <div class="metrics">                                                                                      |
| <div class="metric-card">                                                                                  |
| <div class="metric-label">DOM解析完成</div>                                                                    |
| <div class="metric-value" id="domComplete">0ms</div>                                                       |
| <div class="metric-label">domComplete</div>                                                                |
| </div>                                                                                                     |
| <div class="metric-card">                                                                                  |
| <div class="metric-label">首次内容绘制</div>                                                                     |
| <div class="metric-value" id="fcp">0ms</div>                                                               |
| <div class="metric-label">First Contentful Paint</div>                                                     |
| </div>                                                                                                     |
| <div class="metric-card">                                                                                  |
| <div class="metric-label">最大内容绘制</div>                                                                     |
| <div class="metric-value" id="lcp">0ms</div>                                                               |
| <div class="metric-label">Largest Contentful Paint</div>                                                   |
| </div>                                                                                                     |
| <div class="metric-card">                                                                                  |
| <div class="metric-label">首次输入延迟</div>                                                                     |
| <div class="metric-value" id="fid">0ms</div>                                                               |
| <div class="metric-label">First Input Delay</div>                                                          |
| </div>                                                                                                     |
| </div>                                                                                                     |
|                                                                                                            |
| <div class="dashboard">                                                                                    |
| <div class="card">                                                                                         |
| <h2>页面加载时间线</h2>                                                                                           |
| <div class="chart-container">                                                                              |
| <canvas id="timelineChart"></canvas>                                                                       |
| </div>                                                                                                     |
| </div>                                                                                                     |
|                                                                                                            |
| <div class="card">                                                                                         |
| <h2>性能指标详情</h2>                                                                                            |
| <div class="timeline">                                                                                     |
| <div class="timeline-item">                                                                                |
| <span class="timeline-label">重定向时间</span>                                                                  |
| <span class="timeline-value" id="redirectTime">0ms</span>                                                  |
| </div>                                                                                                     |
| <div class="timeline-item">                                                                                |
| <span class="timeline-label">DNS查询时间</span>                                                                |
| <span class="timeline-value" id="dnsLookupTime">0ms</span>                                                 |
| </div>                                                                                                     |
| <div class="timeline-item">                                                                                |
| <span class="timeline-label">TCP连接时间</span>                                                                |
| <span class="timeline-value" id="tcpTime">0ms</span>                                                       |
| </div>                                                                                                     |
| <div class="timeline-item">                                                                                |
| <span class="timeline-label">请求响应时间</span>                                                                 |
| <span class="timeline-value" id="requestTime">0ms</span>                                                   |
| </div>                                                                                                     |
| <div class="timeline-item">                                                                                |
| <span class="timeline-label">DOM解析时间</span>                                                                |
| <span class="timeline-value" id="domParseTime">0ms</span>                                                  |
| </div>                                                                                                     |
| <div class="timeline-item">                                                                                |
| <span class="timeline-label">页面完全加载</span>                                                                 |
| <span class="timeline-value" id="loadTime">0ms</span>                                                      |
| </div>                                                                                                     |
| </div>                                                                                                     |
|                                                                                                            |
| <div class="buttons">                                                                                      |
| <button id="refreshBtn">刷新数据</button>                                                                      |
| <button id="simulateLoadBtn">模拟资源加载</button>                                                               |
| </div>                                                                                                     |
| </div>                                                                                                     |
| </div>                                                                                                     |
|                                                                                                            |
| <div class="card">                                                                                         |
| <h2>资源加载详情</h2>                                                                                            |
| <div class="resources" id="resourcesList">                                                                 |
| <!-- 资源列表将在这里动态生成 -->                                                                                      |
| </div>                                                                                                     |
| </div>                                                                                                     |
|                                                                                                            |
| <footer>                                                                                                   |
| <p>H5性能监控工具 &copy; 2023 | 基于Performance API实现</p>                                                         |
| </footer>                                                                                                  |
| </div>                                                                                                     |
|                                                                                                            |
| <script>                                                                                                   |
| document.addEventListener('DOMContentLoaded', function() {                                                 |
| // 初始化图表                                                                                                   |
| const timelineCtx = document.getElementById('timelineChart').getContext('2d');                             |
| const timelineChart = new Chart(timelineCtx, {                                                             |
| type: 'bar',                                                                                               |
| data: {                                                                                                    |
| labels: ['重定向', 'DNS查询', 'TCP连接', '请求响应', 'DOM解析', '页面加载'],                                                |
| datasets: [{                                                                                               |
| label: '时间(ms)',                                                                                           |
| data: [0, 0, 0, 0, 0, 0],                                                                                  |
| backgroundColor: [                                                                                         |
| 'rgba(255, 99, 132, 0.7)',                                                                                 |
| 'rgba(54, 162, 235, 0.7)',                                                                                 |
| 'rgba(255, 206, 86, 0.7)',                                                                                 |
| 'rgba(75, 192, 192, 0.7)',                                                                                 |
| 'rgba(153, 102, 255, 0.7)',                                                                                |
| 'rgba(255, 159, 64, 0.7)'                                                                                  |
| ],                                                                                                         |
| borderColor: [                                                                                             |
| 'rgba(255, 99, 132, 1)',                                                                                   |
| 'rgba(54, 162, 235, 1)',                                                                                   |
| 'rgba(255, 206, 86, 1)',                                                                                   |
| 'rgba(75, 192, 192, 1)',                                                                                   |
| 'rgba(153, 102, 255, 1)',                                                                                  |
| 'rgba(255, 159, 64, 1)'                                                                                    |
| ],                                                                                                         |
| borderWidth: 1                                                                                             |
| }]                                                                                                         |
| },                                                                                                         |
| options: {                                                                                                 |
| responsive: true,                                                                                          |
| maintainAspectRatio: false,                                                                                |
| scales: {                                                                                                  |
| y: {                                                                                                       |
| beginAtZero: true,                                                                                         |
| ticks: {                                                                                                   |
| color: 'white'                                                                                             |
| },                                                                                                         |
| grid: {                                                                                                    |
| color: 'rgba(255, 255, 255, 0.1)'                                                                          |
| }                                                                                                          |
| },                                                                                                         |
| x: {                                                                                                       |
| ticks: {                                                                                                   |
| color: 'white'                                                                                             |
| },                                                                                                         |
| grid: {                                                                                                    |
| color: 'rgba(255, 255, 255, 0.1)'                                                                          |
| }                                                                                                          |
| }                                                                                                          |
| },                                                                                                         |
| plugins: {                                                                                                 |
| legend: {                                                                                                  |
| labels: {                                                                                                  |
| color: 'white'                                                                                             |
| }                                                                                                          |
| }                                                                                                          |
| }                                                                                                          |
| }                                                                                                          |
| });                                                                                                        |
|                                                                                                            |
| // 获取性能数据                                                                                                  |
| function getPerformanceData() {                                                                            |
| // 使用Performance Timeline API                                                                              |
| const performance = window.performance;                                                                    |
| if (!performance) {                                                                                        |
| alert('您的浏览器不支持Performance API');                                                                          |
| return;                                                                                                    |
| }                                                                                                          |
|                                                                                                            |
| // 获取导航计时数据                                                                                                |
| const timing = performance.timing;                                                                         |
| const navigation = performance.getEntriesByType('navigation')[0];                                          |
|                                                                                                            |
| // 计算各个阶段的时间                                                                                               |
| const redirectTime = timing.redirectEnd - timing.redirectStart;                                            |
| const dnsLookupTime = timing.domainLookupEnd - timing.domainLookupStart;                                   |
| const tcpTime = timing.connectEnd - timing.connectStart;                                                   |
| const requestTime = timing.responseEnd - timing.requestStart;                                              |
| const domParseTime = timing.domComplete - timing.domLoading;                                               |
| const loadTime = timing.loadEventEnd - timing.navigationStart;                                             |
|                                                                                                            |
| // 更新时间线图表                                                                                                 |
| timelineChart.data.datasets[0].data = [                                                                    |
| redirectTime, dnsLookupTime, tcpTime, requestTime, domParseTime, loadTime                                  |
| ];                                                                                                         |
| timelineChart.update();                                                                                    |
|                                                                                                            |
| // 更新指标显示                                                                                                  |
| document.getElementById('redirectTime').textContent = redirectTime + 'ms';                                 |
| document.getElementById('dnsLookupTime').textContent = dnsLookupTime + 'ms';                               |
| document.getElementById('tcpTime').textContent = tcpTime + 'ms';                                           |
| document.getElementById('requestTime').textContent = requestTime + 'ms';                                   |
| document.getElementById('domParseTime').textContent = domParseTime + 'ms';                                 |
| document.getElementById('loadTime').textContent = loadTime + 'ms';                                         |
|                                                                                                            |
| // 更新核心性能指标                                                                                                |
| document.getElementById('domComplete').textContent = (timing.domComplete - timing.navigationStart) + 'ms'; |
|                                                                                                            |
| // 获取FCP (First Contentful Paint)                                                                          |
| const fcpEntry = performance.getEntriesByName('first-contentful-paint')[0];                                |
| if (fcpEntry) {                                                                                            |
| document.getElementById('fcp').textContent = Math.round(fcpEntry.startTime) + 'ms';                        |
| // 根据FCP时间添加颜色标识                                                                                           |
| const fcpElement = document.getElementById('fcp');                                                         |
| fcpElement.className = 'metric-value ' +                                                                   |
| (fcpEntry.startTime < 1000 ? 'good' :                                                                      |
| fcpEntry.startTime < 3000 ? 'medium' : 'poor');                                                            |
| }                                                                                                          |
|                                                                                                            |
| // 获取LCP (Largest Contentful Paint)                                                                        |
| const lcpEntries = performance.getEntriesByType('largest-contentful-paint');                               |
| if (lcpEntries.length > 0) {                                                                               |
| const lcp = lcpEntries[lcpEntries.length - 1];                                                             |
| document.getElementById('lcp').textContent = Math.round(lcp.startTime) + 'ms';                             |
| // 根据LCP时间添加颜色标识                                                                                           |
| const lcpElement = document.getElementById('lcp');                                                         |
| lcpElement.className = 'metric-value ' +                                                                   |
| (lcp.startTime < 2500 ? 'good' :                                                                           |
| lcp.startTime < 4000 ? 'medium' : 'poor');                                                                 |
| }                                                                                                          |
|                                                                                                            |
| // 获取FID (First Input Delay)                                                                               |
| const fidEntries = performance.getEntriesByType('first-input');                                            |
| if (fidEntries.length > 0) {                                                                               |
| const fid = fidEntries[0];                                                                                 |
| document.getElementById('fid').textContent = Math.round(fid.processingStart - fid.startTime) + 'ms';       |
| // 根据FID时间添加颜色标识                                                                                           |
| const fidElement = document.getElementById('fid');                                                         |
| const fidValue = fid.processingStart - fid.startTime;                                                      |
| fidElement.className = 'metric-value ' +                                                                   |
| (fidValue < 100 ? 'good' :                                                                                 |
| fidValue < 300 ? 'medium' : 'poor');                                                                       |
| }                                                                                                          |
|                                                                                                            |
| // 获取资源加载信息                                                                                                |
| const resources = performance.getEntriesByType('resource');                                                |
| const resourcesList = document.getElementById('resourcesList');                                            |
| resourcesList.innerHTML = '';                                                                              |
|                                                                                                            |
| resources.forEach(resource => {                                                                            |
| const resourceItem = document.createElement('div');                                                        |
| resourceItem.className = 'resource-item';                                                                  |
|                                                                                                            |
| const name = document.createElement('div');                                                                |
| name.className = 'resource-name';                                                                          |
| name.textContent = resource.name;                                                                          |
|                                                                                                            |
| const size = document.createElement('div');                                                                |
| size.className = 'resource-size';                                                                          |
| size.textContent = (resource.transferSize / 1024).toFixed(2) + ' KB';                                      |
|                                                                                                            |
| const time = document.createElement('div');                                                                |
| time.className = 'resource-time';                                                                          |
| time.textContent = Math.round(resource.duration) + 'ms';                                                   |
|                                                                                                            |
| resourceItem.appendChild(name);                                                                            |
| resourceItem.appendChild(size);                                                                            |
| resourceItem.appendChild(time);                                                                            |
|                                                                                                            |
| resourcesList.appendChild(resourceItem);                                                                   |
| });                                                                                                        |
| }                                                                                                          |
|                                                                                                            |
| // 初始加载时获取性能数据                                                                                             |
| // 使用setTimeout确保在页面完全加载后获取数据                                                                              |
| setTimeout(getPerformanceData, 500);                                                                       |
|                                                                                                            |
| // 刷新按钮事件                                                                                                  |
| document.getElementById('refreshBtn').addEventListener('click', function() {                               |
| getPerformanceData();                                                                                      |
| });                                                                                                        |
|                                                                                                            |
| // 模拟资源加载按钮事件                                                                                              |
| document.getElementById('simulateLoadBtn').addEventListener('click', function() {                          |
| // 创建一些图片资源来模拟资源加载                                                                                         |
| for (let i = 0; i < 3; i++) {                                                                              |
| const img = new Image();                                                                                   |
| img.src = `https://picsum.photos/400/200?random=${Date.now()}-${i}`;                                       |
| document.body.appendChild(img);                                                                            |
| }                                                                                                          |
|                                                                                                            |
| // 延迟一下再获取更新的性能数据                                                                                          |
| setTimeout(getPerformanceData, 1000);                                                                      |
| });                                                                                                        |
|                                                                                                            |
| // 监听性能条目变化                                                                                                |
| if (window.PerformanceObserver) {                                                                          |
| // 观察LCP变化                                                                                                 |
| const lcpObserver = new PerformanceObserver((entryList) => {                                               |
| const entries = entryList.getEntries();                                                                    |
| const lastEntry = entries[entries.length - 1];                                                             |
| document.getElementById('lcp').textContent = Math.round(lastEntry.startTime) + 'ms';                       |
| });                                                                                                        |
|                                                                                                            |
| lcpObserver.observe({entryTypes: ['largest-contentful-paint']});                                           |
|                                                                                                            |
| // 观察FID变化                                                                                                 |
| const fidObserver = new PerformanceObserver((entryList) => {                                               |
| const entries = entryList.getEntries();                                                                    |
| const firstEntry = entries[0];                                                                             |
| document.getElementById('fid').textContent =                                                               |
| Math.round(firstEntry.processingStart - firstEntry.startTime) + 'ms';                                      |
| });                                                                                                        |
|                                                                                                            |
| fidObserver.observe({entryTypes: ['first-input']});                                                        |
| }                                                                                                          |
| });                                                                                                        |
| </script>                                                                                                  |
| </body>                                                                                                    |
| </html>

其他可能用到的性能数据

    // 计算页面完全加载(load 事件)耗时
    const timing = window.performance.timing
    const loadTime = timing.loadEventEnd - timing.navigationStart
    console.log(`页面完全加载耗时:${loadTime}ms`)
    const performance = window.performance
    const paintEntries = performance.getEntriesByType('paint')

    // 获取 FCP (首次内容绘制) 时间:
    paintEntries.forEach((entry) => {
      console.log('entry===', entry)
      if (entry.name === 'first-paint') {
        console.log(`FMP: ${entry.startTime}ms`)
      }
    })

    // 统计所有图片资源的加载时间:
    const resources = performance.getEntriesByType('resource')
    const images = resources.filter(r => r.initiatorType === 'img')
    images.forEach(img => {
      console.log(`图片 ${img.name} A加载耗时:${img.duration}ms`)
    })

    const navEntry = performance.getEntriesByType('navigation')[0]
    console.log('WebView初始化完成时间(近似):' + navEntry.fetchStart + 'ms')

    performance.mark('component-start')
    // 组件渲染完成后(可结合nextTick确保DOM更新)
    this.$nextTick(() => {
      performance.mark('component-end')
      const duration = performance.measure('component-init', 'component-start', 'component-end').duration
      console.log('组件创建完成耗时:' + duration + 'ms')
    })

    // 获取所有资源性能条目
    const resourceEntries = performance.getEntriesByType('resource')

    // 分类存储不同类型资源的加载时间
    const resourceStats = {
      js: [],
      css: [],
      image: []
    }

    resourceEntries.forEach(entry => {
      console.log('entry==A==', entry)
      const duration = entry.responseEnd - entry.fetchStart
      const initiatorType = entry.initiatorType
      const entryName = entry.name
      if (initiatorType === 'link' && entryName.endsWith('.js')) {
        resourceStats.js.push({ url: entry.name, duration })
      } else if (initiatorType === 'link' && entryName.endsWith('.css')) {
        resourceStats.css.push({ url: entry.name, duration })
      } else if (initiatorType === 'link' && (entryName.endsWith('.jpg') || entryName.endsWith('.jpeg') || entryName.endsWith('.png'))) {
        resourceStats.image.push({ url: entry.name, duration })
      }
      // switch (entry.initiatorType) {
      //   case 'script':
      //     resourceStats.js.push({ url: entry.name, duration })
      //     break
      //   case 'link':
      //     resourceStats.css.push({ url: entry.name, duration })
      //     break
      //   case 'img':
      //     resourceStats.image.push({ url: entry.name, duration })
      //     break
      //   // 可扩展其他类型(如 'xmlhttprequest' 对应 AJAX)
      // }
    })

    // 打印统计结果
    console.log('JS 资源加载时间:', resourceStats.js)
    console.log('CSS 资源加载时间:', resourceStats.css)
    console.log('图片资源加载时间:', resourceStats.image)

    // 计算每种资源的平均耗时(可选)
    const avgJs = resourceStats.js.reduce((sum, item) => sum + item.duration, 0) / resourceStats.js.length || 0
    const avgCss = resourceStats.css.reduce((sum, item) => sum + item.duration, 0) / resourceStats.css.length || 0
    const avgImage = resourceStats.image.reduce((sum, item) => sum + item.duration, 0) / resourceStats.image.length || 0

    console.log(`JS 资源平均加载耗时:${avgJs.toFixed(2)}ms`)
    console.log(`CSS 资源平均加载耗时:${avgCss.toFixed(2)}ms`)
    console.log(`图片资源平均加载耗时:${avgImage.toFixed(2)}ms`)

    // 获取导航性能条目(现代浏览器推荐方式)
    const navEntries = performance.getEntriesByType('navigation')
    console.log('navEntries===', navEntries)
    if (navEntries.length > 0) {
      const nav = navEntries[0]
      // DNS 耗时
      const dnsTime = nav.domainLookupEnd - nav.domainLookupStart
      // TCP 连接耗时
      const connectTime = nav.connectEnd - nav.connectStart
      // 服务器加载时间(请求+响应)
      const serverTime = nav.responseEnd - nav.requestStart

      console.log(`DNS 耗时:${dnsTime.toFixed(2)}ms`)
      console.log(`TCP 连接耗时:${connectTime.toFixed(2)}ms`)
      console.log(`服务器加载时间:${serverTime.toFixed(2)}ms`)
    }

    // 最大内容绘制时间(页面加载过程中最大内容元素呈现的时间)
    new PerformanceObserver((entries) => {
      const lcpEntry = entries.getEntries()[0]
      console.log(`最大内容绘制(LCP):${lcpEntry.startTime}ms`)
    }).observe({ type: 'largest-contentful-paint', buffered: true })

    // 累积布局偏移(页面元素意外移动的总评分,反映视觉稳定性)
    new PerformanceObserver((entryList) => {
      // 先通过 getEntries() 获取条目数组
      const entries = entryList.getEntries()
      entries.forEach(entry => {
        if (!entry.hadRecentInput) { // 排除用户输入导致的偏移
          console.log(`布局偏移:${entry.value}`)
        }
      })
    }).observe({ type: 'layout-shift', buffered: true })

    // 长任务(执行时间超过 50ms 的任务)会阻塞主线程,导致页面卡顿。
    new PerformanceObserver((entryList) => {
      // 先通过 getEntries() 获取条目数组
      const entries = entryList.getEntries()
      entries.forEach(task => {
        console.log(`长任务耗时:${task.duration}ms,开始于:${task.startTime}ms`)
      })
    }).observe({ type: 'longtask', buffered: true })

    console.log('当前 JS 堆内存使用:', performance.memory.usedJSHeapSize)

    // 测量函数执行耗时:
    // performance.mark('functionStart') // 标记开始
    // // 执行目标函数
    // heavyFunction()
    // performance.mark('functionEnd') // 标记结束
    // performance.measure('functionDuration', 'functionStart', 'functionEnd') // 计算耗时

    // const measure = performance.getEntriesByName('functionDuration')[0]
    // console.log(`函数执行耗时:${measure.duration}ms`)