CSR (Client Rendering) & SSR (Server Rendering) & NSR & ESR (Edge Rendering)
-
csr:
The rendering of the page content comes from the js script returned by the server and the execution of the data requested by ajax. The advent of CSR enables the separation of the front-end and back-end architectures. The essence of CSR is to take the HTML and ask the packaging tool to package the generated JS script, and then execute the script in rendering. Cons: Bad for SEO and long first render time
-
Ssr:
Page templates, data prefetching, and populating are done on the server side, and the full HTML content is returned to the browser on the server side. SSR essentially takes the original CSR initialization data and lets the server perform it, then calls renderToString to generate HTML text, and then executes the service to generate an initial static page. Disadvantages: will increase the overall complexity of the project, the server pressure
-
Nsr:
This is a rendering technique that is unique to Hybrid. To put it simply, HTML data is generated through Native rendering and cached in the client. In this way, for user access to a Hybrid WebView, the offline page template will be loaded from the offline package first, and then data will be requested through front-end Ajax/ or client capabilities to complete the display of the page
The benefits were obvious: we kept the server rendering on separate mobile devices and pre-loaded the pages with offline storage technology without any additional server stress.
-
Esr
Edge rendering is more radical. ESR leverages “edge computing” capabilities that have become popular in recent years.
Edge computing: it refers to an open platform integrating network, computing, storage, and application core capabilities to provide the nearest service on one side of the object or data source. Its applications are initiated on the edge, generating faster network service responses and meeting the industry’s basic needs in real-time business, application intelligence, security and privacy protection. Edge computing is between physical entities and industrial connections, or at the top of physical entities. Cloud computing, on the other hand, still has access to the history of edge computing.
ESR rendering leverages CDN capabilities. ESR will cache the static part of the page on THE CDN, so that when users visit the page, they can quickly return the static content to users. Meanwhile, IT also initiates a request for the dynamic part of the content on the CDN node. After the dynamic content is obtained, it continues to return the dynamic content to users in the way of stream
Manually build an SSR framework
homogeneous
Isometric: A set of react code that executes once on the server and once on the client. ReactDom. RenderToString does not handle the attrs attribute on the JSX when it converts the JSX to HTML text. ReactDom. Hydrate needs to be executed on the client side to take effect for events and properties
See the demo I wrote for a concrete example:
So how are isomorphisms? First, the server runs react to generate the HTML. Then, it inserts the packed index.js into the HTML and puts the index.js into the static directory. The index.js here says reactdom.hydrate re-renders.
-
Server render JSX -> HTML, generated using reactdom.renderToString
-
The client is running JSX -> HTML with reactdom.hydrate for client re-rendering
Here the client code is written in the client, packaged in webpack.client.js, and packaged in the SRC /public directory. The server-side code is written on the server, packaged in webpack.server.js, and packaged in the Build directory. Process: The server runs react to render the HTML -> send the HTML to the browser -> the browser loads the JS file -> the REACT code in js reexecutes -> the react code in JS takes over the page operation.
Route processing
The client uses BrowserRouter and the server uses StaticRouter. When the client executes the react-router, it can know the current URL of the browser. However, the server simply returns the HTML text generated by the StaticRouter. StaticRouter doesn’t know the current browser access path, so it needs the Node app to pass its context.request.path to StaticRouter and render the corresponding HTML text.
Hydrate & Dehydration & Global Context store
How do you introduce context Store in homogeneous projects
The main code is as follows:
import {
Store as GlobalStore,
useReduxHook as useGlobalReduxHook,
initStore,
} from ".. /store/global";
function GlobalProvider({ children }) {
const [state, dispatch] = useGlobalReduxHook();
return (
<GlobalStore.Provider value={{ state.dispatch}} >
{children}
</GlobalStore.Provider>
);
}
Copy the code
The server-side renderToString function does not perform component lifecycle functions. Therefore, the data generated during the client’s lifetime cannot be retrieved by the server. So what about asynchronous data server rendering?
Target: The server loads different asynchronous data based on the user access path.
LoadData (); loadData (); loadData (); So you can get the data and render it in the renderString
The main code is as follows:
// The component requests data asynchronously const Home = (props) = > { const { dispatch: globalDispatch, state: globalState } = useContext(GlobalStore); const { weatherMessage } = globalState; return <div /> } Home.loadData = (Store) = > { return serverAxios .get("/api/homedata") .then((response) = > { Store.weatherMessage = response.data.weatherMessage; }) .catch((err) = > { console.log("error", err); }); }; // The route execution component's asynchronous handler loadData import { matchRoutes } from "react-router-config"; router.get("/ (. *)".async (context, next) => { // Add data to store according to route path const promises = []; const matchedRoutes = matchRoutes(Routes, context.request.path); // Make the loadData method corresponding to all components in matchRoutes run once // Make the data load early for rendering. matchedRoutes.forEach((item) = > { if (item.route.loadData) { const promise = new Promise((resolve, reject) = > { returnitem.route .loadData(initStore) .then(resolve()) .catch(resolve()); }); promises.push(promise); }});Promise.all(promises).then(() = > { const ctx = { css: [],};const html = render(context.request, Routes, ctx); if (ctx.notFound) { context.response.status = 404; } // The Redirect component of staticRouter is called // CTX adds action, URL attributes if (ctx.action === "REPLACE") { context.response.redirect(301, ctx.url); } context.response.body = html; }); await next(); }); Copy the code
Although the server render executes loadData to get the data, but the client render, the initial store does not have the data, so how to ensure that the component on the client and server initial return render text is consistent? This requires injection and outlet operations.
Water injection: puts the server’s rendered data into the script window.context; water injection: takes the client’s initial store data from window.context
In addition, when the client executes the rendering, the component rendering is not returned by loadData executed by the server, because history.go, Link and other methods will not respond to the change of the route through the local BrowserRouter. The initial store obtained by the client operation is null. So you need the client in the lifecycle function to also perform the data request in rendering.
404 page authoring and 301 redirection
Add a NotFound attribute to the context object staticRouter on the 404 component server
When the Redirect component of the React-Router calls the staticRouter context object on the server adds an action property.
if (ctx.action === "REPLACE") {
context.response.redirect(301, ctx.url);
}
Copy the code
Style handling
The server cannot use style-loader, csS-loader. Because Windows don’t exist in nodeJs. Isomorphic-style-loader plugin is used in the isomorphic-style-loader plugin
Note:
- When configuring isomorphic-style-loader for webpack, you must use CommonJs module syntax and write esModule:false
- The plugin isomorphic-style-loader does not write CSS copywriting into HTML. It only generates className. So you need to import it manually
use: ['isomorphic-style-loader', {loader: 'css-loader'.options: {esModule: false}}]
Copy the code
The main code for style processing is as follows:
import styles from './style.css'
// staticContext is injected with the context property staticRouter
if(props.staticContext) {
props.staticContext.css.push(styles._getCss())
}
Copy the code
seo
Using the React-Helmet plugin, the: and is injected into the head
The main code is as follows:
// Write to the component:
<Helment>
<title />
<meta name="description" content="" />
</Helment>
/ / render time
const helmet = Helmet.renderStatic()
${helmet.title.toString()}
${helmet.meta.toString()}
Copy the code
React SSR setup code
Here is the code to implement the react SSR setup
- The use of SCSS
- For the notFound action property in the context, print the context