Release React + KOA Rendering Service Rendering (SSR)

React is one of the most popular UI libraries at the front-end community. Its component-based development method greatly enhances the front-end development experience, React makes us by splitting a large application to a small component The code can be reused, as well as better maintainability, etc. There are still many advantages …

We usually develop a single page application (Spa ), Single-page applications have a better user experience than traditional webpages, and browsers generally get a body for empty HTML, then load the Script specified JS, and start execution after all JS is loaded JS, finally rendering to the DOM, in this process, general users can only wait, nothing can do, if the user is in a high-speed network, in the high-configured device, you must first load all JS and then execute The process may not be a big problem, but there are many situations that our network speed is general, and the equipment may not be the best. In this case, the single-page application may be a very poor user experience to the user, the user may I haven’t experienced the benefits of the browser side SPA, I have left the website, so that your website does not have too many browsing.

But we can’t return to the traditional development of a page of the previous page. Modern UI renders provide server rendering (SSR) features, making our development SPA applications can also Perfect running on the server, greatly speeding up the first screen rendering time, the user can see the content of the webpage faster, at the same time, the browser simultaneously loads JS, then load all DOM events And various interactions added to the page, and finally run in a spa, so we have improved the first-screen rendering time, and you can get the SPA client user experience. For SEO is also a must.

OK, we will roughly understand the necessity of SSR. Now we can implement server rendering in a react app, BTW, since we are already in one everywhere is async / await In the environment, the server here uses KOA2 to implement our server rendering.


Initializes a normal single page application spa


First we will first create a React and React, based on the server -Router’s spa, wait for us to create a complete SPA, join the SSR function to maximize the performance of the app.

First entered the App. App.js:

Import ReactDom from ‘React-Dom’; import {BrowserRrouter AS ROUTER, Route} from ‘React-Router-Dom’; const home = () =>
home

; const hello = () =>
Hello ; const app = () => {Return (
 )} ReactDom.render (
, Document.GtelementByid ('app'))
We are Routing / and / Hello created two components that only render some text to the page. But when our project is getting bigger and bigger, there are more and more components, and the JS we packaged will become great, even uncontrollable, so our first step needs to be optimized is code split (Code-splitting), fortunately, we can easily do this through WebPack Dynamic Import and React-Loadable. Use React-loadable Time code split
before use, first install
:


NPM INSTALL React-loadable # oryarn add react-loadingable

Then in your JavaScript:
// … Import loadable from ‘react-loadable’; // … const asynchello = Loadable …

, // Write your Hello components to separate files // then use WebPack’s Dynamic Import Loader: () => Import (‘./ Hello’ ),}) // then use loadable packaged components in your route:
 is very simple, we only need import  React- Loadable , then pass some Option to go in, where 
loading option is to render the Loading component when dynamically load the JS required to load the Hello component, give the user a feeling of loading, experience Will be better than anything.


Ok, now if we visited the home page, only the HOME component relies on JS will be loaded, and then click on a link to enter the Hello page, you will first render the load network, and simultaneously load The Hello component is dependent on JS, after loading, replacing the loading to render the Hello component. Our spa has greatly optimized by routing code code to different code blocks, and our Spa has greatly optimized, cheers & # 127867 ;. More 叼 的 is

React-LOAdable
also supports SSR, so you can use React-loadable
 anywhere, whether it is running on the front end or the server, let  React-loadable 
running normally on the server If we need to do some additional configurations, this article will talk, you are not anxious!
Here we have created a basic React Spa, plus code split, our app already has a good performance, but we can also optimize the performance of the app, Below we will further increase the loading speed by adding SSR's function, and will solve the SPA problem & # 127881;
Join the server rendering (SSR) function

First we build a simplest KOA web server:

NPM INSTALL KOA KOA-ROUTER Then in the entrance file app.js of KOA:
Const Koa = Require (‘Koa’); Const Router = Require (‘Koa-router’); const app = new koa (); const router = new router (); Router.get (‘*’, async (ctx) => {ctx.body = `

React SSR



`;}); app.use (router.routes ()); app.listen (3000, ‘0.0.0.0’);

 above  *  Routing Represents Arbitrary URLs come in We all default to rendering this HTML, including the JS packing in HTML, you can also use some server template engines (such as: Nunjucks) to directly render html files, package when WebPack By 
html-webpack-plugin is inserted into the packaged JS / CSS resource path.

OK, our simple KOA Server is good, then we start writing the entrance file of React SSR
AppsSr.js

, here we need to use StaticRouter to replace the previous
Browserrouter , because in the server, the route is static, if you don’t work with
 BrowserRouter , then do some configurations will make  React-loadable  run Server.     You can write the code of the entire Node end with the ES6 / JSX style, not some of the common JSX, but if you need to compile the code of the entire server with WebPack into a commonjs style, In order to make it run in the Node environment, let's take out the React SSR code separately, then go to the regquire in the normal Node code. Because it is possible in an existing project, it is a bit large, the previous Node code is turned to ES6, but it can be replaced in the later step   
OK, now in your appsr.js:
ImportReact from 'React'; // Using Static Static RouterImport {StaticRouter} from 'React-Router-Dom'; Import ReactDomServer from 'React-Dom / Server'; Import Loadable from 'React-loadable'; // This is what is needed. Let React-Loadable can run in the server, you will talk about import {getBundles} from 'React-loadable / WebPack'; import stats from '../build/reat-loadable.json'; // here React -router's routing set out, so that you can share it in the browser and the server will also talk ... Import approutes from 'src / approutes'; // We create a simple class, exposing some ways , Then call to the KOA router to implement the server rendering Class SSR {// Koa route to call this method RENDER (URL, DATA) {let modules = []; const context = {}; const html = reactDomserver.renderTostring ( Modules.push (ModulenAme)}>
); // Gets the server-side component array let bundles = getBundles (stats, modules); return {HTML Scripts: this.generateBundlescRipts (bundles),};} // transfers the SSR's Components into the Script tag thrown into the HTML generateBundlescripts (bundle => bundle.file.endswith ('. js')). Map (bundle => {return `
\ n`;});} static preloadAll () {returnidAple.preeloadall ();}} export default SSR;

When using this file, use Target: “Node”
and

Externals

in WebPack configuration, and in your WebPack configuration of your package front-end app, you need Add React-loadable plug-in, App Package needs to run before the SSR package, do not get the components required by React-loadable, first look at the App Package: // WebPack.config.dev.js, app bundleconst reactloadableplugin = Require (‘react-loadable / webpack’) .reatloadableplugin; module.exports = {// … plugins: [// … New ReactLoadablePlugin ({filename: ‘./build/react-loadable.json’,}),]}

is .bAddable Plugin in Abelrc:


{“Plugins”: [“Syntax-Dynamic-Import”, “React-loadable / Babel”, [“Import- Inspector, {“ServersideuequirePath”: true}]]}


The above configuration will make

React-loadable
know which components are ultimately at the server Rendered, then inserted into the HTML Script tab, and consider the components of the SSR when the front end is initialized, avoiding repeated loading, below SSR packaging:
     // WebPack.ssr.jsconst nodeExternals = Require ('WebPack-Node-Externals'); Module.Exports = {// ... Target: 'Node', Output: {Path: 'build / node' , FILENAME: 'SSR.JS', LIBRARYEXPORT: 'DEFAULT', LIBRARYTARGET: 'Commonjs2',}, // Avoid packing the library in Node_Modules, this SSR JS will run directly in the Node side, // does not need Pack in the final file, automatically load externals from Node_Modules when running, running,: [NodeExternals ()], //... } then in 
KOA App.js, Require it,And the method of calling SSR:

// … koa app.js // build out SSR.JSCONST SR = Require (‘./ build / Node / ssr ‘); // Preload All Components On Server Side, the server is not dynamically loaded, first load SSR.PRELOADALL (); // instantiate a SSR object const S = new SSR (); router. GET (‘*’, async (ctx) => {// According to the route, render different page components const rendred = s.render (ctx.URL); const html = `

$ {rendered.html}
   $ {rendered.scripts.join ()} 

`; CTX .BODY = HTML;}; // …

The above is a simple implementation of React SSR to KoA Web Server, in order to make
React-loadable I know which components are rendered in the server,
 Scripts  inside  Scripts 
array contains each SCRIPT label consisting of SSR over, called SSR # GenerateBundlescripts )
Method, it is necessary to ensure that these Script tags are after

runtime.js ((through COMMONSCHUNKPLUGIN
To draw it)))), and before app bundle (that is, when initialization, it should have been rendered by it). More

React-loadable
Server support, refer to here.
  We also pumped the Router of React-Router alone, so that it can run in the browser The server, the following is  approutes 
component:

// approutes.jsimport loadingable from ‘React-loadable’; // … Const asynchello = loading … , loader: () => import ('./ Hello'),} Function Approutes (PrOPS) {

} Export Default Approutes / / Then Import Approutes from ‘./approutes’ () => {Return (
 ) }    The initial state of the server rendering    
Therefore, we have created a React Spa, and Work together with the server side with the server; the community is called
universal app or isomophic App . But our current app is still aLeft remains, generally said that our App's data or status needs to get asynchronously through the far-end API. After getting data, we can start rendering components. The server SSR is also the same, we want to dynamically get the initial data, then throw it To make the react, then the initialization data when the browser should also initialize the initialization data when the SSR can be initialized, avoiding the browser side to initialize it again. Below we simply get some items from Github as the initialized data initialized, in KOA
app.js
:

// … const fetch = Require (‘isomorphic-fetch’); router.get (‘*’, async (ctx) => {// fetch branch info from github const api = ‘ https://api.github.com/repos/jasonboy/wechat-jssdk/branches’; const Data = AWAIT FETCH (API) .Then (res => res. json ()); // Incoming Initialization Data Const Rendred Series = S.Render (CTX.URL, DATA); const html = ` $ {rendered.html} Window .__ {JSON.STRINGY (DATA)} $ {rendered.scripts.join ()} `; ctx.body = html;});

Then in your

Hello components, you need : CheckWindow
(or uniform judgment in the app entry, then pass the PROPS to the subcomponent) There is

window .__ initial_data __,
If you use it directly as an initial data, if we are ComponentDidMount
 Go back to data in the life cycle function:  
Export default class hello extends React.com {Super (SUPER) PROPS); this.State = {// Here directly, if it is incorporated by the parent component, judge Github: window .__ initial_data__ || [],};} componentdidmount ()}; The method of requesting data // requesting data can also be taken so that the browser and server can be unified to avoid writing if (this.State.github.length res.,) ()) .Then ( Data => {this.setState ({GitHub: Data});});}} render () {Return ( {this.state.github.map (b => {return { B.Name} ;}}}}}
Ok, now if the page is rendered by the server, the browser will get all rendered. HTML, including initialization data, then loaded with the contents of these SSRs, and then constitute a complete SPA, just like a normal SPA, but we get better performance, better SEO & # 128526;
React-V16 update


In the latest version V16 of React, SSR’s API has made a lot of optimization, and provides new Based on the streaming API to better improve performance, through the streaming API, the server can send the front rendering HTML to the browser while the browser side can start rendering the page in advance instead of all components of the server. After completion, you can start the initialization of the browser side, enhance performance, also reduces the consumption of server resources. There is also a need to pay attention to the need to use

ReactDom. Hydrate ()

ReactDom.render (), more update reference Medium article Whats-New -with-server-side-rendering-in-react-16. & # 128150; To view complete demo, refer to KOA-WEB-KIT, KOA-WEB-KIT is a modern REACT / KOA-based intertwind, including React SSR support, can directly test server rendering features & # 128512;
Conclusion

Ok, the above is the simple practice of React-SSR + KOA. Through SSR, we have improved performance, and very good to meet the requirements of SEO, Best of the Both WORLDS & # 127866 ;.
English version

The above is all the content of this article, I hope to help everyone, I hope everyone will support Tumi Cloud.
                    
© Copyright Notice
THE END
Just support it if you like
like0
share
comment Grab the couch

Please log in to comment