由于我的网站是从 0 开始的,排版、样式、业务逻辑都是由自己一个人完成,这其中也遇到过很多之前从来没有遇到过的问题,其中也有几次遇到坑一下就卡住了,接连几个星期都没有一点进展,在网上也搜不到有用的解决方案,最后也只能是把官方文档再啃一遍寻找办法,好在苍天不负死磕人,最后还是解决了问题。

在《火星救援》的最后,马特达蒙有一段话:When I was up there, stranded by myself, did I think I was going to die? Yes, absolutely. And that’s what you need to know going in, because it’s going to happend to you. This is space. It does not cooperate. At some point, everything is going to south on you, Everything is going to go south and you’re going to say, “This is it. This is how I end.” Now, you can either accept that or you can get to work. That’s all it is. You just begin. You do the math. You solve one problem then you solve the next one. And then the next. And if you solve enough problem, you get to come home.

“当我独自被困在那里时,想过会死在那吗?想过,当然想过,这是你必须要知道的,因为它正在发生在你身上,这是太空,它不会配合你,在某一时刻,所有的一切都会变得越来越糟糕,当一切都越来越糟糕时,“就这样?这就是我的终点?”现在,你只能坚强的面对,你要么屈服,要么反抗,就是这样,只要你开始想办法,解决一个问题,解决下一个问题,解决了足够多的问题,你就能回家了。”




闲白儿不多说了,首先我遇到的最大的,也是卡住最长时间的一个坑是 Next.js 的,由于 Next.js 是预渲染的框架,在使用它写博客的前端时出现了相同的 HTML 渲染前后 ClassName 不一致的情况:

Warning: Prop `className` did not match. Server: "XXXX-01" Client: "XXXX-02"

上面错误提示中, Server 的类是一个名字, Client 中相同的 HTML 标签中的类名又是另外一个,因为我使用的 UI 框架是 Material-UI 其中使用了 makeStyles 所以很多 ClassName 是由 UI 框架自动生成的。

解决方法是在渲染的时候,将渲染的结果,转换为字符串,传入 Client 这样浏览器是直接将字符串渲染为页面。具的的方法是在 Next.js 的项目根目录的 pages 文件夹内新建 _document.js 的文件,代码如下:

import React from 'react';
import Document, { Html, Head, Main, NextScript } from 'next/document';
import { ServerStyleSheets } from '@material-ui/core/styles';
// import theme from './theme';
export default class MyDocument extends Document {
  render() {
    return (
      <Html>
        <Head>
          <link
            rel="stylesheet"
            href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
          />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}
// 重点是下面。
MyDocument.getInitialProps = async (ctx) => {
  const sheets = new ServerStyleSheets();
  const originalRenderPage = ctx.renderPage;
  ctx.renderPage = () =>
    originalRenderPage({
      enhanceApp: (App) => (props) => sheets.collect(<App {...props} />),
    });
  const initialProps = await Document.getInitialProps(ctx);
  return {
    ...initialProps,
    // Styles fragment is rendered after the app and page rendering finish.
    styles: [...React.Children.toArray(initialProps.styles), sheets.getStyleElement()],
  };
};

还有 _app.js ,代码如下:

export default function App( { Component, pageProps }) {
    return (
        <Component {...pageProps} />
    )
}

至于是什么原理,等之后有时间了再去深挖吧。

阅读次数 457