我很难弄清楚我们应该做些什么来使 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
,HEAD
和BODY
标签,它们引用到bundle.js
- app.js 将 React 设置为 DOM 中的根元素。
- Webpack
bundle.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 找到了解决方案: