【问题标题】:Why is my HTML source code not rendering properly with getStaticProps and getServerSideProps?为什么我的 HTML 源代码无法使用 getStaticProps 和 getServerSideProps 正确呈现?
【发布时间】:2022-10-25 23:13:52
【问题描述】:

getStaticProps 或 getServerSideProps 页面的 html 源未正确呈现。 我对元素和主要内容(h1、p 等....)一无所知。

示例:https://www.acaciapp.com/action/environnement/ne-pas-acheter-bouteilles-plastique/3TY0UDde3V5VZt00RB7X

=> 如果你“检查”:一切正常 => 如果您查看 source code of the page :几乎没有(只有在 getStaticProps 中获取的数据

这是 SEO 的一个主要问题(没有元标记,没有结构化的 html)。 相反,它在静态页面上运行良好(参见示例 https://www.acaciapp.com/

这是我的 __app

import '../styles/globals.css'
import * as React from 'react';
import PropTypes from 'prop-types';
import Head from 'next/head';
import { ThemeProvider, StyledEngineProvider } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import { CacheProvider } from '@emotion/react';
import theme from '../utility/theme';
import createEmotionCache from '../utility/createEmotionCache';
import { AuthProvider } from '../utility/context/authContext';
import { ActionProvider } from '../utility/context/actionContext';
import { ObjectiveProvider } from '../utility/context/objectiveContext';
import { PointsProvider } from '../utility/context/pointsContext';
import { PercentProvider } from '../utility/context/percentContext';



// Client-side cache, shared for the whole session of the user in the browser.
const clientSideEmotionCache = createEmotionCache();

export default function MyApp(props) {
  const { Component, emotionCache = clientSideEmotionCache, pageProps } = props;

  return (
    <CacheProvider value={emotionCache}>
      <Head>
        <title key="title">acacia.</title>
      </Head>
      <StyledEngineProvider injectFirst>
        <ThemeProvider theme={theme}>
          <AuthProvider>
            <ActionProvider>
              <ObjectiveProvider>
                <PointsProvider>
                  {/* <PercentProvider> */}
                    {/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
                    <CssBaseline />
                    <Component {...pageProps} />
                  {/* </PercentProvider> */}
                </PointsProvider>
              </ObjectiveProvider>
            </ActionProvider>
          </AuthProvider>
        </ThemeProvider>
      </StyledEngineProvider>
        
    </CacheProvider>
  );
}

MyApp.propTypes = {
  Component: PropTypes.elementType.isRequired,
  emotionCache: PropTypes.object,
  pageProps: PropTypes.object.isRequired,
}

和我的 __document

import * as React from 'react';
import Document, { Html, Head, Main, NextScript } from 'next/document';
import createEmotionServer from '@emotion/server/create-instance';
import theme from '../utility/theme';
import createEmotionCache from '../utility/createEmotionCache';

export default class MyDocument extends Document {
  render() {
    return (
      <Html lang="fr">
        <Head>
          {/* PWA primary color */}
          <meta charSet="utf-8" />
          <meta key="robots" name="robots" content="index, follow" />
          <meta key="themeColor" name="theme-color" content={theme.palette.primary.main} />
          <link key="shortcutIcon" rel="shortcut icon" href="/favicon.ico" />
          <link
            rel="stylesheet"
            href="https://fonts.googleapis.com/css2?family=Caveat:wght@700&family=Karla:wght@300;400;600;800&display=swap"
          />
          {/* Inject MUI styles first to match with the prepend: true configuration. */}
          {this.props.emotionStyleTags}
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

// `getInitialProps` belongs to `_document` (instead of `_app`),
// it's compatible with static-site generation (SSG).
MyDocument.getInitialProps = async (ctx) => {
  // Resolution order
  //
  // On the server:
  // 1. app.getInitialProps
  // 2. page.getInitialProps
  // 3. document.getInitialProps
  // 4. app.render
  // 5. page.render
  // 6. document.render
  //
  // On the server with error:
  // 1. document.getInitialProps
  // 2. app.render
  // 3. page.render
  // 4. document.render
  //
  // On the client
  // 1. app.getInitialProps
  // 2. page.getInitialProps
  // 3. app.render
  // 4. page.render

  const originalRenderPage = ctx.renderPage;

  // You can consider sharing the same emotion cache between all the SSR requests to speed up performance.
  // However, be aware that it can have global side effects.
  const cache = createEmotionCache();
  const { extractCriticalToChunks } = createEmotionServer(cache);

  ctx.renderPage = () =>
    originalRenderPage({
      enhanceApp: (App) =>
        function EnhanceApp(props) {
          return <App emotionCache={cache} {...props} />;
        },
    });

  const initialProps = await Document.getInitialProps(ctx);
  // This is important. It prevents emotion to render invalid HTML.
  // See https://github.com/mui/material-ui/issues/26561#issuecomment-855286153
  const emotionStyles = extractCriticalToChunks(initialProps.html);
  const emotionStyleTags = emotionStyles.styles.map((style) => (
    <style
      data-emotion={`${style.key} ${style.ids.join(' ')}`}
      key={style.key}
      // eslint-disable-next-line react/no-danger
      dangerouslySetInnerHTML={{ __html: style.css }}
    />
  ));

  return {
    ...initialProps,
    emotionStyleTags,
  };
};

和随机页面结构:

// To generate dynamic links for each Action
export async function getStaticPaths() {
    const actionSlugs = []
    const request = await getDocs(collection(db, "actions")) 
    request.forEach((doc) => {
        actionSlugs.push({ 
            params: { category: specialChar(doc.data().category), slug: doc.data().slug, id: doc.id },
        })
    })
    return {
        paths: actionSlugs,
        fallback: false,
    }
}

// Action is a SSG page optimised for SEO
export async function getStaticProps({ params }) {
    const docRef = doc(db, "actions", params.id);
    const docSnap = await getDoc(docRef);
    if (docSnap.exists()) {
        return {
            props: { 
                actionData: JSON.parse(JSON.stringify(docSnap.data())),
                actionId: params.id,
                params
            } 
        }
    } else {
    console.log("No such document!");
    }

}


function Action({actionData, actionId, params}) {

  // some code and functions
  
  return (
    <Head />
    <Main />
    <Footer />
  )

}

非常感谢 !

【问题讨论】:

  • 你能告诉我们Main 组件的样子吗?
  • 嗨,我写了 <Main /> 但它是一个简单的 <main></main> html 标记。对困惑感到抱歉。我很确定它与 __document.js 渲染方法有关,但我不知道在哪里:(

标签: reactjs next.js server-side-rendering


【解决方案1】:

找到了解决方案。它与 __document 和 __app 中的 render 方法无关。 由于动态页面中的条件渲染,getStaticProps 和 getServerSideProps 实际上没有渲染正确的 HTML。

我在做 :

if (loadingUser) return <Loader/>
return (
  // main render of the page
)

通过删除这个条件渲染(我实际上并没有在原始问题上发布......),一切都运行良好

【讨论】:

    猜你喜欢
    • 2021-12-11
    • 2021-01-29
    • 1970-01-01
    • 1970-01-01
    • 2020-03-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-20
    • 1970-01-01
    相关资源
    最近更新 更多