Skip to content

APM 系统的标准分层架构(三大平面)

shell
┌─────────────────────────────────────────────────────────────┐
                      展示层 (Presentation)                  │
         Web Console / 告警平台 / API Gateway
└─────────────────────────────────────────────────────────────┘

 查询/聚合
┌─────────────────────────────────────────────────────────────┐
                   数据存储与计算层 (Storage/Compute)         │
  时序数据库(ES/TiDB) + 流计算引擎(Flink/Spark) + 索引服务
└─────────────────────────────────────────────────────────────┘

 上报/推送
┌─────────────────────────────────────────────────────────────┐
                    数据采集与传输层 (Collector/Agent)        │
     Agent探针(Java/Python/Node/浏览器SDK)  Kafka/RPC
└─────────────────────────────────────────────────────────────┘

 埋点/注入
┌─────────────────────────────────────────────────────────────┐
                     目标应用系统 (Target System)             │
    你的H5页面 后端微服务 数据库/缓存/第三方API
└─────────────────────────────────────────────────────────────┘

DOMContentLoaded async 脚本虽然不阻塞HTML解析,但会阻塞 DOMContentLoaded

内联样式块会阻塞 DOMContentLoaded 直到样式表解析完成

如果域名解析慢或不可用,会阻塞页面

上报性能数据

javascript
// 只有5%的用户上报性能数据
if (random() > 0.05) {
    return; // 大部分用户不执行,性能影响为0
}
navigator.sendBeacon('/api/performance', JSON.stringify(data))

合并小图片为雪碧图

css
/* 使用 CSS Sprite */
.sprite {
    background-image: url('sprite.png');
    background-repeat: no-repeat;
}
.sprite-close { background-position: 0 0; width: 20px; height: 20px; }
.sprite-delete { background-position: -25px 0; width: 20px; height: 20px; }
.sprite-mingxi { background-position: -50px 0; width: 20px; height: 20px; }

监控指标

🟦 蓝色 (HTML) HTML文件 解析HTML文档的网络请求和解析时间。 xxxx.html 自身的加载和解析。

🟨 黄色 (Script) JavaScript 加载、解析和执行JS脚本的时间。这是优化的重点区域。 performance.js的加载与执行。 黄色块过长,说明监控脚本执行耗时多(你之前观察到的资源加载51ms就是黄色的部分)。

🟪 紫色 (Styles) CSS 解析CSS样式和计算样式(Recalculate Style)的时间。 页面内联样式和任何外部CSS的处理。

🟩 绿色 (Layout) 布局/渲染 计算页面元素几何位置(Layout / Reflow)的时间。 频繁的DOM操作会触发此过程,也是你代码中需要避免多次操作loading元素显示隐藏的原因。

🟥 红色 (Paint) 绘制 将像素绘制到屏幕上的时间。 首次绘制(FP)和首次内容绘制(FCP)。

⬜ 灰色 (System) 系统/空闲 浏览器系统本身的开销,或主线程处于空闲状态。 可能包含垃圾回收(GC)等操作。

⬛ 深灰 (Idle) 空闲 主线程没有任务在处理。 理想的空闲时段,适合用来安排requestIdleCallback()执行非关键任务。

使用 WebP 图片

html
<picture>
    <source srcset="image.webp" type="image/webp">
    <img src="image.png" alt="描述">
</picture>

重点应该放在图片优化和缓存策略上,而不是网络层优化

添加缓存策略

javascript
// 在响应头中设置缓存
// 静态资源缓存 1 年
Cache-Control: public, max-age=31536000, immutable

// HTML 文件不缓存
Cache-Control: no-cache, no-store, must-revalidate

监控实际用户加载时间

// 添加真实用户监控 (RUM)

javascript
window.addEventListener('load', () => {
    const perfData = {
        fcp: performance.getEntriesByType('paint')
            .find(e => e.name === 'first-contentful-paint')?.startTime,
        lcp: performance.getEntriesByType('largest-contentful-paint')[0]?.startTime,
        ttfb: performance.getEntriesByType('navigation')[0]?.responseStart,
        loadTime: performance.now()
    }
    console.log('用户加载数据:', perfData)
    
    // 上报到监控系统
    // navigator.sendBeacon('/api/performance/rum', JSON.stringify(perfData))
})