资源提示:rel="preload" 与 rel="preconnect"
发布于
一句话: <link rel="preload"> 与 <link rel="preconnect"> 都是在 <head> 中声明
的资源提示,但作用不同——preload 会提前获取一个具体的高优先级资源,而 preconnect 只是
预先为某个源建立连接(DNS、TCP,对 HTTPS 还包括 TLS),不获取任何内容。
rel="preload":提前获取特定资源
Section titled “rel="preload":提前获取特定资源”根据 MDN,<link rel="preload"> 让你在页面很快就会需要某个资源时提前声明这次获取,
使浏览器在页面生命周期的早期——即浏览器主渲染流程启动之前——就开始加载它,从而降低
阻塞页面渲染的可能性。
<link rel="preload" href="/fonts/brand.woff2" as="font" type="font/woff2" crossorigin>根据 MDN,as 属性标识资源类型,使浏览器能够应用正确的 Accept 请求头、正确应用内容
安全策略,并为页面的真实请求复用预加载的资源。
rel="preconnect":预热连接,不获取任何内容
Section titled “rel="preconnect":预热连接,不获取任何内容”<link rel="preconnect" href="https://api.example.com">根据 MDN,preconnect 通过预先执行部分或全部连接握手,为将来来自该源的跨源请求、导航
或子资源提供先机。它对同源请求没有帮助,因为该连接本已建立。由于向过多第三方源预连接会
适得其反,MDN 建议只将其保留给最关键的少数几个源,对不那么关键的源改用 dns-prefetch。
preload 上的 crossorigin 属性
Section titled “preload 上的 crossorigin 属性”根据 MDN,crossorigin 属性必须匹配 preload 所代表的真实请求的 CORS 与凭据模式——同源
资源也可能需要它。根据 MDN,字体无论同源与否都以匿名模式 CORS 发出请求。
通过脚本生成提示
Section titled “通过脚本生成提示”function preloadFont(href) { const link = document.createElement('link'); link.rel = 'preload'; link.as = 'font'; link.type = 'font/woff2'; link.crossOrigin = 'anonymous'; link.href = href; document.head.appendChild(link);}运行时检测与回退
Section titled “运行时检测与回退”根据 MDN,HTMLLinkElement.relList 是反映元素 rel 属性的一个实时 DOMTokenList,
DOMTokenList.supports() 会报告某个 token 是否受支持——用它在依赖任一提示前先做特性检测:
function supportsResourceHint(rel) { const link = document.createElement('link'); // 不仅要判断 relList 是否存在,还要判断 supports 本身是否是函数: // 调用一个不存在的方法会抛出异常,而不是返回 false,这会让检测失效。 return 'relList' in link && typeof link.relList.supports === 'function' && link.relList.supports(rel);}
if (supportsResourceHint('preload')) { const link = document.createElement('link'); link.rel = 'preload'; link.as = 'font'; link.type = 'font/woff2'; link.crossOrigin = 'anonymous'; link.href = '/fonts/brand.woff2'; document.head.appendChild(link);} else { // preload 不受支持(或没有 relList.supports):无需额外回退—— // 浏览器仍会在真正的 @font-face 请求触发时发现并获取该字体, // 只是少了这个提示原本能带来的提前起步。}
if (supportsResourceHint('preconnect')) { const link = document.createElement('link'); link.rel = 'preconnect'; link.href = 'https://api.example.com'; document.head.appendChild(link);} else { // preconnect 不受支持:无需回退,浏览器在发出真实的跨源请求时 // 仍会正常建立连接。}根据 MDN,rel="preload" 与 rel="preconnect" 均已 Baseline 广泛可用——preload 自
2021 年 1 月起,preconnect 自 2020 年 1 月起——意味着在 Baseline 浏览器中已保持两年多的
一致支持。
- 为每个
preload链接设置as,使其与资源的真实请求类型匹配(font、style、script、image等)。 - 只要真实请求会以 CORS 模式发出就添加
crossorigin——字体请求始终需要,即使同源 也不例外——以便与真实请求匹配。 - 根据 MDN,将
preconnect保留给最关键的连接;其余第三方源改用dns-prefetch。 - 只 preload 当前页面真正尽早需要的资源——根据 MDN,预加载未被使用的替代格式可能 浪费带宽。