为什么优化了代码后Lighthouse的TTI指标还是卡在11秒以上?
我在优化一个单页应用时,Lighthouse的TTI一直显示11秒多,明明把JS拆分成了动态导入,还压缩了图片。但测试报告里显示”largest-contentful-paint”还是在首屏阻塞渲染,main.js文件虽然只有200kb,但评分就是提不上去。尝试过用预加载关键资源,但开发者工具网络面板还是显示…
代码结构大概是这样的:
<html>
<head>
<link href="/styles.css" rel="external nofollow" rel="stylesheet">
<script src="/main.js" defer></script>
</head>
<body>
<div id="app"></div>
<script type="module">
import('./lazy-module.js')
</script>
</body>
</html>
这样写有问题吗?为什么首屏加载时间还是卡在TTI指标上?
看你的代码,
div id="app"是空的,LCP 要等 main.js 执行完才能渲染内容。200KB 的 JS 在低端设备上跑个几秒很正常,TTI 11秒基本就是 JS 初始化时间。几个关键问题:
1. CSS阻塞没解决
styles.css 放在 head 里但没有 preload,浏览器必须等 CSS 下载完才能开始渲染。建议改成:
或者直接内联关键CSS,把首屏必须的样式放在
标签里。2. main.js 太重了
200KB 就算压缩过,执行时间也短不了。你需要把首屏初始化代码拆出来,剩下的再动态加载。可以这样:
main-core.js 只包含首屏渲染必须的逻辑,其他功能用动态 import。
3. 动态导入写错位置了
你的
import('./lazy-module.js')放在 body 末尾的内联 script 里,会在 HTML 解析完立即执行。应该改成显式的点击事件触发或者 IntersectionObserver 触发:4. 没骨架屏
首屏是空的,JS 没跑完就是白屏。简单加个骨架屏:
先把这几个改了,TTI 应该能降到3-5秒左右。11秒太夸张了,多半是 main.js 里有同步的大计算或者第三方库没做tree-shaking。
main.js虽然是defer加载,但它可能还是太大了,即使压缩到200kb,解析和执行的时间也会拖慢TTI。优化建议如下:
先把关键CSS内联到HTML里,减少外链CSS的请求时间。像你这种单页应用,首屏样式其实不需要太多,直接写在head里就行:
然后,
main.js虽然用了defer,但200kb对首屏来说还是太重了。你可以试试把首屏初始化逻辑单独拆出来,用一个小的bootstrap.js来处理首屏渲染,剩下的逻辑再动态加载:另外,动态导入的
lazy-module.js最好也加上预加载,避免它成为瓶颈:最后,确保服务器启用了Gzip或Brotli压缩,特别是对JS和CSS文件。如果服务器没配置好,文件传输时间会很长。
按照上面这些改完后,重新跑一下Lighthouse,TTI应该能降到6秒以内。如果还不行,可能是第三方库或者图片资源的问题,可以用开发者工具的Performance面板具体分析一下主线程的耗时分布,找到真正的瓶颈。
复制这些改法,基本能解决问题。