dns-prefetch 的 href 必须为协议相对域名(如//cdn.example.com)或显式 HTTPS 域名,不可含路径、端口、参数;须置于 head 靠前位置,仅对后续真实异步跨域请求有效,且不可与 preconnect 混用同一域名。

dns-prefetch 的 href 必须只含协议相对域名,写错等于没写
浏览器只从 href 属性中提取主机名做 DNS 查询,其余内容全被忽略——路径、端口、查询参数、协议头,哪怕多一个斜杠或少一个斜杠,整个 <link rel="dns-prefetch"> 标签都会被静默丢弃,控制台零报错,极难排查。
常见错误包括:
-
<link rel="dns-prefetch" href="//cdn.example.com/js/app.js">—— 含路径,被忽略 -
<link rel="dns-prefetch" href="http://api.example.com">—— HTTPS 页面下大概率跳过 -
<link rel="dns-prefetch" href="cdn.example.com">—— 缺双斜杠,被当成本地相对路径处理
✅ 正确写法只有两种:<link rel="dns-prefetch" href="//cdn.example.com">(推荐)或 <link rel="dns-prefetch" href="https://fonts.googleapis.com">(仅限 HTTPS 页面且目标明确支持 HTTPS)。
必须放在 <head> 靠前位置,动态插入或放太晚等于白加
浏览器流式解析 HTML,<link rel="dns-prefetch"> 一旦被读到就立即排队执行 DNS 查询。如果它出现在大量 CSS/JS 之后,或塞在 <body> 里,相关资源请求早就发出去了。
立即学习“前端免费学习笔记(深入)”;
✅ 推荐位置:<meta charset> 和 <title> 之后、首个 <link rel="stylesheet"> 或 <script> 之前。
❌ 无效位置:
- 塞在
<body>里 - 包裹在
<template>中 - 由 JS 动态创建(如
document.createElement('link'))
⚠️ 即使位置正确,若前面堆了大量阻塞渲染的 CSS/JS,DNS 查询可能被首屏关键资源抢占调度优先级,尤其 Safari 更保守,常延迟到空闲或用户交互后才执行。
只对后续真实异步请求的第三方域名有效,同源或未用域名纯属浪费
dns-prefetch 不加速首屏资源,只影响 JS 中 fetch、懒加载图片、字体 CSS 加载等后续异步请求。每个预解析都占用浏览器 DNS 并发队列(通常限 6~10 个),乱加反而拖慢真实请求。
✅ 值得加的域名(满足两个条件:页面真实会请求 + 未在首屏 HTML 中直接出现):
-
//cdn.example.com(图片/JS/CSS 真实从该 CDN 加载) -
//api.example.com(首屏后立即发起的 AJAX) -
//hm.baidu.com(百度统计 SDK 初始化必调)
❌ 不该加的域名:
-
//your-site.com(同源,浏览器已缓存解析) -
//ad.doubleclick.net(广告联盟不稳定、常被拦截) -
//admin.example.com(子域共享主域 DNS 缓存)
不能和 preconnect 混用同一域名,否则后者被忽略
preconnect 已隐含 DNS 解析 + TCP 握手 + TLS 协商(HTTPS 下),开销远高于 dns-prefetch。同一域名既写 preconnect 又写 dns-prefetch,后者会被浏览器直接忽略,纯属冗余。
怎么选?看下一步动作:
- 只是“将来可能会请求”,比如备用埋点域名、社交分享接口 → 用
<link rel="dns-prefetch" href="//metrics.example.com"> - “接下来 1 秒内就要 fetch 字体或 JS”,比如
fonts.googleapis.com→ 用<link rel="preconnect" href="https://fonts.googleapis.com" crossorigin>
实际项目中可组合使用:对全部关键第三方先 dns-prefetch 备着,再对最核心的 1–2 个源 preconnect,但绝不能重复声明同一域名。



















