styled-component的分体渲染,代码分离(不是next.js)。

问题描述 投票:0回答:1

在我的App的第一次展示中,我的styled-components没有被应用,只是看到了普通的html标签。

我如何处理这个问题?我希望在服务器端渲染时应用基本样式。

我查看了 styled 组件的官方文档,但是...。服务器样式表 不工作。

这里我附上了我的应用程序预览和代码

enter image description here

服务器.tsx

import express from 'express';
import path from 'path';
import React from 'react';
import { renderToString } from 'react-dom/server';
import { StaticRouter } from 'react-router-dom';
import { Helmet } from 'react-helmet';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import { ChunkExtractor } from '@loadable/server';
import { ServerStyleSheet, StyleSheetManager } from 'styled-components';

const app = express();

if (process.env.NODE_ENV !== 'production') {
  const webpack = require('webpack');
  const webpackConfig = require('../webpack.client.js').map((config: any) => {
    config.output.path = config.output.path.replace('dist/dist/', 'dist/');
    return config;
  });

  const webpackDevMiddleware = require('webpack-dev-middleware');
  const webpackHotMiddleware = require('webpack-hot-middleware');

  const compiler = webpack(webpackConfig);

  app.use(
    webpackDevMiddleware(compiler, {
      logLevel: 'silent',
      publicPath: webpackConfig[0].output.publicPath,
      writeToDisk: true,
    }),
  );

  app.use(webpackHotMiddleware(compiler));
}

app.use(express.static(path.resolve(__dirname)));

app.get('*', (req, res) => {
  const sheet = new ServerStyleSheet(); 
  const styleTags = sheet.getStyleTags(); 
  const nodeStats = path.resolve(__dirname, './node/loadable-stats.json');
  const webStats = path.resolve(__dirname, './web/loadable-stats.json');
  const nodeExtractor = new ChunkExtractor({ statsFile: nodeStats });
  const { default: App } = nodeExtractor.requireEntrypoint();
  const webExtractor = new ChunkExtractor({ statsFile: webStats });

  const context = {};


  try {
    const styledHtml = sheet.collectStyles(
      <StaticRouter location={req.url} context={context}>
        <App />
      </StaticRouter>
    )
    const jsx = webExtractor.collectChunks(styledHtml);
    const html = renderToString(jsx);

    const helmet = Helmet.renderStatic();

    res.set('content-type', 'text/html');
    res.send(`
      <!DOCTYPE html>
        <html lang="en">
          <head>
            <meta name="viewport" content="width=device-width, user-scalable=no">
            <meta name="google" content="notranslate">
            ${helmet.title.toString()}
            ${webExtractor.getLinkTags()}
            ${webExtractor.getStyleTags()}
          </head>
          <body>
            <div id="root">${html}</div>
            ${webExtractor.getScriptTags()}
          </body>
        </html>
    `);

    } catch(error){
      console.log(error);
    } finally{
      sheet.seal(); 
  }
});

app.listen(5000, () => console.log('Server started http://localhost:5000'));
reactjs server-side styled-components code-splitting
1个回答
0
投票

我通过注入适当的样式来解决这个问题,使用 服务器样式表

参见以下代码

  /// server.tsx  using express 
  import { ServerStyleSheet } from 'styled-components';
  import { ChunkExtractor } from '@loadable/server'; 
  ... 
  const sheet = new ServerStyleSheet();
  const webStats = path.resolve(__dirname, './loadable-stats.json');
  const webExtractor = new ChunkExtractor({statsFile: webStats}); 

  const jsx = webExtractor.collectChunks(<App/>);
  const html = renderToString(sheet.collectStyles(jsx));
  const styles = sheet.getStyleTags(); 

  res.send(`
      ... 

      <head>
       ${webExtractor.getStyleTags() + styles }
      </head> 
      ...  `)

我缺少的关键点是把 风格 之后 webExtractor.getStyleTags().

做完这些后,我看到一切都很正常

© www.soinside.com 2019 - 2024. All rights reserved.