1

我很难弄清楚我们应该做些什么来使 React 同构。我正在学习一些教程,这就是我现在所拥有的:

  • 我创建了一个server.js启动 Express 服务器的文件
  • 我创建了一个router.js文件,在其中创建了一个 Express Router 对象,导入了ReactRouter( react-router) 和ReactDOMServer( react-dom/server),并在那里设置了一个 Express 路由 ( router.get('*')),它获取 ReactRouter 试图找到一个渲染路由 ( ReactRouter.match)
  • 出于捆绑的目的,我创建了一个包含ReactRouter指令的 allRoutes.js 文件。我设置了两条路径,/并且/about
  • Main和两个组件,About每个组件都有一个按钮和一个单击事件。Main必须在 '/' 中呈现,而 About 在 '/about' 中。两个组件都有HTML,HEADBODY标签,它们引用到bundle.js
  • app.js 将 React 设置为 DOM 中的根元素。
  • Webpackbundle.js从 allRoutes.js 文件创建

我遇到了几个问题,第一个是:

  • Main 已正确呈现并且 Javascript 工作正常,但是转到localhost:3000/about,页面加载大约需要 5 秒,它加载时没有 javascript 行为,并且我收到校验和错误。

  • 从 /about 中删除 bundle.js 解决了校验和和重载问题,但没有 Javascript 行为

  • 从 allRoutes.js 捆绑不会出现上述错误,但我没有在页面中工作的 javascript(尽管它是用 bundle.js 编写的)

  • 将 /about 设置为 / 的子路由,因为 Main 不会导致问题,所以永远不会加载 About 组件。仅当路由匹配时,服务器才会呈现 Main。

正如我计划的那样,但我不确定这是为了实现同构行为我应该做的,我正在这些根组件中创建一个完整的 HTML 页面,即 About 和 Main。在我看来,对 SEO 更友好。

有什么我做错了吗?

应用程序.js

var React = require('react');
var ReactDOM = require('react-dom');
var Main = require('./components/Main');

ReactDOM.render(React.createElement(Main),document);

路由器.js

var express = require('express');
var router = express.Router();
var ReactRouter = require('react-router');
var ReactDOMServer = require('react-dom/server');
var Main = require('./components/Main');
var About = require('./components/About');
var React = require('react');
var routes = require('./routes');

router.get('*', function (req, res) {
    var props = {};
    ReactRouter.match({
        routes: (
          routes
        ),
        location: req.url
    }, function (error, redirectLocation, renderProps) {
        console.log(renderProps)
        if (renderProps) {
            // se encontrou uma rota, responde o HTML referente ao componente que foi preprocessado no backend
            res.send(ReactDOMServer.renderToString(
                <ReactRouter.RouterContext {...renderProps} createElement={
                    function(Component,renderProps){
                        return <Component {...renderProps} {...props} />
                    }
                } />
            ));
        } else {
            res.status(404).send('Not found');
        }
    });
});

module.exports = router;

路由.js

//routes.js
var ReactRouter = require('react-router');
var React = require('react');
var Main = require('./components/Main');
var About = require('./components/About');

module.exports = (
  <ReactRouter.Router history={ ReactRouter.browserHistory }>
      <ReactRouter.Route path='/' component={ Main } />
      <ReactRouter.Route path='/about' component={ About } />
  </ReactRouter.Router>
);

网页包

module.exports = {
    entry: './routes.js',
    output: {
        filename: './bundle.js',
        path: 'public'
    },
    module: {
        loaders: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                loader: 'babel-loader',
                query: {
                    presets: ['react']
                }
            }
        ]
    }
};

about.js

var React = require('react');

module.exports = React.createClass({   
    _handleClick: function(){
        alert('Sobre!');
    },
    render: function(){
         return (
             <html>
                <head>
                    <link rel='stylesheet' href='/style.css' />
                </head>
                <body>
                    <h1>About</h1>
                    <button onClick={ this._handleClick }>About</button>
                    <script src='/bundle.js'></script>
                </body>                
             </html>                      
         );
    }
});

服务器.js

require('babel-register')({
    presets: ['react']
});

var React = require('react');
var ReactDOMServer = require('react-dom/server');
var express = require('express');
var app = express();

app.use(express.static('./public'));

app.use(require('./router'));

app.listen(3000,function(){
    console.log('Started at 3000');
});

@编辑

我将 allRoutes (routes.js) 更改为此。

<ReactRouter.Router history={ ReactRouter.browserHistory }>
      <ReactRouter.Route path='/' component={ Main } >
        <ReactRouter.Route path='about' component={ About } />
      </ReactRouter.Route>
  </ReactRouter.Router>

现在 About 是 Main 的孩子,Javascript 在 Main 中工作,但 About 从未加载。尝试访问不存在的路由会显示 404,但任何映射的路由都会呈现 Main。到底是怎么回事?

@resolved 找到了解决方案:

https://github.com/victorsferreira/react-isormorphic/

4

0 回答 0