Server rendering introduction:
Advantages:
1. Better SEO, conducive to search engines to capture page information.
2. Speed up the first screen rendering.
There are two cases of general use:
1. Request the interface to return HTML, and the server will render a single page and return it to the front end.
2. Front-end projects are placed in the Node environment to render and run, which is equivalent to developing projects in Node.
The preparatory work
Create a project:
Don’t use TS to get rid of –typescript
npx create-react-app ssr-demo --typescript
Copy the code
Create node code backbone:
Create two JS files
App.js is used to store the main Node code, and new start.js and. Babelrc are used to configure Babel.
Since Node does not support ES6, React, etc., we need to introduce Babel:
npm i babel-cli babel-preset-env babel-preset-react babel-preset-stage-0
Copy the code
start.js
require('babel-polyfill');
require('babel-register');
require('./server/app.js');
Copy the code
.babelrc
{
"presets": [
"env"."stage-0"."react",]}Copy the code
app.js
// import express from 'express';
const express = require('express');
const app = express();
const config = {
port: 8000,
}
app.get('/', (req, res) => {
res.send('hello~! ');
})
app.listen(config.port, () => {
console.log('Boot: 127.0.0.1:${config.port}`);
})
Copy the code
Configure node hot update:
Hot updates to Node require the installation of two plug-ins:
Cross-env: configures environment variables across platforms
Nodemon: Hot update of a node
npm i cross-env nodemon
Copy the code
Add the following statement to the package.json file.
The entire development environment is now configured.
Interface returns HTML
Try to return the full HTML to the front end and change the code in app.js to:
const express = require('express');
const fs = require('fs');
const app = express();
const config = {
port: 8000,
}
app.get('/', (req, res) => {
// res.send('hello~!! ');
var index = fs.readFileSync('./public/index.html');
var html = index.toString();
res.send(html);
})
app.listen(config.port, () => {
console.log('Boot: 127.0.0.1:${config.port}`);
})
Copy the code
Public index. HTML
Run NPM run hot to see the result:
React component rendering
Here comes the most important part! Create a folder compontents in the server directory and create the demo.js file inside:
Create component demo in demo.js:
import React from 'react';
class Demo extends React.Component {
constructor(props) {
super(props);
this.state = {
mytext: 'the default 1'
}
this.change = this.change.bind(this);
}
change(e) {
this.setState({
mytext: e.target.value
})
}
render() {
return (
<div className="App">
<h2>{this.state.mytext}</h2>
<input value={this.state.mytext} onChange={this.change}></input>
</div>)}}export default Demo;
Copy the code
Introduce use in app.js
React and react-dom/server
const express = require('express');
const fs = require('fs');
const app = express();
const config = {
port: 8000,}import React from 'react';
import ReactDOMServer from 'react-dom/server';
import Demo from './compontents/demo';
app.get('/', (req, res) => {
var index = fs.readFileSync('./public/index.html');
// renderToString, renderToStaticMarkup
var demo = ReactDOMServer.renderToString(<Demo />); var html = index.toString().replace('hello~! ', demo); res.send(html); }) app. Listen (config. The port () = > {the console. The log (` start: 127.0.0.1: ${config. The port} `); })Copy the code
The results:
The component has been rendered.
Focus on renderToString and renderToStaticMarkup
RenderToString: Render with either data-reactid or data-reactroot properties. (Data-reactid is displayed when parameters are passed between components, data-reactroot is displayed when no parameters are passed)
RenderToStaticMarkup: There is no data-reactid/data-reactroot attribute, pure HTML, can save a little traffic.
What does data-reactid/data-reactroot do?
React recognizes data-reactid in the client and does not render front-end code overwrites. If there is no data-reactid front-end, it ignores server elements and overwrites them.
Binding approach
It is clear that the Demo component has a binding change event to change the mytext parameter, but how to input no effect, because the server rendered just pure HTML, just for display.
How to bind methods, events, and styles?
This is why you put the Node code in create-react-app.
Copy the component of the server to the SRC directory.
There is the isomorphism principle, so the development must ensure that the server components and front-end components are consistent (server component === SRC component).
Modify the App. The TSX
import React from '.. /node_modules/@types/react';
import './App.css';
import Demo from './compontents/demo';
const App: React.FC = (a)= > {
return (
<div>
<Demo/>
</div>
);
}
export default App;
Copy the code
NPM start
Running React on the client side has styles and events, but the HTML available to the client is first loaded without rendering the component content.
The first load renders the component, and the code above has been implemented, now it is time to introduce the style and associated JS:
npm run build
Copy the code
Modify app.js in the server
const express = require('express');
const fs = require('fs');
const app = express();
const config = {
port: 8000,
}
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import Demo from './compontents/demo';
app.get('/', (req, res) => {var index = fs.readfilesync ('./build/index.html');
var demo = ReactDOMServer.renderToString(<Demo />);
var html = index.toString().replace('hello~! ', demo); res.send(html); }) app. Listen (config. The port () = > {the console. The log (` start: 127.0.0.1:${config.port}`);
})
Copy the code
App.use (‘/’, express.static(‘./build’))
app.js
const express = require('express');
const fs = require('fs');
const app = express();
const config = {
port: 8000,
}
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import Demo from './compontents/demo';
app.get('/', (req, res) => {
var index = fs.readFileSync('./build/index.html');
var demo = ReactDOMServer.renderToString(<Demo />);
var html = index.toString().replace('hello~! ', demo);
res.send(html);
})
app.use('/', express.static('./build')); App.listen (config.port, () => {console.log(' boot: 127.0.0.1:${config.port}`);
})
Copy the code
You can see that the Demo component already exists in HTML when first rendered, and that the styles and events are normal:
At this point, the entire server rendering is complete