preconnect必须写在head内且位于首个link或script之前才生效,href需为完整HTTPS域名不带路径,crossorigin属性必须为空值且仅对首屏1秒内必发的第三方HTTPS域名使用。

preconnect必须写在最顶部才生效
浏览器是流式解析 HTML 的,preconnect 提示只有在遇到第一个 <link rel="stylesheet"> 或 <script> 之前被读到,才来得及提前建连。放晚了,连接窗口就关了。
- ✅ 正确位置:
<head><link rel="preconnect" href="https://api.example.com" crossorigin><link rel="stylesheet" href="/main.css"></head> - ❌ 无效位置:放在
<link rel="stylesheet">后面、<body>里、或用 JS 动态插入(document.head.appendChild()) - ⚠️ 同一域名多次声明,只有第一个生效;重复写不会叠加效果,反而浪费标签空间
href必须是完整HTTPS协议+域名,不能带路径
preconnect 的 href 不是资源地址,而是连接目标。它只负责建立 DNS + TCP + TLS 链路,不拉取任何内容。写错格式,浏览器直接忽略,Network 面板里也看不到预连记录。
- ✅ 正确写法:
https://fonts.gstatic.com、https://cdn.example.com - ❌ 错误写法:
//fonts.gstatic.com(协议相对,降级为dns-prefetch)、https://fonts.gstatic.com/css2(含路径)、http://api.example.com(Chrome 直接跳过) - ⚠️ 子域名如
a.cdn.example.com和b.cdn.example.com若共用同一套 DNS 和 CDN 配置,只预连cdn.example.com更高效
crossorigin属性不是可选,是复用前提
浏览器把带 crossorigin 和不带的连接视为两个独立连接池。漏写或写错,预建的连接根本无法被后续请求复用——比如字体加载、带凭据的 fetch(),都会重走一遍 TLS 握手。
- ✅ 必须加:
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>(字体响应头含Access-Control-Allow-Origin: *) - ✅ 可不加:纯静态 JS/CSS(如
https://cdn.jsdelivr.net/npm/react@18/umd/react.production.min.js),且没传credentials: 'include' - ❌ 错误写法:
crossorigin=""或crossorigin="anonymous"—— HTML 规范只接受空属性值,带等号会被解析失败 - ⚠️ 如果 JS 中
fetch("https://api.example.com", { credentials: 'include' }),服务端必须返回Access-Control-Allow-Credentials: true,此时仍要保留crossorigin属性
只对首屏1秒内必发的HTTPS第三方域名加
preconnect 不是“越多越好”,它是有成本的:每个占用一个空闲 TCP 连接槽位,而浏览器对单域名并发连接数上限通常为 6。加错对象,反而拖慢主资源加载。
立即学习“前端免费学习笔记(深入)”;
- ✅ 值得加:Google Fonts(
https://fonts.googleapis.com+https://fonts.gstatic.com)、首屏立即fetch()的 API(如https://api.example.com)、CDN 上已声明的首屏 CSS/JS(如https://cdn.example.com/main.css) - ❌ 别加:分析 SDK(如
https://plausible.io)若仅用于埋点上报、客服弹窗、分享按钮——它们由用户交互触发,时间不确定 - ⚠️ 收益集中在弱网、高延迟地区;本地开发或千兆光纤下几乎测不出差异
- ⚠️ 如果 JS 在 preconnect 后 2 秒才发请求,连接可能已被回收,白做
preconnect 就只是多了一行无用的 HTML。



















