【发布时间】:2018-04-03 22:01:06
【问题描述】:
我运行了一个快速服务器来预渲染我的反应应用程序。我有一个路由文件,它将 HomeContainer 与基本路由 / 匹配,所有其他路由与未找到的页面匹配。
import HomeContainer from 'containers/home-container/home-container';
import PageNotFound from 'components/page-not-found/page-not-found';
const routes = [
{
path: '/',
exact: true,
component: HomeContainer
},
{
path: '*',
component: PageNotFound
}
];
export default routes;
我遇到的问题是,当我在服务器上运行应用程序时,页面未找到路由在快速更改为 HomeContainer 路由之前被渲染。
我发现这是因为我的 express 服务器在向 / 发出请求之前向 /json/version 发出请求,此路由与我的路由文件中的一个不匹配,因此找不到该页面组件被渲染。
现在我不明白为什么它会发出这个请求以及如何停止在主容器之前呈现page not found 组件。我已经尝试调试节点服务器,并且最早可以找到引用此路径的位置是在名为_http_server.js的文件中的发出调用中@
下面是调试器的屏幕截图以及我在其中找到引用的 URL。
也供参考,我在下面包含了我的快递服务器。
import express from 'express';
import React from 'react';
import { renderToString } from 'react-dom/server';
import { Provider } from 'react-redux';
import { StaticRouter, matchPath } from 'react-router-dom';
import serialize from 'serialize-javascript';
import expressStaticGzip from 'express-static-gzip';
import sourceMapSupport from 'source-map-support';
import routes from 'routes';
import configureStore from 'store';
import AppContainer from 'containers/app-container/app-container';
if (process.env.NODE_ENV === 'development') {
sourceMapSupport.install();
}
const app = express();
app.use(expressStaticGzip('./static/assets'));
app.get('*', (req, res, next) => {
const store = configureStore();
/**
* Load initial data into state
* match requested URL path to the component in routes
* check for 'fireInitialActions' method (found in the container components)
* and dispatch if it exists
*/
const routeComponentPromises = routes.reduce((accumulator, route) => {
if (matchPath(req.url, route) && route.component && route.component.fireInitialActions) {
accumulator.push(Promise.resolve(store.dispatch(route.component.fireInitialActions())));
}
return accumulator;
}, []);
Promise.all(routeComponentPromises)
.then(() => {
const context = {};
const markup = renderToString(
<Provider store={store}>
<StaticRouter location={req.url} context={context}>
<AppContainer />
</StaticRouter>
</Provider>
);
const initialData = store.getState();
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<script src='vendor.js' defer></script>
<script src='app.js' defer></script>
<script>window.__initialData__ = ${serialize(initialData)}</script>
</head>
<body>
<div id="root">${markup}</div>
</body>
</html>
`);
})
.catch(next);
});
app.listen(process.env.PORT || 3000, () => {
console.log('Server is listening');
});
有谁知道为什么会发生这种情况以及如何解决我的问题?
编辑:这是一个显示问题的视频 - https://d26dzxoao6i3hh.cloudfront.net/items/2z3y3f1x3N1D2e422W42/Screen%20Recording%202017-10-23%20at%2012.24%20pm.mov
【问题讨论】:
-
出于兴趣,假设您使用的是 react-router,它是什么版本?
-
@jthawme 我和它的版本 4
-
如果你在没有 JavaScript 的情况下运行它会发生什么?我认为发生的情况是您的服务器返回“找不到页面”,但是一旦 JS 启动,它就会加载正确的数据并重建 DOM。我假设您在 routeComponentPromises 中遇到问题。
-
@MaxGram 同样的事情,我已经剥离了整个事情,只是用快速服务器提供了一些基本的 HTML(没有路由或反应),它仍然试图调用
/json和/json/version -
我会尝试使用
app.get('/json/version', (req, res) => { res.send(204);})在服务器上禁用'/json/version,然后在浏览器中关闭JS 并在终端中重新运行整个监视控制台。如果“不喜欢”页面仍然是这种情况,我将开始调试服务器。第一步是检查<StaticRouter location={req.url} context={context}>中 req.url 中的所有内容
标签: javascript json node.js reactjs express