【问题标题】:SSR with styled-components - when app.js loads site missing few styles带有样式组件的 SSR - 当 app.js 加载站点时缺少一些样式
【发布时间】:2019-03-05 22:42:28
【问题描述】:

我使用styled-components 实现了 SSR。

当页面使用 SSR 加载时,一切看起来都很好。但是,当app.js 与 SSR 版本一起加载和水合时,页面缺少一些样式并且很少有元素中断。

更重要的是 - 当我在本地打开应用程序时,使用 npm start 或基本上只是删除我的 SSR,一切正常并且样式被正确应用。

重要提示:当我进入页面并且app.js 加载和样式被破坏时,如果我更改路线 - 新路线将正确显示应用样式并且问题......消失了。

  • SSR 加载 - 样式很好
  • 然后几秒后 app.js 加载(水合过程) - 样式被破坏

在本地运行应用程序 - 样式没有问题

在没有 SSR 的情况下运行应用程序 - 样式没有问题


简而言之 - 如果我使用 SSR 缺少一些样式,SSR 本身会返回正确的样式,但在使用 app.js 水合后,很少有组件损坏。

我敢打赌这可能是styled-components 的问题。除了缺少样式的一个组件外,SSR 工作正常,其他一切正常。


我知道关于我的案例的信息相当不完整,但为了显示可能导致此错误的每个部分,我应该发布整个项目,但是也许您遇到过类似的案例,您会以某种方式帮助我。谢谢。

编辑:我的babel-styled-component-plugin 配置:

['babel-plugin-styled-components', {
    ssr: true,
    displayName: false,
    fileName: false,
    transpileTemplateLiterals: false,
    minify: false,
}],

【问题讨论】:

    标签: reactjs server-side-rendering styled-components isomorphic-javascript


    【解决方案1】:

    两件事...

    1) 确保您使用的是babel plugin;没有它,就不能保证生成的类名在服务器和客户端之间是相同的。

    2) 在您的捆绑设置中,确保您对客户端和服务器使用几乎相同的 babel 配置。如果存在重大差异并且文件以非常不同的方式进行转换,则可能会影响生成的类名输出。

    【讨论】:

    • 谢谢。我知道很难理解我的情况到底发生了什么,但是我在 github github.com/styled-components/styled-components/issues/1860 上看到了类似的问题,不幸的是还没有解决。无论如何 - 感谢您开发这个令人惊叹的库,尊重。
    • 出于好奇,您是否在使用像 react-apollo 这样在 SSR 期间具有数据获取步骤的库?如果是这样,则需要在使用来自 ServerStyleSheet 实例的 collectStyles 调用包装最终 JSX 之前完成所有这些工作。
    • @probablyup 我正在使用 nextjs、apollo 和 styled-components,我遇到了这个确切的问题。我如何确保阿波罗首先运行?我正在使用 withApollo HOC 并将我的页面包装在其中。
    【解决方案2】:

    我分四步解决

    服务器.js

    app.get('*', handleRender);
    
    
    function handleRender (req, res) {
      const activeRoute = routes.find((route) => matchPath(req.url, route)) || {};
    
      const promise = activeRoute.fetchInitialData ?
        activeRoute.fetchInitialData(req.path) :
    
        Promise.resolve();
    
    promise.then((data) => {
        const context = { data };
        
        const store = configureStore({});
        const sheet = new ServerStyleSheet(); // ==== STEP -1
        
    
    
        const preloadedState = store.getState();
    
        const html = renderToString(
            sheet.collectStyles(    // === STEP --2
                <Provider store={store}>
                    <StaticRouter location={req.url} context={context}>
                        <App/>
                    </StaticRouter>
                </Provider>
    
            )
        );
        const styles = sheet.getStyleTags(); /// === STEP 3
       
        res.send(renderFullPage(html, styles, preloadedState));
    });
    
    
    
    function renderFullPage (html, styles, preloadedState) {
    return `
    <!DOCTYPE html>
    <html>
      <head>
      <link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;600&display=swap" rel="stylesheet">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <style>body,html,div,ul,p{margin:0;padding:0;}</style>
        <title>Characters of Rick And Morty Show</title>
        <style>
          ${globalStyles}
        </style>
        ${styles} // === STEP 4
      </head>
      <body>
        <div id="root">${html}</div>
        <script>
          // WARNING: See the following for security issues around embedding JSON in HTML:
          // https://redux.js.org/recipes/server-rendering/#security-considerations
          window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState).replace(
        /</g,
        '\\u003c'
    )}
        </script>
        <script src="client_bundle.js"></script>
      </body>
    </html>
    `;
    

    }

    客户

    hydrate(<BrowserRouter>
         <Provider store={store}>
           <App/>
        </Provider>
      </BrowserRouter>, document.getElementById('root'));
    

    【讨论】:

      猜你喜欢
      • 2019-12-12
      • 2018-10-16
      • 1970-01-01
      • 2014-07-20
      • 2020-03-14
      • 1970-01-01
      • 2011-02-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多