服务端渲染

所有的 Geist UI 组件都能完美适应服务端渲染,实际上,你现在所见的文档站点就是来自服务端渲染。

一个常见的 React 组件在服务端被渲染为 HTML 字符串通常包含两部分:HTML 骨架与样式,它们共同构成了请求中返回的首个字符串,这能有效的保证用户尽可能早的阅读到页面内容 (而不需要等待额外地 JavaScript 资源加载与解析)。

在 Geist 中,你要做的只是把 Geist 生成的样式文本信息添加到服务端渲染工具中,无论 Next.js 还是自行构建的 HTTP 服务器。

使用 Next.js

next.js 框架中,你首先需要创建 _document.js 文件来填充自定义信息,请参考 Next.js 的官方文档了解此文件的影响和意义。

随后我们将以下示例代码加入到文件中:

pages/_document.js
import { Fragment } from "react"
import Document, { Html, Head, Main, NextScript } from 'next/document'
import { CssBaseline } from '@geist-ui/core'

class MyDocument extends Document {
  static async getInitialProps (ctx) {
    const initialProps = await Document.getInitialProps(ctx)
    const styles = CssBaseline.flush()

    return {
      ...initialProps,
      styles: [
        <Fragment key="1">
          {initialProps.styles}
          {styles}
        </Fragment>,
      ],
    }
  }

  render() { ... }
}

示例中的 flush 方法用于收集 Geist 在当前页面中产生的样式,每个项目只需要设置一次。这里也准备了一个完整的 应用示例 供作参考。

定制服务端

在你自定义的服务端或其他预渲染框架中,你可以通过函数 CssBaseline.flush 获取所有样式文本。

import React from 'react'
import ReactDOM from 'react-dom/server'
import { CssBaseline } from 'geist-ui/core'
import App from './app'

export default (req, res) => {
  const app = ReactDOM.renderToString(<App />)
  const styles = CssBaseline.flush()
  const html = ReactDOM.renderToStaticMarkup(
    <html>
      <head>{styles}</head>
      <body>
        <div id="root" dangerouslySetInnerHTML={{ __html: app }} />
      </body>
    </html>,
  )
  res.end('<!doctype html>' + html)
}