Next.js 13 与 Ant Design 5:组件和页面在样式加载之前渲染,导致跳​​转

Fat*_*ani 4 configuration reactjs antd next.js13

我按照 antd 和 nextjs 文档来配置项目。

将此代码添加到./scripts/genAntdCss.tsx文件中:

import { extractStyle } from '@ant-design/static-style-extract';
import fs from 'fs';
const outputPath = './public/antd.min.css';
const css = extractStyle();
fs.writeFileSync(outputPath, css);
Run Code Online (Sandbox Code Playgroud)

这是 App.tsx 文件:

import { StyleProvider } from '@ant-design/cssinjs';
import type { AppProps } from 'next/app';
import '../public/antd.min.css';

export default function App({ Component, pageProps }: AppProps) {
  return (
    <StyleProvider hashPriority='high'>
      <Component {...pageProps} />
    </StyleProvider>
  );
}
Run Code Online (Sandbox Code Playgroud)

这些命令添加到package.json文件中:

"predev": "ts-node --project ./tsconfig.node.json ./scripts/genAntdCss.tsx",
"prebuild": "ts-node --project ./tsconfig.node.json ./scripts/genAntdCss.tsx"
Run Code Online (Sandbox Code Playgroud)

你有什么想法来解决这个问题吗?

Che*_*mah 15

我找到了解决这个问题的方法,但我必须使用 NextJS 13 的新“应用程序”、“布局”和“使用客户端”功能。

好吧,我找到了下面的链接,chunsch 在 NextJS 存储库中添加了一个示例: https: //github.com/vercel/next.js/pull/44015/files

另外,@kiner-tang 帮助我们修复了加载时的布局偏移 https://github.com/ant-design/ant-design/issues/42275#issuecomment-1555805914

这是可能的,但我们需要使用新的cssinjsAntD 5 功能以及 NextJS 13 应用程序和布局功能做一些奇怪的事情。我想避免使用它,但这是我发现的方式。对不起。

我基本上必须使用新的“app”目录(尚未实验功能),创建根布局(布局也是新功能之一),并创建一个 RootStyleRegistry 组件,指定它应该是带有“use client”的客户端组件'指令。此外,如果您使用该Layout组件,则应该指定hasSider={true}prop 以避免在第一次渲染中出现移位效果。

如果没有安装@ant-design/cssinjs,请安装它

  1. 创建RootStyleRegistry组件

    // located at src/modules/shared/components/root-style-registry/index.tsx in my case
    
    'use client'
    import { useState, type PropsWithChildren } from 'react'
    import { useServerInsertedHTML } from 'next/navigation'
    import { createCache, extractStyle, StyleProvider } from '@ant-design/cssinjs'
    
    export const RootStyleRegistry = ({ children }: PropsWithChildren) => {
      const [cache] = useState(() => createCache())
    
      useServerInsertedHTML(() => {
        return (
          <script
             dangerouslySetInnerHTML={{
              __html: `</script>${extractStyle(cache)}<script>`,
            }}
          />
        )
       })
    
       return <StyleProvider cache={cache}>{children}</StyleProvider>
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 创建根页面的布局

    // src/app/layout.tsx
    import type { PropsWithChildren } from 'react'
    import { RootStyleRegistry } from '../modules/shared/components/root-style-registry'
    
    export default function RootLayout({ children }: PropsWithChildren) {
      return (
        <html lang="es">
          <head />
          <body>
            <RootStyleRegistry>{children}</RootStyleRegistry>
          </body>
        </html>
      )
    };
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用“use client”指令创建页面组件。请记住,您现在必须将其命名为“页面”(就像文件夹内的索引文件一样)

    // src/app/page.tsx
    
    'use client'
    import React, { Button, Card, Space, Typography } from 'antd'
    
    export default function Home() {
      return  <Button type="primary">Ant Design Button</Button>
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 如果您使用该Layout组件并且在加载时尝试导航栏移动,则应该显式指定 'hasSider' 属性

    // src/app/components/layout.tsx
    
    export function MyLayout({ children }) {
      return (
        <Layout hasSider>
          <Sider>
            {children}
          </Sider>
        </Layout>
      )
    }
    
    Run Code Online (Sandbox Code Playgroud)

我也在这里回答: https: //github.com/ant-design/ant-design/issues/38555#issuecomment-1535788843