从组件库导入的组件样式在 s-s-r 期间未应用

Posted

技术标签:

【中文标题】从组件库导入的组件样式在 s-s-r 期间未应用【英文标题】:Styles of component imported from component library not applied during s-s-r 【发布时间】:2021-12-21 11:19:38 【问题描述】:

我遇到了一个问题,即从与 webpack 5 捆绑的组件库中导入的组件样式在 s-s-r 期间未应用。

我有两个项目。

带有 SC 的 NextJs 应用。导入组件库:

最小复制回购: https://github.com/tadej321/nextjs-test.git

带有 SC 并与 webpack 5 捆绑在一起的 React 组件库。导入到我的 NextJs 应用程序中:

最小复制回购: https://github.com/tadej321/component-library-test.git

组件库被添加为 NextJs 应用程序的依赖项。 一旦页面在客户端更新,样式就会正确应用,只是页面的初始渲染缺少样式。

我不知道是 SC 还是 NextJs 的问题。但是,如果我不将组件库与 webpack 捆绑,而是仅使用此配置与 babel 进行转译:


  "presets": [
    "@babel/preset-env",
    "@babel/preset-react"
  ],
  "plugins":
  [
    "babel-plugin-styled-components"
  ]

然后 NextJs 执行 s-s-r 并应用样式。

我已经建立了一个最小的repo repo,这样任何人都可以测试这个问题,下面是编译组件库的命令。随意将您的更改推送到我提供的存储库中。

要捆绑组件库,请运行 npm run build 命令并将 package.json 中的 main 设置为:

"main": "./dist/index.js"

要使用 babel 进行编译,请运行 npm run transpile 命令并将 package.json 中的 main 设置为:

"main": "./dist/index.transpiled.js"

如果我没有提供足够的信息来解决此问题,请告诉我,我会将其添加到帖子中。

编辑:

在下面的屏幕截图中,您可以看到两个组件。顶部在 next.js 应用程序中定义并使用样式呈现。底部是从组件库导入的,在服务端渲染时缺少样式。

screenshot of the page

【问题讨论】:

“初始渲染”是什么意思? 我的意思是在服务器端渲染,从 next.js 服务器提供的页面。 问题是当你使用 webpack 编译时你没有使用 babel-plugin-styled-components 插件正确编译? @juliomalves 可能是这样,因为正如我上面所说,当我使用带有babel-plugin-styled-components 插件的 babel 进行编译时,它工作正常。只有当我使用 webpack 编译整个东西时,才会出现这个问题。我将如何继续确定问题是否确实与将 babel-plugin-styled-components 与 webpack 一起使用? 【参考方案1】:

Next 原生具有您应该利用的 babel 预设。我在我的package.json 中使用"babel-plugin-styled-components": "^1.13.2",这个设置适用于我的babel.config.json 中的Webpack 5/Next 11.x:


  "presets": ["next/babel"],
  "plugins": [
    [ 
      "styled-components",  
        "s-s-r": true, 
        "displayName": true, 
        "preprocess": false 
      
    ]
  ]

【讨论】:

您好,谢谢您的回答。我在 next.js 应用程序中设置了与您相同的 babel 配置,它正在渲染在我的 next.js 应用程序中定义的组件。当 next.js 执行服务器端渲染时,只有从我的外部组件库导入的组件缺少样式。 我在您的组件库 repo 中看到的唯一组件称为 Wrapper,您没有导出它。 styled 组件没有导出,react 组件是,返回的是styled 组件。抱歉,如果我的问题不清楚我指的是哪个组件。我已在问题中添加了屏幕截图,您是否知道可能导致此问题的原因? 我不认为你可以像这样从应用程序中提供 react 组件(你需要使用 Next API:nextjs.org/docs/api-routes/introduction)。如果您正在构建一个组件库,那么有一些工具可以帮助您完成该特定任务 - 您正在为自己做很多工作。 我不太明白 Next API 是如何解决这个问题的,据我所知 Next API 的目的是处理 api 调用和数据库操作。虽然我远不是 Next 的专家,所以我可能在这里缺少一些信息。我的实际项目由多个独立服务组成,它们都使用许多相同的组件,因此要在这些服务之间共享公共组件,在我看来,组件库是实现这一目标的最佳方式。当您说“工具”时,您是否想到了任何特定的工具?【参考方案2】:

您必须在渲染之前注入样式才能在pages/_document.js 下创建文件名_document.js。试试这个

import Document,  Head, Main, NextScript, html  from 'next/document';
import  ServerStyleSheet  from 'styled-components';
export default class MainDocument 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 lang='en'>
        <Head>
          <link
            href='https://fonts.googleapis.com/css2?family=Ubuntu'
            rel='stylesheet'
          />
        </Head>
        <body>
          <Main />
          <div id='modal-root' />
          <NextScript />
        </body>
      </Html>
    );
  

【讨论】:

以上是关于从组件库导入的组件样式在 s-s-r 期间未应用的主要内容,如果未能解决你的问题,请参考以下文章

NUXT - s-s-r - 组件未在服务器端呈现

测试期间未为子样式组件提供正确的主题

Nuxt.js 的 s-s-r 兼容组件库

如何配置 webpack 以使用 css-modules 为 Next.js 应用程序构建反应组件库?

Gatsby 构建/s-s-r 换出导致显示错误的组件

在 Next Js 项目 React s-s-r 中导入样式引导程序