Next.js脚本优化 #

一、Script组件 #

1.1 基本用法 #

tsx
import Script from 'next/script'

export default function Page() {
    return (
        <>
            <Script src="https://example.com/script.js" />
            <div>页面内容</div>
        </>
    )
}

1.2 加载策略 #

策略 说明
beforeInteractive 页面交互前加载
afterInteractive 页面交互后加载
lazyOnload 浏览器空闲时加载
worker 在web worker中加载

二、加载策略详解 #

2.1 beforeInteractive #

tsx
import Script from 'next/script'

export default function Page() {
    return (
        <>
            <Script
                src="https://example.com/critical.js"
                strategy="beforeInteractive"
            />
            <div>页面内容</div>
        </>
    )
}

适用场景:

  • 关键脚本
  • 必须在页面渲染前执行

2.2 afterInteractive #

tsx
import Script from 'next/script'

export default function Page() {
    return (
        <>
            <Script
                src="https://example.com/analytics.js"
                strategy="afterInteractive"
            />
            <div>页面内容</div>
        </>
    )
}

适用场景:

  • 分析脚本
  • 非关键功能

2.3 lazyOnload #

tsx
import Script from 'next/script'

export default function Page() {
    return (
        <>
            <Script
                src="https://example.com/non-critical.js"
                strategy="lazyOnload"
            />
            <div>页面内容</div>
        </>
    )
}

适用场景:

  • 非必要脚本
  • 广告脚本
  • 社交媒体插件

三、脚本事件 #

3.1 onLoad #

tsx
import Script from 'next/script'
import { useState } from 'react'

export default function Page() {
    const [loaded, setLoaded] = useState(false)
    
    return (
        <>
            <Script
                src="https://example.com/script.js"
                onLoad={() => setLoaded(true)}
            />
            {loaded && <div>脚本已加载</div>}
        </>
    )
}

3.2 onReady #

tsx
import Script from 'next/script'

export default function Page() {
    return (
        <>
            <Script
                src="https://example.com/script.js"
                onReady={() => {
                    console.log('脚本已就绪')
                }}
            />
        </>
    )
}

3.3 onError #

tsx
import Script from 'next/script'

export default function Page() {
    return (
        <>
            <Script
                src="https://example.com/script.js"
                onError={(e) => {
                    console.error('脚本加载失败:', e)
                }}
            />
        </>
    )
}

四、常见第三方脚本 #

4.1 Google Analytics #

tsx
import Script from 'next/script'

export default function GoogleAnalytics() {
    return (
        <>
            <Script
                src="https://www.googletagmanager.com/gtag/js?id=GA_MEASUREMENT_ID"
                strategy="afterInteractive"
            />
            <Script id="google-analytics" strategy="afterInteractive">
                {`
                    window.dataLayer = window.dataLayer || [];
                    function gtag(){dataLayer.push(arguments);}
                    gtag('js', new Date());
                    gtag('config', 'GA_MEASUREMENT_ID');
                `}
            </Script>
        </>
    )
}

4.2 Google Tag Manager #

tsx
import Script from 'next/script'

export default function GoogleTagManager() {
    return (
        <>
            <Script
                id="gtm-script"
                strategy="afterInteractive"
            >
                {`
                    (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-XXXXXX');
                `}
            </Script>
        </>
    )
}

4.3 Facebook Pixel #

tsx
import Script from 'next/script'

export default function FacebookPixel() {
    return (
        <>
            <Script
                id="facebook-pixel"
                strategy="afterInteractive"
            >
                {`
                    !function(f,b,e,v,n,t,s)
                    {if(f.fbq)return;n=f.fbq=function(){n.callMethod?
                    n.callMethod.apply(n,arguments):n.queue.push(arguments)};
                    if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
                    n.queue=[];t=b.createElement(e);t.async=!0;
                    t.src=v;s=b.getElementsByTagName(e)[0];
                    s.parentNode.insertBefore(t,s)}(window, document,'script',
                    'https://connect.facebook.net/en_US/fbevents.js');
                    fbq('init', 'YOUR_PIXEL_ID');
                    fbq('track', 'PageView');
                `}
            </Script>
        </>
    )
}

4.4 Hotjar #

tsx
import Script from 'next/script'

export default function Hotjar() {
    return (
        <Script
            id="hotjar"
            strategy="afterInteractive"
        >
            {`
                (function(h,o,t,j,a,r){
                    h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};
                    h._hjSettings={hjid:YOUR_SITE_ID,hjsv:6};
                    a=o.getElementsByTagName('head')[0];
                    r=o.createElement('script');r.async=1;
                    r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;
                    a.appendChild(r);
                })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');
            `}
        </Script>
    )
}

五、内联脚本 #

5.1 使用id属性 #

tsx
import Script from 'next/script'

export default function Page() {
    return (
        <Script id="inline-script">
            {`
                console.log('内联脚本执行');
            `}
        </Script>
    )
}

5.2 动态脚本 #

tsx
import Script from 'next/script'

export default function Page({ analyticsId }: { analyticsId: string }) {
    return (
        <Script id="dynamic-script">
            {`
                window.analyticsId = "${analyticsId}";
                console.log(window.analyticsId);
            `}
        </Script>
    )
}

六、布局中使用 #

6.1 根布局 #

tsx
import Script from 'next/script'

export default function RootLayout({ children }: { children: React.ReactNode }) {
    return (
        <html lang="zh-CN">
            <head>
                <Script
                    src="https://example.com/analytics.js"
                    strategy="afterInteractive"
                />
            </head>
            <body>{children}</body>
        </html>
    )
}

6.2 特定页面 #

tsx
import Script from 'next/script'

export default function DashboardPage() {
    return (
        <>
            <Script
                src="https://example.com/dashboard-widget.js"
                strategy="lazyOnload"
            />
            <div>仪表盘内容</div>
        </>
    )
}

七、最佳实践 #

7.1 选择正确的策略 #

脚本类型 推荐策略
关键脚本 beforeInteractive
分析脚本 afterInteractive
广告脚本 lazyOnload

7.2 使用事件处理 #

tsx
import Script from 'next/script'

export default function Page() {
    return (
        <Script
            src="https://example.com/script.js"
            strategy="afterInteractive"
            onLoad={() => {
                initializeApp()
            }}
            onError={(e) => {
                console.error('Script failed:', e)
            }}
        />
    )
}

7.3 条件加载 #

tsx
import Script from 'next/script'

export default function Page() {
    const shouldLoadScript = process.env.NODE_ENV === 'production'
    
    return (
        <>
            {shouldLoadScript && (
                <Script
                    src="https://example.com/analytics.js"
                    strategy="afterInteractive"
                />
            )}
        </>
    )
}

八、总结 #

脚本优化要点:

要点 说明
Script组件 next/script
加载策略 strategy属性
事件处理 onLoad/onReady/onError
内联脚本 id属性
第三方脚本 按需加载

下一步,让我们学习懒加载!

最后更新:2026-03-28