NextJS子布局被父布局覆盖,访问/admin/login时HTML匹配报错求助
Next.js 服务端HTML匹配错误问题解决
项目结构
├── app │ ├── admin │ │ ├── login │ │ │ ├── layout.js │ │ │ └── page.js │ │ ├── users │ │ │ └── page.js │ │ ├── layout.js │ │ └── page.js │ ├── layout.js │ └── page.js
问题现象
访问localhost:3000/admin/login时,出现错误提示:"Expected server HTML to contain a matching in "。移除login目录下的layout.js后,错误消失;修改admin目录下的layout.js时,/admin/login页面也会同步显示修改内容。
相关代码
/admin/login/page.js
export default function Page() { return ( <h1>Hello Login</h1> ); }
/admin/login/layout.js
import { Inter } from "next/font/google"; const inter = Inter({ subsets: ["latin"] }); export const metadata = { title: "Create Next App", description: "Generated by create next app", }; export default function LoginLayout({ children }) { return ( <html lang="en"> <body className={inter.className}>{children}</body> </html> ); }
注:admin目录下的layout.js和page.js代码与上述login目录的代码一致
问题原因
在Next.js的App Router路由体系中,layout是嵌套继承的:app/layout.js → admin/layout.js → login/layout.js。你在login/layout.js和admin/layout.js中都返回了<html>和<body>标签,这会导致服务端渲染时生成重复的根标签结构,客户端水合过程中无法匹配服务端输出的HTML,从而触发错误。
解决方案
只保留最顶层的app/layout.js返回<html>和<body>,下层的admin/layout.js和login/layout.js仅返回包裹内容的容器即可,不需要重复根标签。
修改后的/admin/login/layout.js示例:
import { Inter } from "next/font/google"; const inter = Inter({ subsets: ["latin"] }); export const metadata = { title: "Create Next App", description: "Generated by create next app", }; export default function LoginLayout({ children }) { return ( <div className={inter.className}>{children}</div> ); }
同样,admin/layout.js也需要做类似修改,移除<html>和<body>标签,改用普通容器包裹children。
内容的提问来源于stack exchange,提问作者Carl Ortiz
相关产品推荐
相关产品推荐

