Next.js中如何在状态变化时重新执行动态src的Script?
解决Next.js 13.2.3中Script组件随状态变化重新加载的问题
首先明确:beforeInteractive策略的脚本属于页面预加载资源,只会在页面初始化阶段执行一次,无法随状态变化重新加载。要实现动态切换脚本的需求,得换用运行时策略并配合手动管理逻辑,以下是两种可行方案:
方案1:用key属性触发Script组件重渲染
给Script组件绑定与动态URL关联的key值,当URL变化时,key改变会触发Next.js卸载旧脚本、加载新脚本。注意要把策略换成lazyOnload或afterInteractive这类运行时加载策略:
import { Script } from 'next/script'; function DynamicScript({ urlThatCanChange }) { return ( <Script src={`${urlThatCanChange}/library.js`} strategy="lazyOnload" key={urlThatCanChange} /> ); }
方案2:手动操作DOM控制脚本生命周期
如果需要更精细的副作用控制(比如清理旧脚本的全局变量、事件监听),可以直接通过DOM API创建和移除脚本:
'use client'; import { useEffect } from 'react'; function DynamicScript({ urlThatCanChange }) { useEffect(() => { // 移除已存在的同地址旧脚本 const oldScript = document.querySelector(`script[src="${urlThatCanChange}/library.js"]`); if (oldScript) { oldScript.remove(); // 按需清理脚本副作用,比如:window.libraryInstance = null; } // 创建新脚本元素 const newScript = document.createElement('script'); newScript.src = `${urlThatCanChange}/library.js`; newScript.async = true; // 可选:监听脚本加载完成事件,执行初始化逻辑 newScript.onload = () => { console.log('新脚本加载完成,可执行初始化'); }; document.body.appendChild(newScript); // 组件卸载或URL变化时清理脚本 return () => { newScript.remove(); // 再次清理副作用 }; }, [urlThatCanChange]); return null; }
关键注意点
- 必须放弃
beforeInteractive策略:该策略的脚本在预渲染阶段就已注入,不支持动态更新。 - 清理副作用:切换脚本时一定要清理旧脚本留下的全局变量、事件监听等,避免内存泄漏或逻辑冲突。
- 客户端组件限制:Next.js 13中,这类动态DOM操作逻辑必须放在标记了
'use client'的客户端组件中。
内容的提问来源于stack exchange,提问作者5tormTrooper
相关产品推荐
相关产品推荐

