0

我花了兩天多的時間尋找解決我的問題,我真的需要你的幫助。React路由器v4(找不到頁面)服務器端渲染

當我將我的示例部署到服務器併到達頁面,如site.com/home和重新加載此頁面後,我得到錯誤:未找到請求的URL/在此服務器上找不到URL

在React Router文檔中,我發現爲了防止出現這個問題,我需要使用SSR,但每次嘗試使用這些代碼和其他代碼來解決此問題時,我都遇到了同樣的錯誤。

例子的代碼:https://reacttraining.com/react-router/

目錄地圖:

modules 
    - App.js 
node_modules 
public 
    - bundle.js 
    - index.css 
    - index.html 
index.js 
package.json 
package-lock.json 
server.bundle.js 
server.js 
webpack.config.js 
webpack.server.config.js 

App.js

import React from 'react' 
import { 
    BrowserRouter as Router, 
    Route, 
    Link 
} from 'react-router-dom' 

const App =() => (
    <Router> 
    <div> 
     <ul> 
     <li><Link to="/">Home</Link></li> 
     <li><Link to="/about">About</Link></li> 
     <li><Link to="/topics">Topics</Link></li> 
     </ul> 

     <hr/> 

     <Route exact path="/" component={Home}/> 
     <Route path="/about" component={About}/> 
     <Route path="/topics" component={Topics}/> 
    </div> 
    </Router> 
) 

const Home =() => (
    <div> 
    <h2>Home</h2> 
    </div> 
) 

const About =() => (
    <div> 
    <h2>About</h2> 
    </div> 
) 

const Topics = ({ match }) => (
    <div> 
    <h2>Topics</h2> 
    <ul> 
     <li> 
     <Link to={`${match.url}/rendering`}> 
      Rendering with React 
     </Link> 
     </li> 
     <li> 
     <Link to={`${match.url}/components`}> 
      Components 
     </Link> 
     </li> 
     <li> 
     <Link to={`${match.url}/props-v-state`}> 
      Props v. State 
     </Link> 
     </li> 
    </ul> 

    <Route path={`${match.url}/:topicId`} component={Topic}/> 
    <Route exact path={match.url} render={() => (
     <h3>Please select a topic.</h3> 
    )}/> 
    </div> 
) 

const Topic = ({ match }) => (
    <div> 
    <h3>{match.params.topicId}</h3> 
    </div> 
) 

export default App 

index.html的 - 與容器的id = 「應用程序」 和腳本SRC簡單的網頁= 「bundle.js」

index.js

import React from 'react' 
import ReactDOM from 'react-dom' 
import { BrowserRouter } from 'react-router-dom' 
import App from './modules/App' 

ReactDOM.render((
    <BrowserRouter> 
    <App/> 
    </BrowserRouter> 
), document.getElementById('app')) 

的package.json

{ 
    "name": "", 
    "version": "1.0.0", 
    "description": "", 
    "main": "index.js", 
    "scripts": { 
    "start": "if-env NODE_ENV=production && npm run start:prod || npm run start:dev", 
    "start:dev": "webpack-dev-server --inline --content-base public/ --history-api-fallback", 
    "start:prod": "npm run build && node server.bundle.js", 
    "build:client": "webpack", 
    "build:server": "webpack --config webpack.server.config.js", 
    "build": "npm run build:client && npm run build:server" 
    }, 
    "author": "", 
    "license": "ISC", 
    "dependencies": { 
    "compression": "^1.6.1", 
    "express": "^4.13.4", 
    "http": "0.0.0", 
    "if-env": "^1.0.0", 
    "react": "^0.14.7", 
    "react-dom": "^0.14.7", 
    "react-router": "^2.0.0", 
    "react-router-dom": "^4.1.2" 
    }, 
    "devDependencies": { 
    "babel-core": "^6.5.1", 
    "babel-loader": "^6.2.2", 
    "babel-preset-es2015": "^6.5.0", 
    "babel-preset-react": "^6.5.0", 
    "http-server": "^0.8.5", 
    "webpack": "^1.12.13", 
    "webpack-dev-server": "^1.14.1" 
    } 
} 

server.js

import { createServer } from 'http' 
import React from 'react' 
import ReactDOMServer from 'react-dom/server' 
import { StaticRouter } from 'react-router' 
import App from './modules/App' 

createServer((req, res) => { 
    const context = {} 

    const html = ReactDOMServer.renderToString(
    <StaticRouter 
     location={req.url} 
     context={context} 
    > 
     <App/> 
    </StaticRouter> 
) 

    if (context.url) { 
    res.writeHead(301, { 
     Location: context.url 
    }) 
    res.end() 
    } else { 
    res.write(` 
     <!doctype html> 
     <div id="app">${html}</div> 
    `) 
    res.end() 
    } 
}).listen(3000) 

webpack.config.js

var webpack = require('webpack') 
module.exports = { 
    entry: './index.js', 
    output: { 
    path: 'public', 
    filename: 'bundle.js', 
    publicPath: '/' 
    }, 
    plugins: process.env.NODE_ENV === 'production' ? [ 
    new webpack.optimize.DedupePlugin(), 
    new webpack.optimize.OccurrenceOrderPlugin(), 
    new webpack.optimize.UglifyJsPlugin() 
    ] : [], 
    module: { 
    loaders: [ 
     { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader?presets[]=es2015&presets[]=react' } 
    ] 
    } 
} 

webpack.server.config.js

var fs = require('fs') 
var path = require('path') 
module.exports = { 
    entry: path.resolve(__dirname, 'server.js'), 
    output: { 
    filename: 'server.bundle.js' 
    }, 
    target: 'node', 

    // keep node_module paths out of the bundle 
    externals: fs.readdirSync(path.resolve(__dirname, 'node_modules')).concat([ 
    'react-dom/server', 'react/addons', 
    ]).reduce(function (ext, mod) { 
    ext[mod] = 'commonjs ' + mod 
    return ext 
    }, {}), 

    node: { 
    __filename: true, 
    __dirname: true 
    }, 

    module: { 
    loaders: [ 
     { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader?presets[]=es2015&presets[]=react' } 
    ] 
    } 
} 

在本地主機上一切正常。 我將非常感謝任何幫助。

+0

你的'App'是BrowserRouter的組件。所以在你的serverjs中,你實際上是在StaticRouter中渲染BrowserRouter。嘗試並分開保存路由和路由器。檢查了這一點https://github.com/ReactTraining/react-router/tree/master/packages/react-router-config – Fawaz

回答

0

從您的應用程序中刪除路由器,因爲您已將其添加到BrowserRouter和StaticRouter。

const App =() => (
    <div> 
    <ul> 
     <li><Link to="/">Home</Link></li> 
     <li><Link to="/about">About</Link></li> 
     <li><Link to="/topics">Topics</Link></li> 
    </ul> 

    <hr/> 

    <Route exact path="/" component={Home}/> 
    <Route path="/about" component={About}/> 
    <Route path="/topics" component={Topics}/> 
    </div> 
) 
+0

你是對的,現在路由器工作正常,但「沒有fountd頁」的主要問題是關於託管:)託管應該是VPS(或VDN)服務器,在它們上運行Node.js(和server.js)。 –

+0

@ o.rula如果你在本地運行服務器,它工作正常嗎?你在尋找如何部署在服務器上? – Fawaz

+0

是的:)昨天我在部署中發現了這個問題。如果您能提供任何建議或指導,我會很高興。 –