通用呈现在 DOMContentLoaded 事件和 Load 事件之间创建延迟



我对样式化的组件感到非常兴奋,如果不是因为这个,我很想使用它......
我使用 next.js 通用渲染库准备了两个示例项目。
第一个示例是使用 styled-components 作为解决方案,第二个示例是使用 css 的默认解决方案,即 styled-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

我将非常感谢任何关于为什么它发生在一个而不是另一个的见解, 当然还有任何修改此行为的方法,因为我喜欢使用样式组件的许多功能和优势。


谢谢阿扎尔
:)

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


注意:随着styled-components的 v2(即将推出,您现在可以使用 '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>
)
}
}

希望对您有所帮助!

以下是将样式化组件与 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>
)
}
}

最新更新