index.html 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. <!DOCTYPE HTML>
  2. <html lang="zh-CN">
  3. <head>
  4. <title>当前网页加载时间</title>
  5. <meta charset="utf-8">
  6. <link rel="stylesheet" href="index.css" />
  7. <script type="text/javascript" src="../static/vendor/evalCore.min.js"></script>
  8. <script type="text/javascript" src="../static/vendor/vue/vue.js"></script>
  9. </head>
  10. <body>
  11. <div class="wrapper" id="pageContainer">
  12. <div class="panel panel-default" style="margin-bottom: 0px;">
  13. <div class="panel-heading">
  14. <h3 class="panel-title">
  15. <a href="https://fehelper.com" target="_blank" class="x-a-high">
  16. <img src="../static/img/fe-16.png" alt="fehelper"/> FeHelper</a>:页面性能检测
  17. <a href="#" class="x-donate-link" @click="openDonateModal($event)"><i class="nav-icon">❤&nbsp;</i>打赏鼓励</a>
  18. <a class="x-other-tools" @click="openOptionsPage($event)"><i class="icon-plus-circle"></i> 探索更多实用工具 <span class="tool-market-badge">工具市场</span></a>
  19. </h3>
  20. </div>
  21. </div>
  22. <div class="panel-body mod-json">
  23. <!-- 页面基本信息 -->
  24. <div id="pageInfo" class="row info-card">
  25. <div class="info-item">
  26. <label>被检测的页面:</label>
  27. <span id="pageTitle">{{pageTitle}}</span>
  28. </div>
  29. <div class="info-item">
  30. <label>页面完整地址:</label>
  31. <span id="pageUrl">{{pageUrl}}</span>
  32. </div>
  33. <div class="info-item" v-if="networkInfo">
  34. <label>网络状态:</label>
  35. <span>{{networkInfo.effectiveType}} / {{networkInfo.downlink}}Mbps / RTT:{{networkInfo.rtt}}ms</span>
  36. </div>
  37. <div class="update-time">
  38. <span>数据更新时间:{{new Date().toLocaleString()}}</span>
  39. </div>
  40. </div>
  41. <!-- 网页优化建议 -->
  42. <div class="performance-section">
  43. <h3>性能优化建议</h3>
  44. <div v-for="suggestion in optimizationSuggestions" :key="suggestion.title" class="suggestion-item">
  45. <span :class="['suggestion-category', 'category-' + suggestion.type]">{{suggestion.category}}</span>
  46. <h4 class="suggestion-title">{{suggestion.title}}</h4>
  47. <p class="suggestion-description">{{suggestion.description}}</p>
  48. <ul class="suggestion-list">
  49. <li v-for="item in suggestion.suggestions" :key="item">{{item}}</li>
  50. </ul>
  51. </div>
  52. </div>
  53. <!-- 性能概览区域 -->
  54. <div class="performance-overview">
  55. <!-- 核心Web指标 -->
  56. <div id="coreWebVitals" class="row performance-card" v-if="webVitals">
  57. <h3>核心Web指标 (Core Web Vitals)</h3>
  58. <div class="metrics-grid">
  59. <div class="metric-item" :class="getLCPStatus(webVitals.lcp)">
  60. <div class="metric-value">{{Math.ceil(webVitals.lcp)}} ms</div>
  61. <div class="metric-label">最大内容绘制 (LCP)</div>
  62. <div class="metric-status">{{getLCPStatusText(webVitals.lcp)}}</div>
  63. </div>
  64. <div class="metric-item" :class="getFIDStatus(webVitals.fid)">
  65. <div class="metric-value">{{webVitals.fid ? Math.ceil(webVitals.fid) + ' ms' : '未触发'}}</div>
  66. <div class="metric-label">首次输入延迟 (FID)</div>
  67. <div class="metric-status">{{getFIDStatusText(webVitals.fid)}}</div>
  68. </div>
  69. <div class="metric-item" :class="getCLSStatus(webVitals.cls)">
  70. <div class="metric-value">{{webVitals.cls ? webVitals.cls.toFixed(3) : '0'}}</div>
  71. <div class="metric-label">累积布局偏移 (CLS)</div>
  72. <div class="metric-status">{{getCLSStatusText(webVitals.cls)}}</div>
  73. </div>
  74. </div>
  75. </div>
  76. <!-- 页面加载时间和内存使用 -->
  77. <div class="flex-container">
  78. <div id="pageLoadTime" class="row performance-card half-width">
  79. <h3>页面加载时间</h3>
  80. <div class="timing-list" v-if="timing">
  81. <div class="timing-item" v-for="t in Object.keys(tmDefination)">
  82. <span class="timing-label">{{tmDefination[t]}}</span>
  83. <span class="timing-value">{{Math.ceil(timing[t])}} ms</span>
  84. </div>
  85. </div>
  86. </div>
  87. <div id="performanceMetrics" class="row performance-card half-width" v-if="performanceMetrics">
  88. <h3>内存使用情况</h3>
  89. <div class="memory-usage">
  90. <div class="memory-item">
  91. <div class="memory-label">已用/总量/限制</div>
  92. <div class="memory-value">
  93. {{formatSize(performanceMetrics.usedJSHeapSize)}} /
  94. {{formatSize(performanceMetrics.totalJSHeapSize)}} /
  95. {{formatSize(performanceMetrics.jsHeapSizeLimit)}}
  96. </div>
  97. </div>
  98. <div class="memory-bar">
  99. <div class="used-bar" :style="{width: (performanceMetrics.usedJSHeapSize / performanceMetrics.jsHeapSizeLimit * 100) + '%'}"></div>
  100. <div class="total-bar" :style="{width: (performanceMetrics.totalJSHeapSize / performanceMetrics.jsHeapSizeLimit * 100) + '%'}"></div>
  101. </div>
  102. </div>
  103. </div>
  104. </div>
  105. </div>
  106. <!-- HTTP Header信息 -->
  107. <div id="pageHeaderInfo" class="row detail-card" v-show="headerInfo">
  108. <div class="card-header" @click="toggleSection('headerInfo')">
  109. <h3>HTTP Response Header分析</h3>
  110. <span class="toggle-icon">▼</span>
  111. </div>
  112. <div class="card-content" v-show="sectionsVisible.headerInfo">
  113. <table class="table table-bordered table-striped table-condensed table-hover">
  114. <thead>
  115. <th>Header</th>
  116. <th>值</th>
  117. </thead>
  118. <tbody>
  119. <tr v-for="(value,key) in headerInfo">
  120. <td>{{key}}</td>
  121. <td>{{value || '-'}}</td>
  122. </tr>
  123. </tbody>
  124. </table>
  125. </div>
  126. </div>
  127. <!-- 长任务监控 -->
  128. <div id="longTasks" class="row detail-card" v-if="longTasks && longTasks.length">
  129. <div class="card-header" @click="toggleSection('longTasks')">
  130. <h3>长任务监控 (超过50ms的任务)</h3>
  131. <span class="toggle-icon">▼</span>
  132. </div>
  133. <div class="card-content" v-show="sectionsVisible.longTasks">
  134. <table class="table table-bordered table-striped table-condensed table-hover">
  135. <thead>
  136. <th>开始时间</th>
  137. <th>持续时间</th>
  138. <th>任务名称</th>
  139. </thead>
  140. <tbody>
  141. <tr v-for="task in longTasks">
  142. <td>{{formatTime(task.startTime)}}</td>
  143. <td>{{Math.ceil(task.duration)}} ms</td>
  144. <td>{{task.name}}</td>
  145. </tr>
  146. </tbody>
  147. </table>
  148. </div>
  149. </div>
  150. <!-- 详细信息区域 -->
  151. <div class="details-section">
  152. <!-- 资源加载性能 -->
  153. <div id="resourceTiming" class="row detail-card" v-if="resources && resources.length">
  154. <div class="card-header" @click="toggleSection('resourceTiming')">
  155. <h3>资源加载性能分析</h3>
  156. <span class="toggle-icon">▼</span>
  157. </div>
  158. <div class="card-content" v-show="sectionsVisible.resourceTiming">
  159. <table class="table table-bordered table-striped table-condensed table-hover">
  160. <thead>
  161. <th>资源</th>
  162. <th>类型</th>
  163. <th>大小</th>
  164. <th>总耗时</th>
  165. <th>DNS查询</th>
  166. <th>TCP连接</th>
  167. <th>请求响应</th>
  168. <th>内容下载</th>
  169. </thead>
  170. <tbody>
  171. <tr v-for="resource in resources">
  172. <td :title="resource.name">{{getFileName(resource.name)}}</td>
  173. <td>{{resource.entryType}}</td>
  174. <td>{{formatSize(resource.transferSize)}}</td>
  175. <td>{{Math.ceil(resource.duration)}} ms</td>
  176. <td>{{Math.ceil(resource.dnsTime)}} ms</td>
  177. <td>{{Math.ceil(resource.tcpTime)}} ms</td>
  178. <td>{{Math.ceil(resource.ttfb)}} ms</td>
  179. <td>{{Math.ceil(resource.downloadTime)}} ms</td>
  180. </tr>
  181. </tbody>
  182. </table>
  183. </div>
  184. </div>
  185. </div>
  186. </div>
  187. </div>
  188. <script type="text/javascript" src="index.js"></script>
  189. </body>
  190. </html>