The React server render
my github page: https://github.com/hfpp2012
SSR server side render Server rendering places the initial request of data on the server. After receiving the request, the server fills the data into the template to form a complete page, and the server returns the rendered complete page to the client.
The direct HTML output from the server enables the first screen to be displayed quickly and is beneficial to SEO. However, all pages need to be loaded to the server. If the traffic volume is large, it will put pressure on the server. In addition, the jump between pages and changes in the content of some pages will cause page refresh, which is not friendly enough.
CSR Client-Side Rendering. It is currently the mainstream rendering mode in Web applications. Generally, the Server returns the initial HTML content, and then JS loads the data asynchronously to complete the page rendering. The most popular development mode in client rendering mode is SPA (single-page application). In this mode, the server only returns the framework and js script resources of one page, but does not return specific data.>
The server needs to be requested only when it enters or refreshes for the first time. The jump between pages is completed by the JS script and the response is faster. However, since the server only returns the HTML of an empty node, the content of the page needs to wait until the JS script is loaded and executed. The first screen takes a long time and is not friendly to SEO.
Compared with client rendering SPA applications
When entering or refreshing a page for the first time, the server directly returns the page with content to the client, which greatly reduces the white screen time and is also convenient for SEO.
Compared with traditional SSR applications
Instead of redirecting to different pages, you need to refresh the browser once. Only the HTML is directly displayed on the server during the first visit, and the subsequent pages are redirected to CSR (client rendering).
How to use
For a React application, if you want to directly return the complete HTML after entering or refreshing the page for the first time, you need to convert the components to be rendered on the current page to HTML on the server, react provides corresponding methods for this purpose.
In addition to the renderToString method, Reeact also provides the ReactDom.renderToNodeStream method to return a readable stream that can output HTML strings.
Although the server has already published HTML that needs to be rendered, some event binding operations still need the client JS script to complete. If the client still runs ReactDOM. The render Method replaces all DOM elements under the container node when it is called for the first time. This is obviously not the result we want. Fortunately, React provides ReactDom.hydrate method.
Same as render(), but it is used to hydrate HTML content in the container rendered by ReactDOMServer. React attempts to bind an event listener to an existing tag.
During client-side rendering, the hydrate method compares whether the two-side rendering results are consistent. If the results are consistent, the server-side rendering results are retained. If the results are inconsistent, the client-side rendering results are used.
The route of the SPA application is completely controlled by the client. When the route is redirected to different paths, the JS script replaces the components to present different contents.
For React SSR applications, as long as the server can render the correct components when the user enters or refreshes the page for the first time, the subsequent route switching is completely controlled by the client JS script. react-router provides the StaticRouter component to match and render different components based on the current request path.
Sometimes you need to request data on the server and directly render HTML pages with data. However, because the client does not have this data, the rendered content is inconsistent with the server. How to “inject” The data requested by the server into the client?
The server can control the direct HTML content. In this case, you can insert a script into the direct HTML content. next.js is implemented in this way.
The server has written the data into the script tag, which can be directly used for rendering by the client.
If you only need SEO support, you can put all of them on the server and directly export different TDK data according to different page paths.
However, to ensure experience and improve maintainability, it is best to write TDK in page components. This requires that the server can obtain the TDK data of the current page during rendering and go straight out to HTML. The client can compare the TDK data during rendering and replace the TDK data of the old page with the TDK data of the new page for DOM operations.
react-helmet provides good support for this
Server example (Koa)
Currently, both next.js and egg-react-ssr package css code into a file and load it as a resource. In this way, the HTML result directly output by the server should contain the link tag of the css file, while the JS script on the client does not need to insert the link tag.
The client uses the mini-css-extract-plugin plug-in to extract css files. If you use on-demand loading, all css files need to be extracted as a single file.
Generally, static resource file names are loaded with hash values when packaging. To ensure that the server can obtain the correct path, you need to use the webpack-manifest-plugin plug-in to generate the mapping file of file names and paths, it is convenient for the server to obtain the correct path. If you use react-loadable for on-demand loading, you can use the react-loadable-ssr-addon plug-in to generate a mapping file.
ignore-loader can be used in webpack to ignore the processing of css files.
If css modularization is enabled, css-loader generates an identifier mapping, and the server also needs to generate an identifier to ensure consistent rendering results. The module.exportOnlyLocals option of css-loader provides the function of exporting only identifier mappings without checking in css.
For a large project, when we visit one of the pages, we only need to load the code of the current page, and then load the code of other pages. This can effectively reduce the size of js files that need to be loaded when accessing a page and improve the page response speed. To implement on-demand loading in a SPA application, you only need to use the dynamic import syntax. webpack supports this feature. Modules imported using the dynamic import syntax are packaged into a separate file.
- When the server renders a component, the component loaded on demand cannot be rendered into HTML.
- Even if the server can directly load the HTML of the component on demand, after the client takes over the asynchronous JS code, the intermediate state is displayed first (generally, the intermediate state is rendered and loaded first), in this way, the initial rendering results of the two ends are inconsistent.
- Now that server-side rendering is adopted, the HTML directly output during server-side rendering can finally contain the JS code that needs to be loaded asynchronously on the current page, that is, the script tag, without the need for dynamic creation by the client.
For the first point, the server does not need to load on demand, but should directly render the components loaded on demand;
Second, to ensure the consistency of the initial rendering results on both sides, the client should wait for the asynchronous JS code loaded on the current page to be downloaded before rendering;
Thirdly, to enable the HTML rendered by the server to contain the script of the JS code loaded on demand, you need to obtain the component name loaded on the current page and the mapping of the JS path name corresponding to the component name. Splice the script tags that are loaded on the current page when the HTML is directly exported.
react-loadable provides solutions to the above problems.
The on-demand components are wrapped by Loadable. The modules and webpack options indicate which module the component is loaded, so that the server can obtain the modules to be loaded based on the rendered components.
If you use the babel plug-in react-loadable/babel, you do not need to use the modules and webpack options.
Use the preloadReady method to wait until the script loaded on demand is loaded before rendering. The window.main method is called after the script that goes straight out of the server is loaded.
Generates a mapping between the loaded module and the bundles packaged by the webpack. The server can determine the scirpt that should be directly exported.
The rendered components for Loadable.Capture the package. It provides a callback report method to record the module names loaded on the current page. Based on the generated module mapping, you can obtain the packages of the webpack, the scirpt that needs to be loaded on the current page is directly displayed without dynamic creation by the client.
my github page: https://github.com/hfpp2012
Originally published at http://github.com.