NextJS 13.3中GTM代码导致PageInsights总阻塞时间升高求助
解决NextJS 13.3中GTM导致Total Blocking Time上升的问题
核心原因分析
虽然你用了afterInteractive策略加载GTM脚本,但TBT上升通常不是GTM初始化脚本本身的问题,而是GTM容器内加载的第三方标签(如分析工具、广告脚本)同步执行阻塞了主线程,或者afterInteractive的加载时机仍处于页面关键渲染阶段之后但主线程尚未完全空闲的时段。
具体优化方案
1. 切换到lazyOnload加载策略
将Script组件的strategy改为lazyOnload,这个策略会在浏览器完全空闲时才加载脚本,完全避开页面初始化和交互初期的主线程繁忙时段,最大程度减少对TBT的影响:
<Script id="gtm-script" strategy="lazyOnload" // 替换原afterInteractive dangerouslySetInnerHTML={{ __html: ` (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer', '${GTM_ID}'); `, }} />
2. 优化GTM容器内的标签配置
- 强制异步加载所有第三方脚本:在GTM中配置标签时,确保所有通过GTM加载的外部脚本都启用异步属性(比如Google Analytics的标签默认是异步,但部分广告或自定义脚本可能不是)。
- 延迟非关键标签:对于非核心的标签(如广告、次级分析工具),在GTM中设置触发条件为“页面加载完成后延迟2-5秒”,或者绑定到用户首次交互事件(如滚动、点击)再触发,避免在页面初期抢占主线程。
- 移除冗余标签:清理GTM容器中未使用的标签、触发器和变量,减少不必要的脚本加载。
3. 调整页面视图触发时机
当前的useEffect会在pathname或searchParams变化时立即触发pageview,如果GTM尚未完全加载,可能会导致额外的主线程工作。可以添加GTM加载完成的判断:
useEffect(() => { // 确保dataLayer和GTM已初始化 if (pathname && window.dataLayer) { pageview(pathname) } }, [pathname, searchParams])
同时,确保pageview函数是向dataLayer推送事件,而不是直接执行同步代码:
// @/lib/gtm.ts中的pageview实现示例 export const pageview = (url: string) => { window.dataLayer?.push({ event: 'pageview', page: url, }) }
4. 确认App Router下的组件放置位置
如果你使用的是NextJS 13.3的App Router,建议将Analytics组件放在根layout.tsx中(App Router中_app.tsx已被layout替代),确保脚本只加载一次,避免重复初始化:
// app/layout.tsx import Analytics from '@/components/Analytics' export default function RootLayout({ children, }: { children: React.ReactNode }) { return ( <html lang="en"> <body> {children} <Analytics /> </body> </html> ) }
验证优化效果
修改后,重新运行PageSpeed Insights测试,重点关注:
- GTM脚本的加载时机是否在浏览器空闲时段
- 主线程阻塞的任务中是否还包含GTM或其加载的第三方脚本
- TBT指标是否有明显下降
内容的提问来源于stack exchange,提问作者Angrej Kumar
相关产品推荐
相关产品推荐

