如何使用 React、Material UI 和 Styled-components 在 Meteor 环境中管理服务器端渲染?
How to manage Server side rendering, in Meteor environment with React, Material UI and Styled-components?
我已经按照 Meteor docs 中的说明进行了实施。我添加的所有组件 css 都会被渲染。但是 Material UI 组件,外观和客户端版本不一样。
我试过这个 MaterialUI Docs,但还没有成功。我也没有使用 react-jss
。
如果有人知道我可以使用的任何示例项目,那就太棒了。
即使他们使用 Bootstrap 而不是 Material UI,我还是建议您检查这个管理 SSR 的样板文件:cleverbeagle pup,它现在使用 Styled-组件也是。它会让你很好地了解如何实现它,或者你可以尝试将 css 框架和组件迁移到 Material UI.
您可以尝试使用 npm 包 maka-cli,并使用 React、material-ui 和 SSR 生成样板应用程序,看看我是如何做到的:
$ maka create NewApp --theme=material --ssr=true --client=react
然后,导航到文件:
./NewApp/imports/startup/server/index.jsx
您可以看到应用程序如何使用 SSR 构建 material-ui。请注意,这不是使用最新的 material-ui (1.0.0-beta.36) ...但它可能是一个开始!
/************* SSR Code ********************/
import Routes from '../lib/routes.jsx';
import React from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import { onPageLoad } from 'meteor/server-render';
import { StaticRouter } from 'react-router-dom';
import { createMemoryHistory } from 'history';
import { SheetsRegistry } from 'react-jss/lib/jss';
import JssProvider from 'react-jss/lib/JssProvider';
import { create } from 'jss';
import preset from 'jss-preset-default';
import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles';
import createGenerateClassName from 'material-ui/styles/createGenerateClassName';
import { grey } from 'material-ui/colors';
onPageLoad(sink => {
const history = createMemoryHistory(sink.request.url.pathname);
const App = (props) => (
<StaticRouter
location={props.location}
context={{}}>
<Routes history={history}/>
</StaticRouter>
);
// Create a sheetsRegistry instance.
const sheetsRegistry = new SheetsRegistry();
// Create a theme instance.
const theme = createMuiTheme({
palette: {
primary: grey,
accent: grey,
type: 'light',
},
});
const jss = create(preset());
jss.options.createGenerateClassName = createGenerateClassName;
const html = renderToStaticMarkup(
<JssProvider registry={sheetsRegistry} jss={jss}>
<MuiThemeProvider theme={theme} sheetsManager={new Map()}>
<App location={sink.request.url} />
</MuiThemeProvider>
</JssProvider>
);
const css = sheetsRegistry.toString();
sink.appendToHead(`<style id="jss-server-side">${css}</style>`);
sink.renderIntoElementById('app', html);
});
这个问题的答案很简单,只需按照material ui & styled-components 文档中的文档,并使用两个SSR主题中实现的功能即可。
然后你的样式标签来自 material ui & styled-components 工作正常。
我在这里展示了我的 SSR 代码,它遵循如何在流星环境中进行 SSR 渲染。
SSR 实现文档:
Meteor docs with styled-components usage
import React from 'react'
import { MuiThemeProvider, createMuiTheme, createGenerateClassName } from '@material-ui/core/styles'
import { SheetsRegistry } from 'react-jss/lib/jss'
import JssProvider from 'react-jss/lib/JssProvider'
import { renderToString } from 'react-dom/server'
import { onPageLoad } from 'meteor/server-render'
import { StaticRouter } from 'react-router'
import { Provider } from 'react-redux'
import { Helmet } from 'react-helmet'
import { ServerStyleSheet } from 'styled-components'
import MainApp from '../imports/app/MainApp'
import store from '../imports/app/store/store'
onPageLoad(sink => {
const context = {}
// Create a sheetsRegistry instance.
const sheetsRegistry = new SheetsRegistry()
// Create a sheetsManager instance.
const sheetsManager = new Map()
// Theme Font Change
const theme = createMuiTheme({
typography: {
fontFamily: 'FuturaPT-Light',
fontWeight: 'normal',
fontStyle: 'normal',
},
})
const generateClassName = createGenerateClassName()
const sheet = new ServerStyleSheet()
const App = () => (
<Provider store={store}>
<StaticRouter location={sink.request.url} context={context}>
<JssProvider registry={sheetsRegistry} generateClassName={generateClassName}>
<MuiThemeProvider theme={theme} sheetsManager={sheetsManager}>
<MainApp />
</MuiThemeProvider>
</JssProvider>
</StaticRouter>
</Provider>
)
sheet.collectStyles(<App />)
sink.renderIntoElementById('react-root', renderToString(<App />))
const css = sheetsRegistry.toString()
const helmet = Helmet.renderStatic()
sink.appendToHead(helmet.meta.toString())
sink.appendToHead(helmet.title.toString())
sink.appendToHead(`<style id="jss-server-side">${css}</style>`) // material-ui css attached
sink.appendToHead(sheet.getStyleTags()) // styled-components css attached
// console.log(html)
const preloadedState = store.getState()
sink.appendToBody(
`<div id="pre-loaded-state" style="display:none">${JSON.stringify(preloadedState).replace(
/</g,
'\u003c'
)}</div>`
)
})
我已经按照 Meteor docs 中的说明进行了实施。我添加的所有组件 css 都会被渲染。但是 Material UI 组件,外观和客户端版本不一样。
我试过这个 MaterialUI Docs,但还没有成功。我也没有使用 react-jss
。
如果有人知道我可以使用的任何示例项目,那就太棒了。
即使他们使用 Bootstrap 而不是 Material UI,我还是建议您检查这个管理 SSR 的样板文件:cleverbeagle pup,它现在使用 Styled-组件也是。它会让你很好地了解如何实现它,或者你可以尝试将 css 框架和组件迁移到 Material UI.
您可以尝试使用 npm 包 maka-cli,并使用 React、material-ui 和 SSR 生成样板应用程序,看看我是如何做到的:
$ maka create NewApp --theme=material --ssr=true --client=react
然后,导航到文件:
./NewApp/imports/startup/server/index.jsx
您可以看到应用程序如何使用 SSR 构建 material-ui。请注意,这不是使用最新的 material-ui (1.0.0-beta.36) ...但它可能是一个开始!
/************* SSR Code ********************/
import Routes from '../lib/routes.jsx';
import React from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import { onPageLoad } from 'meteor/server-render';
import { StaticRouter } from 'react-router-dom';
import { createMemoryHistory } from 'history';
import { SheetsRegistry } from 'react-jss/lib/jss';
import JssProvider from 'react-jss/lib/JssProvider';
import { create } from 'jss';
import preset from 'jss-preset-default';
import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles';
import createGenerateClassName from 'material-ui/styles/createGenerateClassName';
import { grey } from 'material-ui/colors';
onPageLoad(sink => {
const history = createMemoryHistory(sink.request.url.pathname);
const App = (props) => (
<StaticRouter
location={props.location}
context={{}}>
<Routes history={history}/>
</StaticRouter>
);
// Create a sheetsRegistry instance.
const sheetsRegistry = new SheetsRegistry();
// Create a theme instance.
const theme = createMuiTheme({
palette: {
primary: grey,
accent: grey,
type: 'light',
},
});
const jss = create(preset());
jss.options.createGenerateClassName = createGenerateClassName;
const html = renderToStaticMarkup(
<JssProvider registry={sheetsRegistry} jss={jss}>
<MuiThemeProvider theme={theme} sheetsManager={new Map()}>
<App location={sink.request.url} />
</MuiThemeProvider>
</JssProvider>
);
const css = sheetsRegistry.toString();
sink.appendToHead(`<style id="jss-server-side">${css}</style>`);
sink.renderIntoElementById('app', html);
});
这个问题的答案很简单,只需按照material ui & styled-components 文档中的文档,并使用两个SSR主题中实现的功能即可。
然后你的样式标签来自 material ui & styled-components 工作正常。 我在这里展示了我的 SSR 代码,它遵循如何在流星环境中进行 SSR 渲染。
SSR 实现文档:
Meteor docs with styled-components usage
import React from 'react'
import { MuiThemeProvider, createMuiTheme, createGenerateClassName } from '@material-ui/core/styles'
import { SheetsRegistry } from 'react-jss/lib/jss'
import JssProvider from 'react-jss/lib/JssProvider'
import { renderToString } from 'react-dom/server'
import { onPageLoad } from 'meteor/server-render'
import { StaticRouter } from 'react-router'
import { Provider } from 'react-redux'
import { Helmet } from 'react-helmet'
import { ServerStyleSheet } from 'styled-components'
import MainApp from '../imports/app/MainApp'
import store from '../imports/app/store/store'
onPageLoad(sink => {
const context = {}
// Create a sheetsRegistry instance.
const sheetsRegistry = new SheetsRegistry()
// Create a sheetsManager instance.
const sheetsManager = new Map()
// Theme Font Change
const theme = createMuiTheme({
typography: {
fontFamily: 'FuturaPT-Light',
fontWeight: 'normal',
fontStyle: 'normal',
},
})
const generateClassName = createGenerateClassName()
const sheet = new ServerStyleSheet()
const App = () => (
<Provider store={store}>
<StaticRouter location={sink.request.url} context={context}>
<JssProvider registry={sheetsRegistry} generateClassName={generateClassName}>
<MuiThemeProvider theme={theme} sheetsManager={sheetsManager}>
<MainApp />
</MuiThemeProvider>
</JssProvider>
</StaticRouter>
</Provider>
)
sheet.collectStyles(<App />)
sink.renderIntoElementById('react-root', renderToString(<App />))
const css = sheetsRegistry.toString()
const helmet = Helmet.renderStatic()
sink.appendToHead(helmet.meta.toString())
sink.appendToHead(helmet.title.toString())
sink.appendToHead(`<style id="jss-server-side">${css}</style>`) // material-ui css attached
sink.appendToHead(sheet.getStyleTags()) // styled-components css attached
// console.log(html)
const preloadedState = store.getState()
sink.appendToBody(
`<div id="pre-loaded-state" style="display:none">${JSON.stringify(preloadedState).replace(
/</g,
'\u003c'
)}</div>`
)
})