link标签是声明式语法,不具备执行逻辑能力,仅指示浏览器加载行为,不自动上报性能数据;所有指标必须由JavaScript主动通过performance.getEntries()或PerformanceObserver读取并上报。

外部资源引用标签本身不参与指标上报,所有上报必须由 JavaScript 主动触发;link 标签的 rel 值只影响浏览器是否加载、何时加载、如何加载,但不会自动发送任何性能数据。
为什么 link 标签不能直接上报性能数据
HTML 标签是声明式语法,不具备执行逻辑的能力。link 的 rel="preload" 或 rel="stylesheet" 只告诉浏览器“去加载”,但加载耗时、失败与否、是否阻塞渲染等信息,浏览器不会主动上报——它只把原始记录存进 performance.getEntries(),等着你手动读取。
常见错误现象:
- 在
head里写了<link rel="preload" as="script" href="/app.js">,却没写 JS 监听逻辑 → 控制台查不到该资源的duration或startTime - 以为
rel="prefetch"会触发resource类型 PerformanceEntry → 实际上它不会生成 entry,仅预加载到 HTTP 缓存,无法被getEntriesByType('resource')捕获 - 给
link加了crossorigin却没配 CDN 响应头 →duration和transferSize返回 0,误判为“加载极快”
performance.getEntriesByType('resource') 怎么正确拿到 link 加载的资源
只有带明确加载行为的 link(如 rel="stylesheet"、rel="preload"、rel="icon")才会出现在 performance.getEntriesByType('resource') 中,但需满足两个硬性前提:
立即学习“前端免费学习笔记(深入)”;
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
- 脚本必须在
window.addEventListener('load', ...)或document.readyState === 'complete'后调用,否则部分资源还没完成加载流程,条目未入库 - 跨域资源必须同时满足:
<link crossorigin>+ CDN 响应头含Access-Control-Allow-Origin: *,否则浏览器抹掉敏感字段(duration、encodedBodySize等全为 0) - 不要依赖
name字段匹配 HTML 源码中的href:动态插入的link(如 JS 创建)也会进列表,而内联style标签不会出现
示例:过滤出所有通过 link 加载的 CSS 资源
const entries = performance.getEntriesByType('resource');
const cssLinks = entries.filter(e =>
e.initiatorType === 'link' &&
e.name.endsWith('.css') &&
e.duration > 0
);
如何用 PerformanceObserver 监听 link 触发的资源加载
不能监听 link 标签本身,但可以监听其触发的资源加载事件。关键点是:PerformanceObserver 必须在 head 最顶部同步注册,且只订阅 entryTypes: ['resource'] ——但这会显著增加低端机内存压力,**生产环境不推荐**。
更稳妥的做法是:只监听 'paint' 和 'navigation',再配合 load 事件后调用 getEntriesByType('resource') 补全。如果真要实时捕获,注意:
- 避免监听
resource类型超过 1 秒,否则可能堆积数百个 entry 对象,Android WebView 容易 OOM -
observe()不能放在DOMContentLoaded回调里 → 此时很多link已加载完毕,observer 拿不到 entry - 每个
link只产生一个resourceentry,但同一个 URL 多次插入(如反复切换主题 CSS)会生成多个 entry,需按name + startTime去重
容易被忽略的细节:CSS 加载阻塞与指标失真
link[rel="stylesheet"] 是唯一能阻塞 HTML 解析和首次绘制的 link 类型,但它在 performance.getEntries() 中的 duration 并不等于“阻塞时长”。真正影响 FCP/LCP 的是:
- 从
fetchStart到responseEnd的网络耗时(可查) - 从
responseEnd到 CSSOM 构建完成的时间(不可查,浏览器不暴露) - 若该 CSS 文件内含
@import,嵌套加载不会单独成 entry,全部计入父 CSS 的duration
所以,单纯看 link 的 duration 会低估真实阻塞成本。更准的方式是比对 navigationStart 与 first-contentful-paint 时间差,并结合 Chrome DevTools 的 “Coverage” 面板确认 CSS 是否冗余加载。


















