Next.js正确导入本地脚本的方法及加载报错解决方案
问题根因
两种写法加载失败,核心是三个典型错误:
- 错误使用
import()动态导入public目录静态资源:import()是打包工具处理模块化代码的专用API,public目录下的文件不会走打包解析流程,仅作为静态资源对外提供访问,不能通过模块导入方式引用。 - 静态资源路径缺少根前缀:Next.js中public目录下的资源引用时必须以
/开头标识根路径,之前写的lib/js/xxx属于相对路径,遇到嵌套路由场景会直接拼接错误路径返回404。 - Script组件使用位置错误:Next.js官方明确要求
next/script组件不能放在_document.js的<Head>标签内,该位置的脚本不会被正常注入加载。
正确实现方案
方案1:全局加载(适配整站使用Bootstrap模板的场景)
直接修改pages/_app.js,删掉原来useEffect里的动态导入逻辑,用Next.js官方的next/script组件加载脚本,路径统一加/前缀,严格按照依赖顺序放置脚本(jQuery最先加载,依赖jQuery的插件其次,自定义业务逻辑最后加载):
import Head from 'next/head'; import Script from 'next/script'; import '../styles/globals.css'; llo function MyApp({ Component, pageProps }) { return ( <> <Head> <meta charSet="UTF-8"/> <meta name="keywords" content="Ogani, unica, creative, html"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta httpEquiv="X-UA-Compatible" content="ie=edge"/> {/* 字体引入 */} <link href="https://fonts.googleapis.com/css2?family=Cairo:wght@200;300;400;600;900&display=swap" rel="stylesheet"/> {/* CSS引入,路径补/前缀避免嵌套路由404 */} <link rel="stylesheet" href="/lib/css/bootstrap.min.css" type="text/css"/> <link rel="stylesheet" href="/lib/css/font-awesome.min.css" type="text/css"/> <link rel="stylesheet" href="/lib/css/elegant-icons.css" type="text/css"/> <link rel="stylesheet" href="/lib/css/nice-select.css" type="text/css"/> <link rel="stylesheet" href="/lib/css/jquery-ui.min.css" type="text/css"/> <link rel="stylesheet" href="/lib/css/owl.carousel.min.css" type="text/css"/> <link rel="stylesheet" href="/lib/css/slicknav.min.css" type="text/css"/> <link rel="stylesheet" href="/lib/css/style.css" type="text/css"/> </Head> {/* 按依赖顺序加载JS,路径均以/开头对应public目录下文件 */} <Script src="/lib/js/jquery-3.3.1.min.js" strategy="beforeInteractive"/> <Script src="/lib/js/jquery.nice-select.min.js" strategy="beforeInteractive"/> <Script src="/lib/js/jquery-ui.min.js" strategy="beforeInteractive"/> <Script src="/lib/js/jquery.slicknav.js" strategy="beforeInteractive"/> <Script src="/lib/js/mixitup.min.js" strategy="beforeInteractive"/> <Script src="/lib/js/owl.carousel.min.js" strategy="beforeInteractive"/> <Script src="/lib/js/bootstrap.min.js" strategy="beforeInteractive"/> {/* 依赖其他库的自定义逻辑最后加载 */} <Script src="/lib/js/main.js" strategy="afterInteractive"/> <Component {...pageProps} /> </> ); } export default MyApp;
配套修改
pages/_document.js,移除所有自定义Script标签,仅保留默认结构即可,参考代码如下:import { Html, Head, Main, NextScript } from 'next/document' export default function Document() { return ( <Html lang="zh-CN"> <Head /> <body> <Main /> <NextScript /> </body> </Html> ) }
方案2:单页面加载(仅个别页面需要模板效果时使用)
如果只有首页等个别页面用到这套模板的JS交互,不需要全局加载,直接把上述Script组件放到对应页面文件的顶层即可,不用写入_app.js,路径和加载顺序规则和全局加载一致。
额外注意事项
- 所有public目录下的静态资源(图片、CSS、JS),引用时路径必须以
/开头,代表从站点根路径的public目录取资源,禁止写相对路径。 - 不要用
import()导入public下的传统jQuery插件,这类文件不符合ES模块规范,打包工具无法解析,会直接报模块不存在的错误。 - 如果开发时仍报404,直接核对public目录下的文件路径与src属性值是否完全一致,注意文件名大小写,Linux部署环境下文件名大小写敏感。
- 若出现
$ is not defined报错,调整脚本加载顺序,确保jQuery在所有依赖它的插件之前加载。
内容的提问来源于stack exchange,提问作者Sami Ullah
相关产品推荐
相关产品推荐

