javascript - React Router v4(未找到页面)服务器端渲染

标签 javascript reactjs deployment react-router server-side-rendering

我花了两天多的时间寻找问题的解决方案,我真的需要你的帮助。

将示例部署到服务器并到达 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="app"和脚本 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"
  }
}

服务器.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' }
    ]
  }
}

在本地主机上一切正常。 我将非常感谢任何帮助。

最佳答案

从您的应用程序中删除 Router,因为您已将其添加到 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>
)

关于javascript - React Router v4(未找到页面)服务器端渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45409685/

相关文章:

reactjs - 为多级状态对象 react setState

ruby-on-rails - Ruby on Rails : Capistrano 3 deployment error

javascript - 使用 Range.insertNode() 动态添加图像到 DOM

javascript - 为什么我会收到此错误(Tailwind + Next.js)? HookwebpackError, CssSyntaxError

javascript - Chartjs - 两个 Y 轴刻度问题

javascript - 尽管其有效性,但未提供所需类型的变量

c++ - 部署的Qt应用程序QtWebEngineProcess无法加载Qt5Core.dll

python - 如何在 Heroku 中使用 Flask/Peewee?

javascript - jQuery slideToggle 和带有许多框的 cookie

javascript - 除了 Marionette 应用程序之外还可以进行登陆/身份验证