为什么我的页面TTI指标一直卡在8秒以上?优化后没明显改善
最近在优化一个电商详情页,Lighthouse评分里的TTI指标总是在8秒左右,用户反馈页面加载卡顿。页面用了Vue组件,图片都加了懒加载,还把CSS抽离成单独文件了,但测试结果还是差。折腾了半天,发现可能是某个组件的初始化代码拖慢了?
比如这个商品轮播图组件,代码逻辑看起来不复杂,但每次加载时控制台都会显示长时间任务:
<template>
<div ref="carousel" class="carousel">
<img
v-for="(src, index) in images"
:key="index"
:data-src="src"
@load="handleImageLoad"
class="lazy-img">
</div>
</template>
<script>
export default {
mounted() {
// 手动实现Intersection Observer懒加载
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
}, { rootMargin: '0px 0px 200px 0px' });
this.$refs.carousel.querySelectorAll('.lazy-img').forEach(img => {
observer.observe(img);
});
}
}
</script>
已经尝试过把图片尺寸压缩到200kb以内,合并JS打包,甚至把第三方统计脚本移到底部,但TTI还是没降到5秒以下。是不是懒加载实现有问题?或者有其他隐藏的性能瓶颈没发现?
第一,图片没设宽高,加载完会触发重排,轮播图里一堆图片重排能把主线程卡死。给图片加固定的width和height,或者用aspect-ratio撑开容器。
第二,
handleImageLoad里是不是写了什么计算逻辑?比如重新计算轮播图尺寸或者触发Vue响应式更新?这种在图片onload里搞事情最容易产生长任务。第三,Vue组件初始化本身就有开销,如果轮播图组件不是首屏必须的,直接异步加载它:
第四,最容易被忽略的,你的第三方统计脚本是不是在head里?用
defer或async加载,或者干脆等用户交互后再动态插入。你先用Chrome DevTools的Performance面板跑一次,看看到底哪个函数执行时间最长,别瞎猜。八成是某个统计SDK或者广告脚本在搞鬼。
mounted钩子里干了太多事,Intersection Observer虽然高效,但每次初始化都会消耗时间。我一般直接用原生图片懒加载,浏览器自带的就挺好:这样省掉一大坨JS开销,TTI能降不少。另外检查下Vuex或生命周期里有没有阻塞主线程的任务,
console.time()帮你定位耗时代码。