1

我正在 NodeJS 之上构建一个同构的 react-redux 应用程序。我正在从服务器渲染我的主页。但是,我的样式并没有反映在我的渲染视图中。我想在客户端导入样式表。我尝试了这篇文章这篇文章,但它们都没有真正让我得到我想要实现的目标。

以下是有关该项目的更多详细信息。

.babelrc

{
 "presets": [ "es2015", "react", "stage-0"],
 "plugins": ["transform-decorators-legacy", ["transform-assets", {
            "extensions": ["scss"],
            "name": "[name].[ext]?[sha512:hash:base64:7]",
          }]]
 }

webpack.config.js

const path = require('path');
module.exports = [
    {
      name: 'client',
      target: 'web',
      entry: './routes/client.jsx',
      output: {
        path: path.join(__dirname, 'assets'),
        filename: 'client.js',
        publicPath: '/assets/',
      },
      resolve: {
        extensions: ['.js', '.jsx']
      },
      devtool: 'source-map',
      module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /(node_modules\/)/,
                use: [{ loader: 'babel-loader'}]
            },
            {
                test: /\.scss$/,
                use: [
                    { loader: 'isomorphic-style-loader' },
                    {
                        loader: 'css-loader',
                        options: {
                            modules: true,
                            importLoaders: 1,
                            localIdentName: '[name]__[local]___[hash:base64:5]',
                            sourceMap: true
                        }
                    },
                    { loader: 'sass-loader'}
                ]
            }
        ],
    },
}];

服务器.js

import express from 'express'
import React from 'react'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import MainStore from './views/store/MainStore'
import { StaticRouter } from 'react-router-dom';
import Routes from './routes/routes';
import Template from './views/templates/template';
import { Helmet } from 'react-helmet';
import { renderToString } from 'react-dom/server'
import ReactDOMServer from 'react-dom/server';
import ContextProvider from './routes/contextProvider'

const webpackDevMiddleware = require('webpack-dev-middleware')
const config = require('./webpack/webpack.development.config.js')
const webpack = require('webpack')
const app = express()
const port = 3000
const compiler = webpack(config);

let preloadedState = { shipper: {view: "from_server"} }

app.use('/assets', express.static('./assets'))
app.use(webpackDevMiddleware(compiler, {
   publicPath: "/assets/",
}));

app.use(handleRender);

function handleRender(req, res) {
   // Create a new Redux store instance
   const store = createStore(MainStore, preloadedState)
   const css = new Set(); // CSS for all rendered React components
   const context = { insertCss: (...styles) => styles.forEach(style =>   
   css.add(style._getCss())) }

   const html = renderToString(
     <Provider store={store}>
        <StaticRouter context={context}>
            <ContextProvider context={context}>
            <Routes />
        </ContextProvider>
        </StaticRouter>
     </Provider>
  )
  const finalState = store.getState()
  const helmet = Helmet.renderStatic();
  const preloadedState = store.getState()
  res.send(renderFullPage(html, preloadedState));
 }

 function renderFullPage(html, finalState) {
    return `
      <!doctype html>
      <html>
         <head>
            <title>Redux Universal Example</title>
            <style type="text/css">${[...css].join('')}</style>
         </head>
         <body>
             <div id="root">${html}</div>
             <script>
                window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState).replace(/</g, '\\u003c')}
             </script>
             <script src="./assets/client.js"></script>
         </body>
    </html>
    `
  }

app.listen(port)

contextProvider.js

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Routes from './routes.jsx';

export default class ContextProvider extends Component {
   static childContextTypes = {
   insertCss: PropTypes.func,
}

 getChildContext() {
    return { ...this.props.context }
  }

 render() {
    const { children, ...props } = this.props
    return React.cloneElement(children, props)
  }
}

我将它导入到我的 homePresenter 中

import homePageStyle from './home.scss';

并在我的 div 中使用它与相同的组件

<div className="component">

如果我将其更改为

<div className={homePageStyle.component}>

我在浏览器上收到错误

TypeError: style._getCss is not a function at server.js:52:84

在浏览器上,我可以看到 div 的类名为“组件”;它;只是它没有继承样式。

关于我在这里缺少什么的任何建议?

4

1 回答 1

-1

TypeError:style._getCss 不是 server.js:52:84 处的函数

很可能是服务器端渲染配置不正确。如果您不webpack用于编译服务器端包,当然不会加载适当的样式,因为isomorphic-style-loader没有在服务器端处理文件。
检查应用程序如何启动并确保webpack已应用于服务器捆绑包和配置是这样的:https
://webpack.js.org/configuration/node/ 您也可以尝试使用前端+后端捆绑包的现成同构解决方案并包括CSS 支持,例如resolve-app

于 2017-12-06T10:24:13.427 回答