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