Program source code
Pulled to run
yarn
npm run ssr
Gif preview effect
SSR: render on the server. The HTML of the first screen is directly returned to the client on the server
- SEO: let each crawler can climb to the first screen content, matching to search keywords, improve the ranking in Baidu Google
- Speed up the first screen instead of loading js and then
ReactDom.render('#app', Com)
Let the server share some of the rendering burden - See the reference documentation for details
Here comes the easy stuff
- How to achieve the first screen rendering SSR
- Combined with the Router
- Combined with the story
- How to load on demand
- How does the server handle CSS and images
How to achieve the first screen rendering SSR
- Express service to return HTML to the browser’s front screen
- HTML is a
react-dom/server
To provide therenderToString
React generates a virtual DOM, inserts HTML and returns it directly to the browser for rendering
import { renderToString } from "react-dom/server";
import { StaticRouter } from "react-router-dom";
const app = express();
app.get( "/ *", (req, res) => {
const context = {}; // A context object that can store information about rendering
const jsx = (
<StaticRouter context={ context } location={ req.url} >
<App />
</StaticRouter>
);
const reactDom = renderToString( jsx ); // Render JSX to HTML on the server
res.writeHead( 200, { "Content-Type": "text/html"}); res.end(` <! DOCTYPE html> <html> <head> <meta charset="UTF-8"> <link rel="icon" href="data:; base64,="> <title>React SSR</title> </head> <body> <div id="app">${ reactDom }</div> <script SRC ="/index.js"></script> Handle routing jumps and other Ajax requests </body> </ HTML > ');
});
app.listen(3000, () = > {console.log('Running on http://localhost:3000/');
});
Copy the code
const jsx = (
<Provider store={store}>
<Router>
<Layout />
</Router>
</Provider>
);
const app = document.getElementById( "app" );
ReactDOM.hydrate( jsx, app ); // After the client takes over the application, React will load the tags rendered by the server and will attempt to attach event listeners to the existing tags
Copy the code
Combined with the Router
- The server renders the corresponding component through the StaticRouter, matches the route based on the URL requested by the browser and returns the corresponding component
- After returning it to the browser, load the client JS wrapped by WebPack and take over the page
- See the code
Combined with the story
- The first screen usually requires the interface to render corresponding data
- Set the requested data to the status tree and return the JSON to the browser
<script> window.REDUX_DATA = ${ JSON.stringify( state ) } </script> Copy the code
- After the client takes over the application, it initializes the data into the client state tree
const store = createClientStore( window.REDUX_DATA ); const jsx = ( <Provider store={store}> <Router> <Layout /> </Router> </Provider> ); Copy the code
How to load on demand
- use
react-lodable
Load on demand, it works like thisimport().then()
Webpack can split the code after recognizing it - It will be generated
react-loadable.json
To identify components that need to be loaded dynamicallyconst jsx = ( <Provider store={store}> <Loadable.Capture report={moduleName= >Modules.push (moduleName)}> // The module that needs lazy loading is iterated in the returned HTML<StaticRouter context={ context } location={ req.url} > <Layout /> </StaticRouter> </Loadable.Capture> </Provider> ); ${bundles.map(bundle => { return `<script src="/${bundle.file}"></script>` // alternatively if you are using publicPath option in webpack config // you can use the publicPath value from bundle, e.g: // return `<script src="${bundle.publicPath}"></script>` }).join('\n')} Copy the code
- Lodable implementation principle
Lodable({ loader: (a)= > import(/* webpackChunkName: 'Hello' */'./Hello'), loading, }) class Lodable { componentWillMount() { this.cancelUpdate = false; const { loader } = this.props; loader.then(Com= > { this.Com = Com; if(!this.cancelUpdate) { thi.forceUpdate(); // Re-render after the initial lazy loading } }) } componentWillUnmount() { this.cancelUpdate = true; } render() { const { comProps } = this.props; return this.Com ? ( <this.Com.default {... comProps} /> ) : ( <this.Com {... comProps}/> ) } }Copy the code
How does the server handle CSS and images
- The server side still uses Webpack to compile the corresponding Node side code to realize the reference and processing of CSS and image resources
- In fact, we only need to understand that the client and the server are packaged separately. Finally, Node runs the JS of the server, returns HTML and loads the JS of the client, realizing that the client takes over the application
- Dealing with static resources and
webpack-isomorphic-tools
.universal-webpack
, the author of the former has not updated, I later found that it is actually much easier to use Webpack to deal with directly, may be the application scene is not usedconst serverConfig = { target: 'node'.// mark it as the node end mode: 'development'.entry: './src/server'.output: { filename: 'bundle.js'.path: path.resolve(__dirname, 'build')},externals: [nodeExternals()], // node_modules will not be packaged module: { rules: [{ test: /\.js? $/.loader: 'babel-loader'.exclude: /node_modules/.options: { cacheDirectory: true.plugins: ['transform-decorators-legacy'].presets: ["react"["env", { "targets": { "node": "current"}}]."stage-0"],}}, {test: /\.css? $/.use: ['isomorphic-style-loader', { // Process the LOADER on the CSS server loader: 'css-loader'.options: { importLoaders: 1.modules: true./ / open the CSS - module localIdentName: '[name]_[local]_[hash:base64:5]' // Name the generated class}}}, {test: /\.(png|jpeg|jpg|gif|svg)? $/.loader: 'url-loader'.options: { limit: 8000.outputPath: '.. /build/'.publicPath: '/'}}},plugins: [ new ReactLoadablePlugin({ filename: './build/react-loadable.json'.// Load configuration files on demand})]};Copy the code
Reference documentation
- Step by step, foundation
- Go a little deeper
- How much faster does SSR front screen make SPA
I’m going to do a
Combined with TS server render the whole network free listening SPA application (Jay Chou also has that kind)
- Home page, leaderboard, mine
- Crawl Jay Chou’s songs to mongoDB or save them in memory
- Combining Aplayer
- Associative spectrum
- Depending on the situation support search other artists and songs