在 Next.js 中,next/script 是框架封装的优化版脚本加载组件,相比原生 <script> 标签,核心优势是 支持高级加载策略、自动优化性能、适配 Next.js 渲染逻辑,尤其适合生产环境和复杂脚本场景。下面从「核心区别、用法对比、适用场景」三方面详细拆解:
一、核心区别(表格总结)
| 对比维度 | 原生 <script> 标签 |
Next.js next/script 组件 |
|---|---|---|
| 加载策略 | 仅支持 async/defer 基础属性,无细粒度控制 |
支持 strategy 配置(beforeInteractive/afterInteractive/lazyOnload/worker),精准控制加载时机 |
| 渲染适配 | 客户端渲染(CSR)中正常工作,但 SSR/SSG 时可能导致 hydration 不匹配 | 自动适配 SSR/SSG/ISR 渲染模式,避免 hydration 错误,脚本执行时机与渲染流程对齐 |
| 性能优化 | 无内置优化,需手动处理脚本加载阻塞、重复加载问题 | 自动去重(同一脚本不重复加载)、支持预加载、部分策略下脚本加载不阻塞页面渲染 |
| 脚本位置 | 需手动指定 head/body 位置(如 next/head 中) |
无需手动指定位置,框架根据 strategy 自动插入最优位置(如 beforeInteractive 插入 <head>) |
| 动态脚本(如 CDN 链接) | 直接写链接,但 SSR 时可能因跨域/时机问题失效 | 支持动态链接(如环境变量拼接),且框架会处理跨域脚本的加载兼容性 |
| 事件监听 | 需手动绑定 onload/onerror 事件 |
内置 onLoad/onError 回调 props,使用更便捷 |
| Worker 脚本支持 | 需手动创建 Worker 实例,配置复杂 |
支持 strategy="worker",一键将脚本放入 Web Worker 执行,避免阻塞主线程 |
二、用法对比(代码示例)
1. 加载第三方 CDN 脚本(如 jQuery、PayPal SDK)
原生 <script> 标签(Next.js 中使用)
jsx
// 需手动导入 next/head,且只能用 async/defer 控制加载
import Head from 'next/head';
export default function Page() {
return (
<>
<Head>
{/* 只能选择 async 或 defer,无法控制脚本在页面交互前/后执行 */}
<script
src="https://cdn.jsdelivr.net/npm/jquery@3.6.4/dist/jquery.min.js"
async
onLoad={() => console.log('jQuery 加载完成')}
/>
</Head>
</>
);
}
Next.js next/script 组件
jsx
// 导入组件即可,无需手动指定 head/body 位置
import Script from 'next/script';
export default function Page() {
return (
<>
<Script
src="https://cdn.jsdelivr.net/npm/jquery@3.6.4/dist/jquery.min.js"
// 配置加载策略:页面交互后加载(不阻塞首屏)
strategy="afterInteractive"
// 内置回调,无需手动绑定
onLoad={() => console.log('jQuery 加载完成')}
onError={(err) => console.log('加载失败', err)}
/>
</>
);
}
2. 加载本地脚本(如 public/js/custom.js)
原生 <script> 标签
jsx
// 需拼接 public 路径,且 SSR 时可能执行时机错乱
import Head from 'next/head';
export default function Page() {
return (
<>
<Head>
<script src="/js/custom.js" defer />
</Head>
</>
);
}
Next.js next/script 组件(支持策略+自动路径处理)
jsx
import Script from 'next/script';
export default function Page() {
return (
<>
{/* 无需拼接 public 路径,直接写相对路径 */}
<Script
src="/js/custom.js"
// 关键脚本:页面交互前加载(如初始化全局状态的脚本)
strategy="beforeInteractive"
/>
</>
);
}
3. 特殊场景:Web Worker 脚本(避免阻塞主线程)
原生 <script> 标签(复杂)
jsx
export default function Page() {
useEffect(() => {
// 手动创建 Worker,需处理路径、兼容性、销毁等问题
const worker = new Worker('/js/heavy-task.js');
worker.postMessage({ data: '任务数据' });
worker.onmessage = (e) => console.log('Worker 结果', e.data);
return () => worker.terminate(); // 手动销毁
}, []);
return <div>原生 Worker 示例</div>;
}
Next.js next/script 组件(一键实现)
jsx
import Script from 'next/script';
export default function Page() {
return (
<>
{/* strategy="worker" 自动将脚本放入 Worker 执行,无需手动处理 */}
<Script
src="/js/heavy-task.js"
strategy="worker"
onLoad={() => console.log('Worker 脚本加载完成')}
/>
</>
);
}
三、next/script 核心优势详解
1. 四大加载策略,精准控制执行时机(最核心优势)
strategy 属性是 next/script 的灵魂,解决了原生脚本加载时机难以控制的问题:
beforeInteractive:仅支持 SSR/SSG,脚本在页面「可交互前」加载(如next/head中),适合关键脚本(如初始化全局配置、监控脚本);afterInteractive:默认值,脚本在页面「可交互后」加载(类似defer但优化更好),不阻塞首屏渲染,适合非关键第三方脚本(如统计、广告);lazyOnload:脚本在页面「完全加载+空闲时」加载(类似requestIdleCallback),适合非紧急脚本(如隐藏组件的脚本、辅助功能);worker:脚本在 Web Worker 中执行,不占用主线程,适合耗时操作(如数据处理、复杂计算)。
2. 自动适配 Next.js 渲染模式,避免 hydration 错误
Next.js 是 SSR/SSG 框架,原生 <script> 可能在服务端渲染时被插入,但客户端 hydration 时重复执行,导致状态错乱。next/script 会自动处理:
- SSR 时:脚本仅在客户端执行,避免服务端渲染时的跨域/环境问题;
- Hydration 时:确保脚本执行时机与客户端渲染对齐,不会出现「脚本已执行但 DOM 未挂载」的错误。
3. 性能优化:去重+预加载
- 自动去重:同一
src或id的脚本不会重复加载,避免原生脚本因组件复用导致的重复执行问题; - 预加载优化:框架会根据加载策略自动预加载脚本(如
beforeInteractive脚本会被优先预加载),提升加载速度; - 无阻塞渲染:除
beforeInteractive外,其他策略的脚本加载均不阻塞页面渲染,优化首屏加载时间(LCP)。
4. 更便捷的事件处理与配置
- 内置
onLoad/onError回调,无需手动绑定addEventListener; - 支持
id/nonce/integrity等安全属性,满足生产环境安全要求; - 支持动态
src(如通过环境变量拼接 CDN 链接),适配多环境部署:jsx<Script src={`${process.env.NEXT_PUBLIC_CDN_URL}/js/custom.js`} />
四、适用场景与注意事项
什么时候用 next/script?
- 生产环境项目(需要性能优化、渲染适配);
- 加载第三方脚本(如统计、支付、广告 SDK);
- 需要控制加载时机的脚本(如关键脚本、非紧急脚本);
- 需使用 Web Worker 的耗时脚本;
- SSR/SSG/ISR 渲染模式的页面(避免 hydration 错误)。
什么时候用原生 <script>?
- 简单静态页面(无需优化,快速开发);
- 客户端渲染(CSR)的简单组件(无 SSR 需求);
- 需自定义复杂加载逻辑(如动态插入脚本且无需 Next.js 优化)。
注意事项
strategy="beforeInteractive"仅支持放在pages/_document.js或根布局(App Router)中,不能放在普通页面/组件;- 本地脚本需放在
public文件夹下,src路径直接写/文件名(无需public/前缀); - 第三方脚本需确保支持跨域(大部分 CDN 脚本都支持),否则可能加载失败;
- 生产环境建议给脚本添加
integrity属性(校验脚本完整性,防止篡改):jsx<Script src="https://cdn.jsdelivr.net/npm/jquery@3.6.4/dist/jquery.min.js" integrity="sha256-oP6HI9z1XaZNBrJURtCoUT5SUnxFr8s3BzRl+cbzUq8=" crossOrigin="anonymous" />
总结
next/script 是 Next.js 为脚本加载量身打造的优化方案,核心优势是「加载策略可控、渲染适配、性能优化」,完全覆盖原生 <script> 的功能且解决了其在 Next.js 中的痛点。生产环境优先使用 next/script,尤其对于 SSR/SSG 项目和需要优化性能的场景;简单场景或临时调试时,原生 <script> 也可满足需求。