我正在试用Next.js13的新experimental appDir
,我遇到了一个小问题。
本项目基于:
- 下一步. js 13
- React18
- MUI 5(样式化构件,使用
@mui/system @emotion/react @emotion/styled
)
为了让MUI/Emotion在服务器端渲染中表现良好,有一个处理SSR缓存的开放票证,这意味着我必须将layout.tsx
转换为一个仅面向客户端的组件,这意味着像<head>
这样的组件现在只能在服务器端渲染。
为了解决这个问题,我将布局拆分为带有客户端leaf的服务器组件。
但无论我做什么,当我在Vercel上部署时,我都无法让<title>
或任何<meta>
标记出现在服务器源代码的<head>
中。
下面是我所做的工作的摘要。(注:在next.config.js
中需要experimental: { appDir: true }
)。
// app/head.tsx
export default function Head() {
return (
<>
<title>My App</title>
</>
)
}
// app/layout.tsx
import { SSRThemeProvider } from "lib/SSR/theme";
import React from "react";
import theme from "styles/appTheme";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<React.StrictMode>
<html lang="en" key="root">
<head />
</html>
{/* ^ duplicate html/head outside of client-only provider */}
<SSRThemeProvider theme={theme} key="theme-provider">
<html lang="en" key="root">
{/*
<head /> will contain the components returned by the nearest parent
head.tsx. Find out more at https://beta.nextjs.org/docs/api-reference/file-conventions/head
*/}
<head />
<body>{children}</body>
</html>
</SSRThemeProvider>
</React.StrictMode>
);
}
// app/home.tsx
import { HomePage } from "content/home";
import { getPlaceholderImages } from "lib/SSR/placeholderImages";
export default async function HybridHome() {
const images = await getPlaceholderImages();
// ^ server-side stuff with sharp
return <HomePage placeholderImages={images} />;
}
"use client";
// ^ client only directive
// lib/SSR/theme.provider.tsx
import { ThemeProvider } from "@mui/material";
import { DefaultTheme, ThemeProviderProps } from "@mui/styles";
import React from "react";
export const SSRThemeProvider = <T = DefaultTheme,>(
props: ThemeProviderProps<T>
): React.ReactElement<ThemeProviderProps<T>> => {
return (
<React.StrictMode>
<ThemeProvider {...props} />
</React.StrictMode>
);
};
"use client";
// ^ client only here too
// content/home.tsx
import { CssBaseline } from "@mui/material";
import RootStyleRegistry from "lib/SSR/emotion";
import { usePathname, useSearchParams } from "next/navigation";
export const HomePage = () => {
const pathname = usePathname();
const searchParams = useSearchParams();
return (
<>
<CssBaseline key="css-baseline" />
<RootStyleRegistry>
<main>
{/* Words go here /*}
</main>
</RootStyleRegistry>
</>
);
};
2条答案
按热度按时间zsohkypk1#
head.tsx
组件应该返回一个片段,而不是head
。试试这个
其次,你不需要在任何地方导入这个组件,它会自动添加到相应页面和子页面的head部分。
31moq8wy2#
啊,原来这是
useQueryParams
中每个https://github.com/vercel/next.js/issues/44868的一个实际错误。我暂时用一个定制的钩子替换了它,现在我所有的标记都显示出来了,即使我使用@MayankKumar的建议,直接使用
<head />
而不使用其他组件。这是我的钩子,而门票仍然开放: