NextJS页面切换后自定义JS失效问题求助
Hey there! I totally get where you're coming from—first time working with Next.js can throw some curveballs, especially with how it handles client-side navigation vs. server-side rendering. Let's break down why this is happening and how to fix it.
Why This Happens
The core issue is that _document.js only runs once on the server when your initial page loads. Next.js uses client-side routing for page switches (no full browser reload), so any scripts you added in _document.js won't re-execute for subsequent pages. Those scripts only fire when the browser first receives the server-rendered HTML.
Solutions
Here are the most straightforward fixes tailored for your first Next.js project:
1. Move Your Script Logic to _app.js
_app.js is Next.js's top-level component that wraps all your pages, and it runs both on the server and client. Crucially, it can react to page navigation events, making it perfect for scripts that need to run on every page load.
Option A: Use useEffect with Router Events
If you have custom JS functions that need to run on every page switch, hook into Next.js's router events:
// pages/_app.js import { useEffect } from 'react'; import { useRouter } from 'next/router'; import '../styles/globals.css'; function MyApp({ Component, pageProps }) { const router = useRouter(); useEffect(() => { // Define your custom script logic here const initCustomScript = () => { // Example: Initialize a third-party widget, add event listeners, etc. console.log('Running custom script for current page'); }; // Run on initial page load initCustomScript(); // Re-run every time navigation completes const handleRouteChange = () => initCustomScript(); router.events.on('routeChangeComplete', handleRouteChange); // Cleanup event listener when component unmounts return () => { router.events.off('routeChangeComplete', handleRouteChange); }; }, [router]); return <Component {...pageProps} />; } export default MyApp;
Option B: Use Next.js's Script Component (Next.js 11+)
If you're loading an external JS file, use the built-in next/script component—it handles proper loading for client-side navigation automatically:
// pages/_app.js import Script from 'next/script'; import '../styles/globals.css'; function MyApp({ Component, pageProps }) { return ( <> <Script src="/path/to/your/custom-script.js" strategy="afterInteractive" // Loads after page is interactive onLoad={() => { // Run initialization code once the script loads window.initCustomScript(); // If your script exposes a global function }} /> <Component {...pageProps} /> </> ); } export default MyApp;
2. Add Scripts to Specific Page Components
If your custom JS only applies to certain pages, skip _app.js and add the useEffect or Script component directly to those page files. This keeps your code focused and avoids unnecessary script runs on unrelated pages.
3. Reserve _document.js for Server-Only Scripts
Going forward, remember that _document.js is designed for modifying the server-rendered HTML structure (like adding global meta tags, fonts, or scripts that only need to run once on the initial page load). Client-side interactive scripts that need to re-run on navigation don't belong here.
Since this is your first Next.js project, starting with the _app.js approach is the most idiomatic and simple fix. If you hit snags with specific code snippets, feel free to share them and we can dive deeper!
内容的提问来源于stack exchange,提问作者nicer00ster

