You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何fetch获取资源生成Object URL再设iframe src,比直接设src更快?

问题

最近在为报表创建打印按钮,为保证跨浏览器一致性采用PDF版本。最初通过fetch()获取PDF,转为Blob后创建Object URL并设置为iframe的src。后来尝试直接将iframe的src设为PDF URL,却发现该方式在5秒请求中慢了约400ms,且速度差异随请求时长增大而更明显。即使加载JSON文件,差异依然存在。排除缓存因素后,fetch()仍有约90%的情况更快。请问为何通过fetch获取资源、创建Object URL再设置iframe的src,比直接设置src指向资源更快?

测试代码

JavaScript

const iframe = document.getElementById("iframe");
const testUri = "https://hacker-news.firebaseio.com/v0/topstories.json";
const fastestEl = document.getElementById('fastest')

async function runTests() {
  const srcTime = await measureLoadTimeUsingSrc()
  const fetchTime = await measureLoadTimeUsingFetch()

  document.getElementById("srcTime").textContent = srcTime;
  document.getElementById("fetchTime").textContent = fetchTime;
  
  if (srcTime < fetchTime) {
    fastestEl.textContent = 'src'
  } else if (fetchTime < srcTime) {
    fastestEl.textContent = 'fetch'
  } else {
    fastestEl.textContent = 'tie'
  }
}

function measureLoadTimeUsingSrc() {
  return new Promise((resolve, reject) => {
    const startTime = performance.now()
    iframe.src = testUri;
    iframe.addEventListener(
      "load", 
      () => resolve(performance.now() - startTime), 
      { once: true }
    );
  });
}

function measureLoadTimeUsingFetch() {
  return new Promise((resolve, reject) => {
    const startTime = performance.now()
    fetch(testUri)
      .then((result) => result.blob())
      .then((blob) => {
        iframe.src = URL.createObjectURL(blob);
        iframe.addEventListener(
          "load", 
          () => resolve(performance.now() - startTime), 
          { once: true }
        );
      })
      .finally(() => URL.revokeObjectURL(iframe.src));
  });
}

HTML

<dl>
  <dt>Time using <code>iframe.src = '…'</code><dt>
  <dd id="srcTime">…</dd>
  <dt>Time using <code>fetch('…')</code><dt>
  <dd id="fetchTime">…</dd>
  <dt>Fastest</dt>
  <dd id="fastest">…</dd>
</dl>

<iframe id="iframe" hidden></iframe>
  
<button type="button" onclick="runTests()">
  Run tests
</button>
原因分析
  • 资源加载阶段的拆分优化:直接设置iframe.src时,浏览器需要同时处理iframe上下文初始化、URL解析、网络请求、资源接收与渲染,这些步骤存在串行或部分阻塞的情况。而用fetch先获取资源时,网络请求和资源下载在主页面上下文提前完成,后续仅需将本地Blob通过Object URL传给iframe,iframe只需读取本地资源完成加载,省去了自身发起网络请求的链路开销,请求耗时越长,这种提前下载的优势越显著。
  • 浏览上下文初始化的开销差异:iframe作为独立的浏览上下文,直接设置src时,浏览器需要为其初始化安全沙箱、DOM解析器等完整环境,同时并行处理网络请求,两者的资源调度存在冲突。而先通过fetch拿到资源后,iframe的初始化与本地资源加载的重叠度更高,整体耗时更短。
  • 请求调度的优先级差异:fetch请求由主页面直接发起,任务调度优先级更高;而iframe发起的请求属于子上下文任务,调度顺序可能滞后于主上下文任务,导致整体启动延迟。
  • 缓存与校验逻辑的隐性区别:即使排除了常规缓存,iframe的请求可能会额外触发安全校验、缓存验证等步骤,而fetch请求的逻辑更直接,下载完成后转为本地Blob,完全避免了后续的网络相关校验操作。

内容的提问来源于stack exchange,提问作者tvanc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 16:33:19