所以我正在开发 POC 应用程序,它需要有 SEO 优化的内容(=== 在服务器上呈现)。但是在同一条路线中,可能会有来自不同来源的动态数据,并且可能需要一段时间才能捕获所有这些数据。SEO 不需要此动态数据,因此将实施异步加载。
到目前为止,我所拥有的看起来像这样(请记住,这只是示例):
// routes.js
import serverRender from './services/aboutService';
const routes = (
<Route path="/" component={Layout}>
<IndexRoute component={Home}/>
<Route path="/about">
<Route
path="/About"
component={AboutContainer}
serverRender={serverRender} />
</Route>
</Route>
);
// aboutService.js
const serverRender = () => {
return axios.get("http://localhost:3002/services/about")
.then(res => res.data)
.catch(function (error) {
console.log(error);
});
}
export default serverRender;
// AboutContainer.js
import React from 'react';
export default class About extends Component {
constructor(props){
super(props);
this.state = {
data: { username: "", isFetching : true, hasError: false }
};
this._fetchNonSEOData = this.fetchNonSEOData.bind(this);
console.log("CompetitionContainer constructor: ", props)
}
componentDidMount(){
//this._fetchNonSEOData();
}
_fetchNonSEOData(){
// dynamic content, not important for Crawlers
// will call setState here to update state properties
}
render(){
return (
<div>
<h1>User: {this.props.data.username}</h1>
<div className="non-seo">
{this._fetchNonSEOData()}
</div>
</div>
)
}
}
使用 ExpressJS 的 server.js(它的一小部分):
// server.js app.get('*', (req, res) => { ReactRouter.match({ routes, location: req.url }, (err, redirectLocation, renderProps) => {
if (err) {
return res.status(500).send(err.message);
}
if (redirectLocation) {
return res.redirect(302, redirectLocation.pathname + redirectLocation.search);
}
let markup;
if (renderProps) {
preRenderMiddleware(renderProps)
.then(data => {
const appElement = (
<ReactRouter.RouterContext
{...renderProps}
createElement={(Component, props) => {
return <Component data={data} {...props} />;
}}
/>
);
//
let markup = ReactDOMServer.renderToString(appElement);
console.log("AppString:", markup)
return res.render('index', { markup, head });
})
} else {
// otherwise we can render a 404 page
markup = ReactDOMServer.renderToString(<NotFoundPage/>);
res.status(404);
}
});
});
所以你看到有 preRenderMiddleware 它返回已解决的 Promise ,这是我认为我可能错的部分:
//preRenderMiddleware.js
const defaultServerRender = () => Promise.resolve();
function preRenderMiddleware({ routes, location, params }) {
const matchedRoute = routes[routes.length - 1];
const serverRenderHandler = matchedRoute.serverRender || defaultServerRender;
return serverRenderHandler(params);
}
所以我的问题是从服务器获取预期的标记 - 在 AboutContainer this.props.data 正在获取数据。但是,当客户端启动时, this.props.data 是未定义的。
任何人都可以指出一些好的解决方案吗?我确定我不是第一个遇到这个问题的人。我遇到了一些解决方案,但是客户端上所有重新请求的相同数据都是我希望避免的,这又会有点奇怪。
我也不想为此使用 Redux / 任何 Flux。
有什么想法吗?