Рендеринг на стороне сервера с Material UI 1 и Nodejs/React

Проблема: Не удается заставить стили отправляться или загружаться изначально через ssr.

Я слежу за документами и пытаюсь делать, как говорится, но переменная styleSheets все равно кажется пустой. В моем компоненте навигации я использую JSS и использую withStyles. Судя по документации, использование withStyles должно заполнить мои таблицы стилей на моем сервере, верно? Однако переменная, содержащая эти стили, по какой-то причине оказывается пустой. Я что-то неправильно истолковываю?

serverRender.jsx

import React from 'react';
import { renderToString } from 'react-dom/server';
import { Provider } from 'react-redux';
import { RouterContext } from 'react-router';
import Helmet from 'react-helmet';
import serialize from 'serialize-javascript';
import { create } from 'jss';
import preset from 'jss-preset-default';
import { SheetsRegistry } from 'react-jss/lib/jss';
import JssProvider from 'react-jss/lib/JssProvider';
import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles';
import createGenerateClassName from 'material-ui/styles/createGenerateClassName';
import { deepOrange, lightBlue, red } from 'material-ui/colors';
import staticAssets from './static-assets';
// import rtl from 'jss-rtl'; // in-case you're supporting rtl


const sheetsRegistry = new SheetsRegistry();

const theme = createMuiTheme({
  palette: {
    primary: deepOrange,
    secondary: lightBlue,
    error: red,
  },
});

// Configure JSS
const jss = create(preset());
jss.options.createGenerateClassName = createGenerateClassName;

const createApp = (store, props) => renderToString(
  <JssProvider registry={sheetsRegistry} jss={jss}>
    <MuiThemeProvider theme={theme} sheetsManager={new Map()}>
      <Provider store={store}>
        <RouterContext {...props} />
      </Provider>
    </MuiThemeProvider>
  </JssProvider>
);

//Grab our css from our sheetsRegistry
const registeredCss = sheetsRegistry.toString();

const buildPage = ({ componentHTML, initialState, headAssets, css }) => {
  return `
<!doctype html>
<html>
  <head>
    ${headAssets.title.toString()}
    ${headAssets.meta.toString()}
    ${headAssets.link.toString()}
    ${staticAssets.createStylesheets()}
    ${staticAssets.createTrackingScript()}
  </head>
  <body>
    <div id="app">${componentHTML}</div>
    <script>window.__INITIAL_STATE__ = ${serialize(initialState)}</script>
    ${staticAssets.createAppScript()}
    <style id="jss-server-side" type="text/css">${css}</style>
  </body>
</html>`;
};

export default (store, props) => {
  const initialState = store.getState();
  const componentHTML = createApp(store, props);
  const headAssets = Helmet.renderStatic();
  const css = registeredCss;
  console.log(css);
  return buildPage({ componentHTML, initialState, headAssets, css });
};

Здесь он должен взять то, что нам нужно для стилизации.

Где Навигация может выглядеть примерно так:

import React, { Component } from 'react';
import { Link } from 'react-router';
import classNames from 'classnames/bind';
import AppBar from 'material-ui/AppBar';
import Toolbar from 'material-ui/Toolbar';
import Typography from 'material-ui/Typography';
import Button from 'material-ui/Button';
import IconButton from 'material-ui/IconButton';
import MenuIcon from 'material-ui-icons/Menu';
import { withStyles } from 'material-ui/styles';
import styles from '../css/components/navigation.css';

// import passTheAuxLogo from '../images/PassTheAux.png';

const styleSheet = ({
appbar: {
  width: '100%',
},

flex: {

},

menuButton: {
  marginLeft: -12,
  marginRight: 20,
},

navCenter: {
  display: 'flex',
  flex: 1
},
});

const cx = classNames.bind(styles);

class Navigation extends Component {

  constructor(props) {
    super(props);
    this.mobile = false;
  }
  render() {
    const mobile = this.mobile;
    const { classes } = this.props;
    return (
      <div className={classes.appbar}>
        <AppBar position="static" color="primary">
          <Toolbar>
            {mobile && (
            <IconButton className={classes.menuButton} color="contrast" aria-label="Menu">
              <MenuIcon />
            </IconButton>)}
            <Typography type="title" color="inherit" className={cx('flex')}>
              PassTheAux
            </Typography>
            <div className={classes.navCenter}>
              <Link to="/dashboard">
                <Button color="contrast">Dashboard</Button>
              </Link>

              <Link to="/about">
                <Button color="contrast">About</Button>
              </Link>

              <Link to="/404notfound">
                <Button color="contrast">404 Not Found</Button>
              </Link>
            </div>
            <Button color="contrast">Log In</Button>
            |
            <Button color="contrast">Sign up</Button>
          </Toolbar>
        </AppBar>
      </div>
    );
  }
}


export default withStyles(styleSheet)(Navigation);

Должен ли провайдер обойти мое приложение и на клиенте? https://github.com/kkotwal94/KaranPRNB

РЕДАКТИРОВАТЬ: Я думаю, что еще один вопрос, помимо этого, будет заключаться в том, должен ли я использовать JSS, можно ли это сделать, если я хочу использовать PostCSS?


person Karan    schedule 05.12.2017    source источник


Ответы (1)


Вы должны убедиться, что следующий поток выполнения соблюдается:

  1. ReactDOM.renderToString() называется
  2. sheetsRegistry.toString() называется

Это не будет работать наоборот, как это делается в вашем репозитории GitHub.

person Olivier Tassinari    schedule 06.12.2017
comment
Я запутался, разве это не в моем репо? Я вижу в первом кодовом блоке моего вопроса (serverRender.jsx), который я ввел для переменной createApp, которую я обертываю с помощью renderToString. Затем, когда я генерирую свой html ниже, у меня есть {createApp} над {css}, где css вызывает SheetRegistry.toString(). Я сильно дергаюсь или что? - person Karan; 07.12.2017
comment
Неважно, я понимаю, что вы имеете в виду, const registeredCss = sheetsRegistry.toString(); я установил это в середине нигде, однако это должно происходить после того, как я вызываю createApp() в моем методе экспорта по умолчанию. Следовательно, registerCss ничем не заполнен, спасибо, кстати. - person Karan; 07.12.2017