1

我对样式化组件感到非常兴奋,如果不是因为这个,我很想使用它……
我已经准备了两个使用 next.js 通用渲染库的示例项目。
第一个示例使用 styled-components 作为解决方案,第二个示例使用他们的默认 css 解决方案 styled-jsx。
这两个示例都包含完全相同的代码,但复杂性最低。正如您很快就会看到的那样 - 在 styled-components 示例中,在 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

我非常感谢任何关于为什么它发生在一个而不是另一个的见解,当然还有任何修改这种行为的方法,因为我喜欢使用 styled-components 的许多特性和优势。

谢谢
Ajar
:)

4

2 回答 2

3

这里缺少的是服务器上的样式注入。基本上,当您在 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。这就是它的全部内容,现在那些没有样式的内容已经消失了!(这取自官方示例


注意:使用v2styled-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>
    )
  }
}

希望有帮助!

于 2017-03-22T20:22:24.763 回答
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>
)

 }
}
于 2021-05-25T08:23:30.203 回答