React路由器服务器端无法正常工作

我有我的应用程序代码在这里: https : //github.com/WebTerminator/aldemar/commits/master

我试图让我的反应的应用程序在服务器端工作,在这个阶段,它的工作部分。

我遇到的问题是(山姆问题发生在本地)

如果我在浏览器中浏览它一切正常,当我刷新此URL https://aldemar-productions.herokuapp.com/projects/margam2我得到一个控制台错误,如:

bundle.js:1未捕获的SyntaxError:意外的标记< 在这里输入图像说明

如果我刷新其他url,如“ https://aldemar-productions.herokuapp.com/projects ”或“ https://aldemar-productions.herokuapp.com/about ”,他们工作正常。

server.js

import express from 'express'; import path from 'path'; import React from 'react'; import { renderToString } from 'react-dom/server'; import { match, RouterContext } from 'react-router'; import routes from './src/client/app/config/routes.jsx'; let port = process.env.PORT || 8080; let app = express(); app.use(express.static('src/client/')); // app.get('/', (req, res) => { // res.sendFile(path.resolve(__dirname + '/src/client/index.html')) // }); app.get('*', (req, res) => { match( { routes, location: req.url }, (err, redirectLocation, renderProps) => { // in case of error display the error message if (err) { return res.status(500).send(err.message); } // in case of redirect propagate the redirect to the browser if (redirectLocation) { return res.redirect(302, redirectLocation.pathname + redirectLocation.search); } // generate the React markup for the current route let markup; if (renderProps) { // if the current route matched we have renderProps markup = renderToString(<RouterContext {...renderProps}/>); } // else { // // otherwise we can render a 404 page // markup = renderToString(<NotFoundPage/>); // res.status(404); // } // render the index template with the embedded React markup return res.sendFile('index.html', {root : __dirname + '/src/client/'}); } ); }); app.listen(port); console.log('server started'); 

routes.jsx

 import React from 'react'; import { Route, Router, browserHistory } from 'react-router'; import ReactDOM from 'react-dom'; import Wrapper from './../components/wrapper.jsx'; import Home from './../components/home.jsx'; import Projects from './../components/projects.jsx'; import SingleProject from './../components/projectContent/singleProject.jsx'; import About from './../components/aboutUs.jsx' if(typeof window !== 'undefined') { console.log('here baby'); ReactDOM.render(( <Router history={browserHistory} > <Route component={Wrapper} > <Route path="/" component={Home} /> <Route path="projects" component={Projects} /> <Route path="projects/:id" component={SingleProject} /> <Route path="about" component={About} /> </Route> </Router> ), document.getElementById('app')); } 

singleProject.jsx(我从URL获取ID参数加载特定的数据)

 import React from 'react'; import Video from './../video.jsx'; import Overview from './overview.jsx'; import Photography from './photography.jsx'; import Details from './details.jsx'; import Cast from './cast.jsx'; import porgectsCollection from './../../data/projectInfo.js'; import { StickyContainer, Sticky } from 'react-sticky'; class Nav extends React.Component { constructor(props) { super(props); this.state = { mobileMenu: false }; } showMobileMenu () { this.setState({ mobileMenu: !this.state.mobileMenu }); } render () { let links = this.props.project.links.map(function(el, i){ return <li key={i}>{el}</li>; }); const open = this.state.mobileMenu ? ' open' : ''; return ( <Sticky stickyClassName="sticky-nav" topOffset={-100}> <span onClick={this.showMobileMenu.bind(this)} className="mobile-trigger">X</span> <nav className={"secondary-nav" + open}> <ul> {links} </ul> </nav> </Sticky> ); } } class SingleProject extends React.Component { getProjectDataFromUrl() { return **porgectsCollection.filter(el => el.title === this.props.params.id)**; } render () { let data = this.getProjectDataFromUrl(), project = data[0]; return ( <section className="project-page"> <StickyContainer> <Video project={project} /> <Nav project={project} /> <Overview project={project} /> <Photography project={project} /> <Details project={project} /> <Cast project={project} /> </StickyContainer> </section> ); } } export default SingleProject; 

当我点击这样的url“ https://aldemar-productions.herokuapp.com/projects/margam2 ”时,我按照我的路线收集“margam2”:

 <Route path="projects/:id" component={SingleProject} /> 

并根据该参数加载特定的数据。 我相信这个问题是在做服务器端渲染。

UPDATE-1

在我的index.html的头部添加这个可以让我刷新页面时显示的内容,但CSS丢失:

 <base href="/" /> 

可以通过http:// localhost:8080 / css / style.css完全访问css ,但是当我刷新“ http:// localhost:8080 / projects / margam2 ”时,显示的内容不是css。

好了两天的研究,这帮助了我:

 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> **<base href="/" />** <link rel="stylesheet" href="./css/foundation.min.css"> <link href="https://fonts.googleapis.com/css?family=Montserrat:400,700" rel="stylesheet"> <link rel="stylesheet" href="./css/font-awesome.min.css"> <link rel="stylesheet" href="./css/style.css"> <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick.min.css" /> <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick-theme.min.css" /> </head> <body> <div id="app"></div> <script src="./public/bundle.js" type="text/javascript"></script> </body> </html> 

不过我也在控制台里发现了这个:

browser.js:49警告:自动设置基本名称已被弃用,将在下一个主要版本中删除。 与basename的语义有细微的差别。 请将选项中的basename明确地传递给createHistory

所以需要为此find一个解决scheme。

更新1

我认为更好的解决scheme。 我已经改变了相对于绝对的资产pathforms:

请参阅每个本地资产前面的“/”

 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <link rel="stylesheet" href="/css/foundation.min.css"> <link href="https://fonts.googleapis.com/css?family=Montserrat:400,700" rel="stylesheet"> <link rel="stylesheet" href="/css/font-awesome.min.css"> <link rel="stylesheet" href="/css/style.css"> <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick.min.css" /> <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick-theme.min.css" /> </head> <body> <div id="app"></div> <script src="/public/bundle.js" type="text/javascript"></script> </body> </html> 

在你的项目页面上,你正在使用一个内联的div,像这样:

<div id="app" />

在所有其他页面中,您正在使用空格

<div id="app" > </div>

这是正确的做法。

React-Router不会重新渲染你的页面,而只是将你的反应代码“重新添加”到你的id =“app”中
这就是为什么当你打开点击它的作品,当你刷新它打破了。