create-react-app Server Side Rendering

2019-08-18 06:23发布

问题:

I am trying to achieve Server side rendering with my create-react-app project. I don't really need routes for now because it's a single-page application. I have been going through some articles but they seem to be quite complicated to me. Could someone guide me about how to do it or could link me to some simpler articles please?

Here is the code till now:-

The main app component, which imports other components:-

import React, { Component } from "react";
import HomePage from "./HomePage";
import "./App.css";

class App extends Component {

  render() {
    return(
      <div>
        <HomePage/>
      </div>
    );
  }
}

export default App;

The Express code till now:-

import express from "express";
import React from "react";
import { renderToString } from "react-dom/server";
import App from "../src/App";

const app = express();

app.use(express.static("../public"));

app.get('*', (req, res) => {
    res.send(`
        <!DOCTYPE html>
        <head>
            <title>Universal React</title>
        </head>
        <body>
            <div id="root">${renderToString(<App/>)}</div>
        </body>
        </html>
    `);
});

app.listen(3000, () => {
    console.log('Server running on PORT 3000');
})

All the articles or videos I have checked out till now use webpack and make changes to webpack.config.js file but I am using Create-react-app which comes with webpack included, there is no config file so I am a bit confused about how to make the required changes?

回答1:

You have to eject the project/scripts/webpack config

Here's an example article on how to implement server-side rendering with react-router/redux



回答2:

  1. Replace react-scripts with react-app-tools
  2. Update NPM scripts in package.json to call react-app build, react-app start
  3. Rename src/index.js to src/app.browser.js, add one more entry point for the server src/app.node.js

Directory Layout

.
├── /build/                     # Compiled output
│   ├── /public/                # Pre-compiled client-side app
│   └── server.js               # Pre-compiled Node.js app
├── /src/                       # Application source files
│   ├── /components/            # React.js components
│   │   ├── /App/               #   - The top-level React component
│   │   ├── /Button/            #   - Some other UI element
│   │   └── ...                 #   - etc.
│   ├── app.browser.js          # Client-side rendering, e.g. ReactDOM.render(<App />, container)
│   ├── app.node.js             # Server-side rendering, e.g. ReactDOMServer.renderToString(<App />)
│   └── server.js               # Server-side entiry point, e.g. app.listen(process.env.PORT)
└── package.json                # List of project dependencies and NPM scripts

src/app.browser.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';

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

src/app.node.js

import path from 'path';
import express from 'express';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import App from './components/App';

const app = express();

app.use(express.static(path.join(__dirname, 'public')));

app.get('*', (req, res) => {
  res.send(ReactDOMServer.renderToString(<App />));
});

export default app;

package.json

{
  "dependencies": {
    "express": "^4.6.12",
    "react": "^16.2.0",
    "react-dom": "^16.2.0"
  },
  {
    "react-app-tools": "^2.0.0-beta.5"
  },
  "scripts": {
    "test": "react-app test --env=jsdom",
    "build": "react-app build",
    "start": "react-app start"
  }
}

More info: https://github.com/kriasoft/react-app