通用渲染会在DOMContentLoaded事件与Load事件之间产生延迟

时间:2017-03-15 10:35:07

标签: css reactjs styled-components next.js universal-react

我对设计风格的组件非常兴奋,如果不是这样的话,我会很乐意使用它...
我使用next.js通用渲染库准备了两个示例项目 第一个例子是使用样式组件作为解决方案,第二个例子是使用他们的默认解决方案css,样式为-jsx。
两个示例都包含具有最低复杂程度的完全相同的代码。 正如您将很快看到的那样 - 在样式组件示例中,DOMContentLoaded事件和Load事件之间存在令人不安的延迟,其中用户实际看到未样式的html标记,而在第二个示例中使用styled-jsx这不是情况下。

这两个演示现在都使用Zeit在线托管:
1 - https://01-styled-components-sqprkdqeft.now.sh
2 - https://02-styled-jsx-nhrynpsdox.now.sh

github上提供的来源:
1 - https://github.com/Ajar-Ajar/next-demo--styled-components
2 - https://github.com/Ajar-Ajar/next-demo--styled-jsx

我非常感谢任何关于为什么会在一个而不是另一个中发生的见解, 当然还有任何方法可以修改这种行为,因为我很乐意使用样式组件来实现其众多特性和优势。

谢谢你 半掩
:)

2 个答案:

答案 0 :(得分:2)

这里缺少的是服务器上的样式注入。基本上,当您在JavaScript中编写样式时,您必须在服务器上获取生成的样式,并将它们作为style标记注入生成的HTML中。

Next的内置解决方案会自动为您执行此操作,styled-components您必须执行一些手动工作并添加pages/_document.js文件,如下所示:

import Document, { Head, Main, NextScript } from 'next/document'
import { styleSheet } from 'styled-components'

export default class MyDocument extends Document {
  static async getInitialProps ({ renderPage }) {
    const page = renderPage()
    const styles = (
      <style dangerouslySetInnerHTML={{ __html: styleSheet.rules().map(rule => rule.cssText).join('\n') }} />
    )
    return { ...page, styles }
  }

  render () {
    return (
      <html>
        <Head>
          <title>My page</title>
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </html>
    )
  }
}

注意我们如何使用styled-components的样式注入样式标记。这就是它的全部,现在无格式内容的闪现消失了! (这取自the official example

注意:使用{strong> v2 styled-components (即将推出,你现在可以使用`npm i --save styled-components @ next)获得 SSR的官方API 所以它看起来更像是这样:

import Document, { Head, Main, NextScript } from 'next/document'
import styleSheet from 'styled-components/lib/models/StyleSheet'

export default class MyDocument extends Document {
  static async getInitialProps ({ renderPage }) {
    const page = renderPage()
    const styles = (
      <style dangerouslySetInnerHTML={{ __html: styleSheet.getCSS() }} />
    )
    return { ...page, styles }
  }

  render () {
    return (
      <html>
        <Head>
          <title>My page</title>
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </html>
    )
  }
}

希望有所帮助!

答案 1 :(得分:0)

以下是将样式组件与 next 一起使用以避免该问题的推荐方法: https://github.com/vercel/next.js/blob/master/examples/with-styled-components/pages/_document.js

import Document from 'next/document'
import { ServerStyleSheet } from 'styled-components'

export default class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const sheet = new ServerStyleSheet()
    const originalRenderPage = ctx.renderPage

try {
  ctx.renderPage = () =>
    originalRenderPage({
      enhanceApp: (App) => (props) =>
        sheet.collectStyles(<App {...props} />),
    })

  const initialProps = await Document.getInitialProps(ctx)
  return {
    ...initialProps,
    styles: (
      <>
        {initialProps.styles}
        {sheet.getStyleElement()}
      </>
    ),
  }
} finally {
  sheet.seal()
}
render () {
return (
  <html>
    <Head>
      <title>My page</title>
    </Head>
    <body>
      <Main />
      <NextScript />
    </body>
  </html>
)

 }
}