简体   繁体   English

使用 React Router 的服务器端渲染“浏览器历史需要一个 DOM”

[英]Server-side rendering with React Router "Browser history needs a DOM"

I've scanned through the inte.net for two days but I can't get the gist of implementing SSR with react-routes.我已经在 inte.net 上浏览了两天,但我无法理解使用 react-routes 实现 SSR 的要点。 It took me 5 days to somehow understand all this without the routes .没有路线的情况下,我花了 5 天时间才以某种方式理解所有这些。 But now I'm unable to understand further with using react-routes .但是现在我无法进一步理解使用react-routes Here's the necessary details-这是必要的细节-

server/server.js服务器/server.js

import express from 'express';
import fs from 'fs';
import path from 'path';

import React from 'react';
import ReactDOMServer from 'react-dom/server';
import {StaticRouter} from 'react-router-dom';

import App from '../src/App';

const PORT = process.env.PORT || 8080;

const app = express();

app.use(express.static(path.resolve('./build')))

app.get('*', (req, res) => {

    fs.readFile(path.resolve('./build/index.html'), 'utf-8', (err, data) => {

    if (err) {
      console.log(err);
      return res.status(500).send('Some error happened');
        }

        const context = {};
        const app = ReactDOMServer.renderToString(
            <StaticRouter location={req.url} context={context}>
                <App />
            </StaticRouter>
        )
        
    return res.send(
      data.replace(
        '<div id="root"></div>',
        `<div id="root">${app}</div>`
      )
    );
    });
    
});

app.listen(PORT, () => {
  console.log(`App launched on ${PORT}`);
});

server/index.js服务器/index.js

require('ignore-styles')

require('@babel/register')({
    ignore: [/(node_module)/],
    presets: ['@babel/preset-env', '@babel/preset-react']
})

require('./server')

src/App.js源代码/App.js

import React from "react";
import {BrowserRouter, Switch, Route, Link} from 'react-router-dom';
import "./App.css";

function App() {

  return (
    <BrowserRouter>
      <Switch>
        <Route path='/' exact component={() => <Link to='/about'>This is Home. Go to About.</Link>} />
        <Route path='/about' component={() => <Link to='/'>This is About. Go to Home.</Link>} />
      </Switch>
    </BrowserRouter>
  );
}

export default App;

src/index.js源代码/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.hydrate(<App />, document.getElementById('root'));

serviceWorker.unregister();

Remove the BrowserRouter from the App and put it in your index file.从应用程序中删除BrowserRouter并将其放入索引文件中。

index.js索引.js

ReactDOM.hydrate(
       <BrowserRouter>
          <App />
       </BrowserRouter>, 
   document.getElementById('root')
);

App.js应用程序.js

import React from "react";
import { Switch, Route, Link} from 'react-router-dom';
import "./App.css";

function App() {

  return (
      <Switch>
        <Route path='/' exact component={() => <Link to='/about'>This is Home. Go to About.</Link>} />
        <Route path='/about' component={() => <Link to='/'>This is About. Go to Home.</Link>} />
      </Switch>
  );
}

Since <App /> contains BrowserRouter and you're using it in the server.由于<App />包含BrowserRouter并且您在服务器中使用它。 BrowserRouter cannot be processed in the server since it requires DOM. BrowserRouter无法在服务器中处理,因为它需要 DOM。

Also, import your StaticRouter from react-router not react-router-dom .另外,从react-router而不是react-router-dom导入你的StaticRouter

You could check the docs here你可以在这里查看文档

import { StaticRouter } from 'react-router';

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM