前端性能优化必看:preload和prefetch让页面加载快人一步(附避坑指南)

前端性能优化必看:preload和prefetch让页面加载快人一步(附避坑指南)
前端性能优化必看:preload和prefetch让页面加载快人一步(附避坑指南)
先说个扎心的事儿
你家的网站首屏加载是不是慢到用户想砸手机?明明资源都压缩了、图片也懒加载了、CDN也上了,为啥还是卡成PPT?用户在那盯着白屏发呆三秒钟,心里早就把你祖宗十八代问候了个遍,然后手指一滑,拜拜了您嘞,转化率直接归零。
我跟你说,这事儿真不能全怪网络。浏览器其实早就给了你加速神器,只是你没用对,或者说,你根本不知道它的存在。今天就把这个压箱底的干货掏出来跟大家唠唠——preload和prefetch这对卧龙凤雏,用好了能让你的页面加载快人一步,用错了……嘿嘿,那画面太美我不敢看。
说实话,我第一次听说这俩API的时候,心里也是懵逼的:这不都是预加载吗?有啥区别?后来踩了一堆坑,被测试小姐姐追着骂,被产品经理质疑能力,才慢慢琢磨出门道。现在就把这些血泪经验分享出来,希望能帮你少走点弯路。
浏览器加载资源那点门道
要搞懂preload和prefetch,咱得先聊聊浏览器是怎么加载资源的。这玩意儿就跟排队打饭一样,讲究个先来后到、尊卑有序。
Chrome内部给资源排优先级的骚操作
Chrome内核(Blink)给资源分了五个优先级档次,从Highest到Lowest,跟王者荣耀的段位似的:
- Highest:HTML文档本身,这是祖宗,没它页面都渲染不出来
- High:CSS样式表,没有CSS页面就是一团乱麻,用户看了直接崩溃
- Medium:普通的JS脚本、图片这些
- Low:异步加载的脚本、预加载的资源
- Lowest:
prefetch预加载的资源,基本就是"有空再搞"的意思
浏览器会根据资源类型、位置、属性自动分配优先级。比如放在<head>里的同步JS就是High,放在</body>前面的就是Medium,加了async或defer的就更低。
HTML和CSS为啥永远站在鄙视链顶端
你想啊,HTML是页面的骨架,CSS是衣服,JS是肌肉。骨架和衣服都没有,你光有一身肌肉(JS),那不就是解剖课上的标本吗?吓人不说,根本没法看。所以浏览器会优先保证HTML和CSS的下载和解析,这是渲染阻塞资源,必须等它们到位才能开始画页面。
这里有个关键概念叫关键渲染路径(Critical Rendering Path)。浏览器收到HTML后开始解析,遇到CSS就发请求,同时继续解析HTML。等CSS回来了,构建CSSOM,和DOM一起合成渲染树,然后布局、绘制。如果CSS卡住了,后面的步骤全得等着。
JS脚本根据位置不同待遇天差地别
JS这玩意儿特别矫情。默认情况下,浏览器遇到<script>标签就会停下来下载并执行,因为JS可能会修改DOM和CSSOM。这就是所谓的脚本阻塞。
<!-- 这种写法会阻塞渲染,优先级 High -->
<script src="critical.js"></script>
<!-- 放在底部,优先级 Medium,不会阻塞首屏 -->
<script src="non-critical.js"></script>
<!-- async 异步下载,下载完立即执行,优先级 Low -->
<script async src="analytics.js"></script>
<!-- defer 异步下载,等HTML解析完再执行,优先级 Low -->
<script defer src="app.js"></script>
所以老前端都知道,非关键的JS要放底部,或者加async/defer。但有时候有些JS就是关键资源,比如埋点库、错误监控,这时候就得用preload来提前加载,避免阻塞。
一张图看懂浏览器加载队列的内心戏
想象一下浏览器内部有个资源调度中心,就像机场塔台指挥飞机起降:
- HTML文档最先起飞(Highest)
- CSS紧随其后(High)
- 首屏需要的字体、关键JS开始排队(High/Medium)
- 图片资源根据是否在视口内决定优先级(Medium/Low)
prefetch的资源被扔到了"候补席",等前面没活儿了再说(Lowest)
preload的作用就是让你可以手动调整这个队列,把某个资源从经济舱升级到头等舱。而prefetch则是给下一趟航班占个座,这趟航班先不管它。
preload到底是个啥玩意儿
官方说法叫资源提示符(Resource Hint),咱说人话就是插队券。你告诉浏览器:“这个资源我现在马上就要用,你给我插队到最前面,别的资源先靠边站。”
告诉浏览器这个资源我现在马上就要用
preload的设计初衷是解决** late-discovered resources **的问题。啥意思呢?就是有些资源浏览器一开始不知道需要它,等解析到某个阶段才发现:"哎呀,原来还需要这个字体/图片/脚本!"这时候才去下载,就耽误了时间。
最典型的例子就是自定义字体。CSS里用@font-face声明了字体,但浏览器解析CSS的时候只是记下了这个声明,等到实际渲染文本时才发现:"卧槽,这个字要用WebFont,我得去下载!"这时候用户已经看到文字了,然后文字突然一闪变成自定义字体,这就是FOIT(Flash of Invisible Text)或FOUT(Flash of Unstyled Text),体验极差。
用preload可以提前把字体下载好:
<!-- 提前加载字体文件,避免字体闪烁 -->
<link rel="preload" href="/fonts/awesome-font.woff2" as="font" type="font/woff2" crossorigin>
注意那个crossorigin属性,字体资源是跨域的,必须加这个,不然浏览器不会用预加载的字体,还是会重新下载。
优先级直接拉到最高不给其他资源留面子
当你用preload时,浏览器会把对应资源的优先级提升到High甚至Highest,跟CSS一个级别。这意味着它会抢占带宽,其他资源得先等等。
这既是优点也是缺点。优点是真的快,缺点是用多了会挤占其他资源的带宽,反而拖慢整体加载。所以preload要精准打击,只用来加载真正关键的资源。
加载完放内存缓存里当前页面随取随用
preload加载的资源会放在**内存缓存(Memory Cache)**里,这个页面内随取随用,速度极快。而且因为是预加载,浏览器会提前建立连接、解析DNS,真正用到的时候直接拿,省去了网络往返的时间。
必须配合as属性不然浏览器会重复下载白忙活
这里有个大坑!preload必须配合as属性使用,告诉浏览器这个资源是什么类型。可能的值包括:
script:JavaScript文件style:CSS文件font:字体文件image:图片fetch:XHR或Fetch请求document:HTML文档(用于iframe)
为啥必须写as?因为浏览器要根据资源类型设置正确的请求头、优先级、CSP策略等。如果你不写as,或者写错了,浏览器下载了也不会用,等真正需要的时候会重新下载一遍,白忙活一场。
<!-- 正确写法 -->
<link rel="preload" href="/js/app.js" as="script">
<!-- 错误写法 - 不写as -->
<link rel="preload" href="/js/app.js">
<!-- 错误写法 - as写错 -->
<link rel="preload" href="/js/app.js" as="style"> <!-- 浏览器会以为是CSS,不会执行JS -->
还有个type属性用于指定MIME类型,如果浏览器不支持这种类型就不会下载,用来做渐进增强:
<!-- 只有支持module的浏览器才会预加载 -->
<link rel="preload" href="/js/app.mjs" as="script" type="module">
prefetch又是哪路神仙
如果说preload是个急性子,prefetch就是个佛系青年。它的意思很明确:“这个资源现在不用,但等会儿可能要,你先准备着,有空的时候下载一下,没空就算了。”
跟preload比起来就是个佛系青年
prefetch的优先级是Lowest,浏览器只有在当前页面的关键资源都下载完了,带宽空闲的时候,才会去下载prefetch的资源。如果用户网络不好,或者很快跳走了,可能根本就不会下载。
这听起来好像很鸡肋?其实不然。它的设计目标就是为下一页预加载资源,提升后续导航的体验。
意思是这个资源现在不用但等会儿可能要
典型的使用场景是单页应用(SPA)的路由切换。用户在首页,很可能下一步会跳转到详情页。你可以prefetch详情页需要的代码块,等用户真的点击时,资源已经缓存好了,切换秒开。
<!-- 预加载下一页可能需要的资源 -->
<link rel="prefetch" href="/js/detail-page.js">
<link rel="prefetch" href="/api/product-detail.json">
优先级降到最低等浏览器闲了再慢慢下
因为优先级低,prefetch不会跟当前页面的资源抢带宽,不会影响首屏加载。这是它和preload最大的区别之一。
适合预加载下一页可能用到的东西
除了SPA,多页应用(MPA)也能用。比如电商网站,用户在商品列表页,你可以prefetch商品详情页的关键资源。但要注意,别一股脑把所有链接对应的页面都prefetch,那会把用户的流量吃光,而且浏览器有并发限制,太多反而一个都下不下来。
缓存机制跟preload不一样跨页面也能用
prefetch的资源会放在**HTTP缓存(Disk Cache)**里,跨页面也能用。用户从A页跳到B页,如果B页需要的资源在A页已经prefetch过了,直接从缓存拿,速度飞快。
而preload的资源主要在内存缓存里,页面关了就没,而且一般不跨页面共享(除非是用Service Worker做了特殊处理)。
这俩兄弟的区别得拎清楚
说实话,我刚学的时候经常搞混这俩,以为都是预加载,随便用哪个都行。后来吃了亏才明白,它们的差异可大了去了。
使用场景完全不同别搞混了闹笑话
| 特性 | preload | prefetch |
|---|---|---|
| 目标 | 当前页面 | 下一页/未来页面 |
| 优先级 | High/Highest | Lowest |
| 缓存位置 | 内存缓存 | 磁盘缓存 |
| 是否阻塞 | 可能阻塞渲染(如果滥用) | 不阻塞 |
| 跨页面 | 一般不共享 | 可以共享 |
preload管当前页面prefetch管未来页面
这是最根本的区别。preload解决的是"我现在就需要,但浏览器发现得晚"的问题。prefetch解决的是"我一会儿可能需要,先准备着"的问题。
优先级一个天一个地带宽分配差很多
preload会抢占带宽,所以要慎用。prefetch是"捡漏"的,有剩余带宽才下,不会影响当前页面。
缓存行为也不一样复用效率有讲究
preload在内存里,快但生命周期短;prefetch在磁盘里,慢点但持久。如果你预加载的资源是下一页用的,用prefetch更合适,因为用户可能过一会儿才跳转,内存缓存可能早被清掉了。
用错了不仅没加速还可能拖慢页面
我见过有人把页面上所有图片都用preload,结果首屏加载反而更慢了,因为带宽被这些图片占满,CSS和JS都在排队。这就是典型的滥用。
还有人用prefetch来加载当前页面需要的资源,结果浏览器优先级太低,等到用的时候还没下载完,白预加载一场。
实际开发中咋用才不翻车
理论讲了一堆,来点实战的。这些都是我在项目里真实用过的方案,有成功的也有踩坑的,分享出来供参考。
关键CSS文件用preload避免渲染阻塞
如果你的CSS是动态加载的(比如通过JS判断加载不同主题),或者CSS文件特别大,可以用preload提前加载:
<!-- 提前加载关键CSS -->
<link rel="preload" href="/css/critical.css" as="style" onload="this.rel='stylesheet'">
<!-- 兜底:如果JS禁用,用noscript -->
<noscript><link rel="stylesheet" href="/css/critical.css"></noscript>
这里用了个小技巧:onload="this.rel='stylesheet'",这样预加载完成后自动应用样式,不会重复下载。但要注意,这种写法在Safari上有兼容性问题,需要polyfill或者直接用传统的<link rel="stylesheet">。
更稳妥的做法是直接用preload提示,然后正常引入CSS:
<link rel="preload" href="/css/main.css" as="style">
<link rel="stylesheet" href="/css/main.css">
浏览器会聪明地复用预加载的CSS,不会下载两次。
自定义字体预加载告别字体闪烁的尴尬
字体预加载是最常见的preload使用场景。前面说过,字体是late-discovered resource,不用preload就会出现闪烁。
<!-- 预加载自定义字体 -->
<link rel="preload" href="/fonts/Inter-Regular.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/fonts/Inter-Bold.woff2" as="font" type="font/woff2" crossorigin>
<style>
@font-face {
font-family: 'Inter';
src: url('/fonts/Inter-Regular.woff2') format('woff2');
font-weight: 400;
font-display: swap; /* 配合font-display使用 */
}
@font-face {
font-family: 'Inter';
src: url('/fonts/Inter-Bold.woff2') format('woff2');
font-weight: 700;
font-display: swap;
}
body {
font-family: 'Inter', sans-serif;
}
</style>
注意几点:
- 必须加
crossorigin,即使是同域字体(因为字体请求默认是anonymous CORS模式) - 只预加载关键字体,比如Regular和Bold,Light、Italic这些非关键的字重可以不管
- 配合
font-display: swap,让浏览器先用系统字体渲染,等自定义字体来了再换,避免 invisible text
首屏图片该预加载就别懒加载了
懒加载(lazy loading)是个好技术,但首屏图片不能懒加载,因为用户一进来就要看到。这些图片可以用preload提前加载:
<!-- 首屏Hero图片预加载 -->
<link rel="preload" href="/images/hero-banner.webp" as="image" type="image/webp" imagesrcset="/images/hero-banner-400.webp 400w, /images/hero-banner-800.webp 800w" imagesizes="100vw">
<!-- 响应式图片预加载(Chrome 73+支持) -->
<link rel="preload" href="/images/hero.png" as="image" imagesrcset="/images/hero-400.png 400w, /images/hero-800.png 800w" imagesizes="(max-width: 600px) 400px, 800px">
这里用了imagesrcset和imagesizes,让浏览器根据屏幕大小预加载合适的图片尺寸,避免浪费带宽。
但要注意,不要预加载太多图片。一般来说,首屏只有1-2张关键图片需要预加载,其他的用懒加载。
路由跳转的下一个页面资源可以prefetch
在SPA里,结合路由库可以做智能预加载。比如用React Router:
// 路由配置
const routes = [
{
path: '/',
component: Home,
// 首页组件本身可能需要预加载其他资源
},
{
path: '/product/:id',
component: () => import('./ProductDetail'), // 动态导入
prefetch: true // 标记可预加载
}
];
// 在Link组件里做hover预加载
const SmartLink = ({ to, children }) => {
const handleMouseEnter = () => {
// 鼠标放上去就开始预加载
const route = routes.find(r => r.path === to);
if (route && route.component && typeof route.component === 'function') {
route.component(); // 执行动态导入
}
// 也可以prefetch API数据
if (to.startsWith('/product/')) {
const link = document.createElement('link');
link.rel = 'prefetch';
link.href = `/api/product/${to.split('/').pop()}`;
document.head.appendChild(link);
}
};
return (
<Link to={to} onMouseEnter={handleMouseEnter}>
{children}
</Link>
);
};
这个思路是预测用户行为。鼠标hover到链接上时,有很大概率用户会点击,这时候开始预加载,等真的点击时资源已经准备好了。从hover到click通常有几百毫秒的时间,足够下载很多资源了。
SPA应用里配合代码分割效果更香
现代前端工具(Webpack、Vite、Rollup)都支持代码分割,配合import()动态导入和prefetch,可以实现路由级别的按需加载+预加载:
// Webpack魔法注释实现prefetch
const AdminDashboard = () => import(
/* webpackChunkName: "admin" */
/* webpackPrefetch: true */ // 告诉Webpack生成prefetch标签
'./AdminDashboard.vue'
);
// 或者手动控制
const UserProfile = () => import('./UserProfile.vue');
// 在用户登录后,预加载管理后台(因为登录后很可能有权限进后台)
if (user.isLoggedIn && user.hasAdminRole) {
// 动态创建prefetch link
const link = document.createElement('link');
link.rel = 'prefetch';
link.href = '/js/admin-dashboard.js'; // 根据实际chunk文件名调整
document.head.appendChild(link);
}
Webpack的webpackPrefetch: true会自动在head里插入<link rel="prefetch">,省心省力。
视频海报图提前加载用户体验直接拉满
如果页面有视频,海报图(poster)是用户首先看到的,可以用preload:
<!-- 预加载视频海报 -->
<link rel="preload" href="/images/video-poster.jpg" as="image">
<video poster="/images/video-poster.jpg" controls preload="none">
<source src="/video/demo.mp4" type="video/mp4">
</video>
注意视频的preload属性默认是auto,会预加载视频数据,如果不需要可以设为none或metadata,节省流量。
踩过的坑都在这儿了别重复造轮子
说了这么多好处,也得说说坑。这些都是我血泪的教训,希望你别重蹈覆辙。
preload忘记写as属性导致资源下载两次
这个前面强调过了,但太常见了,再啰嗦一遍。有一次我预加载一个JSON文件(用于Web Worker),写了:
<!-- 错误!JSON应该用fetch -->
<link rel="preload" href="/data/config.json">
结果浏览器下载了一遍,然后Fetch API又下载了一遍,因为浏览器不知道这个资源是干嘛用的,没放到对应的缓存池里。正确的写法是:
<!-- 正确:用as="fetch" -->
<link rel="preload" href="/data/config.json" as="fetch" crossorigin>
然后在JS里:
fetch('/data/config.json')
.then(res => res.json())
.then(data => {
// 浏览器会复用预加载的响应
});
滥用preload把不该优先的资源也插队
我曾经把页面上所有字体(Regular、Light、Bold、Italic、Bold Italic,共5个文件)都用preload,结果首屏加载时间从1.2秒涨到了2.5秒,因为带宽被字体占满了,CSS和JS都在排队等。
后来只预加载了Regular和Bold,其他的让浏览器正常加载,首屏时间降回1.3秒。记住:只预加载关键资源。
prefetch用太多占用带宽反而拖慢当前页
虽然prefetch优先级低,但如果你prefetch了几十个资源,浏览器还是会尝试下载,这会占用TCP连接数、消耗用户流量,而且可能挤占当前页面的非关键资源(比如图片)的带宽。
建议一个页面prefetch的资源不超过5-10个,而且要是高概率会用到的。
移动端网络环境下要更谨慎使用
移动端网络不稳定,用户可能用的是2G/3G或者流量紧张。这时候prefetch可能浪费用户流量,而且下载速度慢,还没下完用户就跳走了。
可以用Network Information API检测网络状况,智能决定是否prefetch:
// 检测网络状况
const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
if (connection) {
// effectiveType可能是 '4g', '3g', '2g', 'slow-2g'
if (connection.effectiveType === '4g' && !connection.saveData) {
// 只有4G且未开启省流量模式时才prefetch
const link = document.createElement('link');
link.rel = 'prefetch';
link.href = '/js/next-page.js';
document.head.appendChild(link);
}
}
跟懒加载配合使用时机没把握好
有个常见误区:给懒加载的图片加preload。这逻辑上是矛盾的——懒加载是为了"不需要的时候不加载",preload是为了"提前加载"。如果你预加载了懒加载的图片,那还懒加载个啥?
正确的做法是:首屏关键图片用preload,非首屏图片用懒加载。
<!-- 首屏关键图片:preload + 不懒加载 -->
<link rel="preload" href="/images/hero.jpg" as="image">
<img src="/images/hero.jpg" alt="Hero" width="800" height="600">
<!-- 非首屏图片:懒加载,不要preload -->
<img data-src="/images/below-fold.jpg" loading="lazy" alt="Below fold" width="400" height="300">
开发者工具里看不到prefetch缓存别慌
有时候你在Network面板里看不到prefetch的请求,或者看到状态是pending,这是正常的。因为prefetch优先级太低,可能被推迟执行,或者被浏览器取消了(比如用户很快跳走了)。
想看prefetch是否生效,可以在Application面板的Cache Storage或Local Storage里查看,或者看后续页面加载时这些资源是否从disk cache读取。
排查问题的思路得有一套
优化完了得验证效果,出了问题得会排查。下面是我常用的调试方法。
打开Chrome开发者工具Network面板
这是最基本的操作。打开DevTools,切换到Network面板,勾选"Disable cache"(禁用缓存)来模拟首次访问,或者保持不勾选来看缓存效果。
看Priority列确认资源优先级对不对
在Network面板的表头右键,勾选"Priority"列,可以看到每个资源的优先级:
- 如果你用了
preload,应该看到对应资源的优先级是High - 如果是
prefetch,应该是Lowest - 如果不对,检查
rel和as属性是否写对
Waterfall瀑布图能看出加载时序有没有问题
看Waterfall列,资源是从上到下发请求的。关键资源(CSS、关键JS)应该尽早开始下载,如果它们开始得很晚,说明被其他资源阻塞了,可能需要调整顺序或用preload提升优先级。
内存缓存和磁盘缓存的区别要分清楚
在Size列可以看到缓存类型:
(memory cache):内存缓存,极快,页面关闭即消失(disk cache):磁盘缓存,较快,跨页面可用(prefetch cache):Chrome对prefetch资源的特殊标记,其实也是disk cache的一种
如果你preload了一个资源,但看到它是从disk cache读取的,说明预加载没生效,可能是as属性写错了。
Lighthouse跑分能给你优化建议
Lighthouse是Google的自动化测试工具,在DevTools的Lighthouse面板就能跑。它会检测你是否正确使用了preload和prefetch,并给出建议。
常见的相关审计项:
- Preload key requests:提示你应该预加载的关键资源
- Preload Largest Contentful Paint image:提示预加载LCP图片
- Avoid enormous network payloads:警告你预加载了太多资源
Performance面板记录加载过程慢慢分析
对于复杂的性能问题,用Performance面板记录页面加载过程,可以看到:
- 每个资源的精确加载时间
- 主线程的阻塞情况
- 渲染的具体时间点(FP、FCP、LCP等)
结合这些信息,可以判断preload是否真的起到了加速作用,还是只是增加了竞争。
几个让性能起飞的小技巧
最后分享一些进阶技巧,都是我实战中总结的。
关键路径资源尽量用preload提前招呼
关键渲染路径上的资源,如果不在HTML最开始就引入,都可以用preload。比如:
<head>
<!-- 1. 预加载关键CSS -->
<link rel="preload" href="/css/critical.css" as="style">
<!-- 2. 预加载关键字体 -->
<link rel="preload" href="/fonts/main.woff2" as="font" crossorigin>
<!-- 3. 预加载首屏关键JS(比如埋点库) -->
<link rel="preload" href="/js/monitor.js" as="script">
<!-- 4. 正常引入CSS -->
<link rel="stylesheet" href="/css/critical.css">
</head>
非关键资源该defer就defer别堵着渲染
不要所有JS都塞在<head>里,非关键的(比如统计代码、广告脚本、社交分享按钮)都放底部或加defer:
<!-- 关键JS,可能用preload -->
<script src="/js/app.js" defer></script>
<!-- 非关键JS,放底部 -->
<script src="/js/analytics.js" async></script>
<script src="/js/chat-widget.js" defer></script>
图片根据重要性决定preload还是懒加载
制定一个图片加载策略:
- LCP图片(最大内容绘制,通常是首屏大图):
preload+ 优先加载 - 首屏其他图片:正常加载,不用
preload也不用懒加载 - 非首屏图片:
loading="lazy"懒加载 - 可能很快要看的图片(比如轮播图的下一张):
prefetch或提前用JS加载
<!-- LCP图片预加载 -->
<link rel="preload" as="image" href="/images/hero.webp">
<!-- 首屏普通图片 -->
<img src="/images/logo.png" alt="Logo" width="200" height="50">
<!-- 非首屏懒加载 -->
<img data-src="/images/footer.png" loading="lazy" alt="Footer" width="400" height="200">
第三方脚本能异步就别同步加载
第三方脚本(Google Analytics、Facebook Pixel、客服插件等)通常很慢,而且不受你控制。一定要用异步加载,避免阻塞:
<!-- 异步加载Google Analytics -->
<script>
// 动态创建script标签,避免阻塞
window.gaLoaded = new Promise((resolve) => {
const script = document.createElement('script');
script.src = 'https://www.google-analytics.com/analytics.js';
script.async = true;
script.onload = resolve;
document.head.appendChild(script);
});
</script>
如果第三方脚本支持async或defer属性,直接用:
<script src="https://third-party.com/script.js" async defer></script>
结合preconnect提前建立连接更省时
preconnect是另一个资源提示符,用来提前建立DNS查询、TCP连接、TLS握手,适用于那些你确定会访问的第三方域名:
<!-- 提前建立Google Fonts的连接 -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<!-- 然后正常引入字体CSS -->
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
这样等浏览器解析到CSS需要下载字体时,连接已经建立好了,省去了几百毫秒的连接时间。
preconnect和preload可以配合使用:
<!-- 1. 先建立连接 -->
<link rel="preconnect" href="https://cdn.example.com">
<!-- 2. 预加载关键资源 -->
<link rel="preload" href="https://cdn.example.com/critical.js" as="script">
DNS预解析dns-prefetch小细节大作用
如果有些域名你不确定是否会访问,或者只是可能访问,用dns-prefetch做DNS预解析,比preconnect更轻量:
<!-- 预解析DNS -->
<link rel="dns-prefetch" href="https://api.example.com">
<link rel="dns-prefetch" href="https://cdn.example.com">
<link rel="dns-prefetch" href="https://images.example.com">
这样等真正请求这些域名时,DNS已经解析好了,节省几十到几百毫秒。
preconnect和dns-prefetch的关系:
preconnect= DNS + TCP + TLS, heavier but faster when useddns-prefetch= DNS only, lighter but less gain
建议:关键第三方域名用preconnect,其他可能用到的用dns-prefetch。
最后唠两句
性能优化这事儿没有银弹,别指望一招鲜吃遍天。preload和prefetch只是工具箱里的两件工具,用对了是神器,用错了就是累赘。
我见过的最离谱的案例,有人给页面上的所有外链CSS和JS都加了preload,结果首屏时间增加了3秒,因为浏览器带宽被这些预加载占满,真正关键的资源反而在排队。这就是典型的"优化过度"。
记住几个原则:
- 测了再优化:先用Lighthouse、WebPageTest等工具测出瓶颈,针对性优化
- 少即是多:预加载的资源越少越好,只选最关键的
- 移动端优先:移动端网络差,更要谨慎使用,做好降级方案
- 持续监控:性能优化不是一次性的,要持续监控,防止回归
多测多看,不瞎搞,线上出问题就尴尬了。下次面试被问到这个,你能侃侃而谈半小时,从浏览器原理讲到实战案例,从API细节讲到踩坑经验,面试官肯定对你刮目相看。
老板问你为啥网站变快了,你就把这篇文章甩给他,让他知道前端不是切图仔,是正经的技术活。当然,如果他看不懂,你就说:“用了一些浏览器底层的资源调度优化技术”,显得更高深莫测。
行了,就聊到这儿。该去改代码了,祝你页面加载飞快,用户永不流失,SEO排名暴涨,年终奖翻倍!
欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。
推荐:DTcode7的博客首页。
一个做过前端开发的产品经理,经历过睿智产品的折磨导致脱发之后,励志要翻身农奴把歌唱,一边打入敌人内部一边持续提升自己,为我们广大开发同胞谋福祉,坚决抵制睿智产品折磨我们码农兄弟!
| 专栏系列(点击解锁) | 学习路线(点击解锁) | 知识定位 |
|---|---|---|
| 《微信小程序相关博客》 | 持续更新中~ | 结合微信官方原生框架、uniapp等小程序框架,记录请求、封装、tabbar、UI组件的学习记录和使用技巧等 |
| 《AIGC相关博客》 | 持续更新中~ | AIGC、AI生产力工具的介绍,例如stable diffusion这种的AI绘画工具安装、使用、技巧等总结 |
| 《HTML网站开发相关》 | 《前端基础入门三大核心之html相关博客》 | 前端基础入门三大核心之html板块的内容,入坑前端或者辅助学习的必看知识 |
| 《前端基础入门三大核心之JS相关博客》 | 前端JS是JavaScript语言在网页开发中的应用,负责实现交互效果和动态内容。它与HTML和CSS并称前端三剑客,共同构建用户界面。 通过操作DOM元素、响应事件、发起网络请求等,JS使页面能够响应用户行为,实现数据动态展示和页面流畅跳转,是现代Web开发的核心 |
|
| 《前端基础入门三大核心之CSS相关博客》 | 介绍前端开发中遇到的CSS疑问和各种奇妙的CSS语法,同时收集精美的CSS效果代码,用来丰富你的web网页 | |
| 《canvas绘图相关博客》 | Canvas是HTML5中用于绘制图形的元素,通过JavaScript及其提供的绘图API,开发者可以在网页上绘制出各种复杂的图形、动画和图像效果。Canvas提供了高度的灵活性和控制力,使得前端绘图技术更加丰富和多样化 | |
| 《Vue实战相关博客》 | 持续更新中~ | 详细总结了常用UI库elementUI的使用技巧以及Vue的学习之旅 |
| 《python相关博客》 | 持续更新中~ | Python,简洁易学的编程语言,强大到足以应对各种应用场景,是编程新手的理想选择,也是专业人士的得力工具 |
| 《sql数据库相关博客》 | 持续更新中~ | SQL数据库:高效管理数据的利器,学会SQL,轻松驾驭结构化数据,解锁数据分析与挖掘的无限可能 |
| 《算法系列相关博客》 | 持续更新中~ | 算法与数据结构学习总结,通过JS来编写处理复杂有趣的算法问题,提升你的技术思维 |
| 《IT信息技术相关博客》 | 持续更新中~ | 作为信息化人员所需要掌握的底层技术,涉及软件开发、网络建设、系统维护等领域的知识 |
| 《信息化人员基础技能知识相关博客》 | 无论你是开发、产品、实施、经理,只要是从事信息化相关行业的人员,都应该掌握这些信息化的基础知识,可以不精通但是一定要了解,避免日常工作中贻笑大方 | |
| 《信息化技能面试宝典相关博客》 | 涉及信息化相关工作基础知识和面试技巧,提升自我能力与面试通过率,扩展知识面 | |
| 《前端开发习惯与小技巧相关博客》 | 持续更新中~ | 罗列常用的开发工具使用技巧,如 Vscode快捷键操作、Git、CMD、游览器控制台等 |
| 《photoshop相关博客》 | 持续更新中~ | 基础的PS学习记录,含括PPI与DPI、物理像素dp、逻辑像素dip、矢量图和位图以及帧动画等的学习总结 |
| 日常开发&办公&生产【实用工具】分享相关博客》 | 持续更新中~ | 分享介绍各种开发中、工作中、个人生产以及学习上的工具,丰富阅历,给大家提供处理事情的更多角度,学习了解更多的便利工具,如Fiddler抓包、办公快捷键、虚拟机VMware等工具 |
吾辈才疏学浅,摹写之作,恐有瑕疵。望诸君海涵赐教。望轻喷,嘤嘤嘤
非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。愿斯文对汝有所裨益,纵其简陋未及渊博,亦足以略尽绵薄之力。倘若尚存阙漏,敬请不吝斧正,俾便精进!

更多推荐
所有评论(0)