Because of the needs of the web SEO,

has to transform the previous React project into a server - side rendering. After a survey and research, a large number of Internet data have been consulted. Trample the pit successfully.

: the realization of server selection ideas rendering, want to use the latest version of React, and does not change the existing way and, if you start to write directly to the server-side rendering, proposed

project with NEXT address: https://github.com/wlx200510/react_koa_ssr

scaffold selection: webpack3.11.0 + react Router4 + Redux + koa2 + React16 + Node8.x

main experience: knowledge of React's more familiar, successfully expand their technical field, the server technology has accumulated

in the actual project note: before using the framework to confirm the current version of webpack for 3.x Node is above 8.x, the reader is best to use React in the above for 3 months, and have practical experience in React project

project directory introduction < / Strong>

 - assets, index.css - had placed some global resources / file can be JS - config, had had pictures of webpack.config.dev.js development environment webpack package, set webpack.config.prod.js production environment webpack package package.json README.md had just set up just server server end to render the file, if not very understanding, suggestions [koa tutorial] (http://wlxadyl.cn/2018/02/11/koa-learn/), app.js, clientRouter.js had had this / / file contains the service end route is matched to the react routing logic, ignore.js, index.js had - SRC app - just under this folder is mainly used for placing the browser and server, configureStore.j had universal logic S //redux-thunk / createApp.js / / -- had set according to different rendering environment to set different patterns of router - index.js / router had / index.js / routes.js / Song - / routing configuration file! Important - assets / CSS had just placed some public style files had _base.scss / / we carry out many projects will be used to initialize the CSS / index.scss / / / / Song - - my.scss / img - components - had placed some common components of just FloatDownloadBtn common components, we carry out just FloatDownloadBtn.js writing sample we carry out FloatDownloadBtn.scss,, just index.js, Loading.js, Model.js had functional components of favicon.ico had just written index.ejs / / rendering template if the project needs, you can put some public documents in just index.js / / include logic just hot update pages page component / folder Just home we carry out just components / / for placing page components, the main logic, we carry out - homePage.js / / containers / / -- just use connect to encapsulate a high order component into the global state data, we carry out - homeContainer.js / / index.js / / page / song: routing configuration file thunk attribute,, attention: reducer we carry out - index.js / / reducer page here exposed to store for processing, user, pay attention to writing had components - userPage.js / / / containers / / / Song - - userContainer.js / index.js - - store - actions / action had the storage of home.js, thunk.js had just- The name of action - constants.js / / reducers pool to prevent the same name - index.js / reference of each page, all reducer 

  1. in the construction of local development using webpack-dev-server combine

to unify the project, realize the basic process with the previous hot update, react development is similar to the browser rendering, therefore in the preparation of the code when considering a set of logic, two rendering environment problems. After

  • 's current end page rendering is completed, its Router jump will not request the server side, so as to alleviate the server side pressure, so that the way of page entry is also two, and we need to consider the problem of routing isomorphism in two rendering environments.
  • production environment should use koa to do the back-end server, realize on-demand loading, get data at the server side, and render the entire HTML, and use the latest React16 capabilities to merge the whole state tree, and achieve server side rendering.
  • introduced the local development view local development mainly refers to the file is the SRC directory of the index.js file, judge the current operating environment, the use of module.hot API only in the development environment, to achieve when the reducer changes the page rendering update notification, note that the hydrate method, which is a specialized added to the server and render the API version of the V16 method, it realizes the maximum possible reuse for server-side rendering content based on the render method, the static DOM to dynamic process NODES. The essence is to replace the checksum markup process in the V15 version, making the process of reuse more efficient and elegant.

     const renderApp= (=>); let application=createApp {({store, history}); hydrate (application, document.getElementById ('root'));} = (window.main) => Loadable.preloadReady (.Then) {((=>));} ({renderApp});; if (process.env.NODE_ENV==='development') {if {module.hot.accept (module.hot) ('./store/reducers/index.js') (=> newReducer=require ('./store/reducers/index.js') {let}; store.replaceReducer (newReducer) module.hot.accept ('./app/index.js'), (=>); {createApp}=require {let ('./app/index.js'); let newReducer=require ('./store/reducers/index.js'); store.replaceReducer (newReducer) let application=createApp ({store, history}); hydrate (application, document.getElementById ('root'));} note that the wind 

    }

    }) The definition of ow.main function, this function is combined with index.ejs can know all scripts are loaded only after the trigger, which is used for writing react-loadable, lazy loading the page on the page were packaged to explain the combination of written routing settings, there is a general impression. It's important to note that the three methods exposed under app are browser and server side. Next is the idea of this part.

    routing process then look at the following src/app file directory, index.js exposes three methods, these three methods involved will be used in the server and browser development, this part is mainly about the router file inside the code idea and process the createApp.js file on the route, is here the key point to realize the mutual open ends of routing. Routes.js in the

    router folder is the routing configuration file, which brings all the routing configurations under the page into a configuration array, which can control the page's upper and lower line flexibly. The index.js in the same directory is the standard way of RouterV4. The routing configuration is passed by traversing the configuration array. ConnectRouter is a component used to merge Router. It is noticed that history needs to be imported as a parameter and needs to be processed separately in createApp.js file. First look a few configuration items in the Route component, it is worth noting that the thunk attribute, which is achieved after obtaining data back rendering a key step is the attribute of a software component similar to Next inside to get ahead of the life cycle of the hook data, the remaining properties can be found in in the >React-router document, and not repeat them here.

     import routesConfig from'./routes'; const Routers= ({history}) => (< ConnectedRouter; history={history}> < div> routesConfig.map ({route=> (< Route; key={route.path} exact={route.exact} path={route.path} component={route.component} thunk={route.thunk} />})) < /div> < /ConnectedRouter> export default Routers; 

    ) to view the app directory createApp.js inside the code can be found, this framework is based on different work environment is different, only in the production environment before using the Loadable.Capture method to realize the lazy loading, dynamic page corresponding to the introduction of different package after the JS file. Here's a look at the route configuration file in the component, with the example of index.js under the home page. Note webpackChunkName: / *'Home'* / this string of characters, is the essence of the package after this page corresponding JS file name specified, so according to different pages, this note also need to be modified, avoid packaged together. The configuration item of loading will only take effect in the development environment. If the page load is not completed, it is shown that the actual project development can be deleted if there is no need.

     import {homeThunk} from'../../store/actions/thunk'; const LoadableHome = Loadable (loader: (=>) {import (webpackChunkName:;'Home', loading: / */'./containers/homeContainer.js') Loading, HomeRouter = {const}); path: exact: true, component:', LoadableHome thunk:, homeThunk / / server rendering will open and execute the action, used to obtain the required data page rendering export default HomeRouter

    } here to say one more thing, get the parameters from the window.location inside the code sometimes we want to transform the project page file, into server-side rendering should be removed, or is to be used in the render after the life cycle. And the page level components have been injected with the relevant routing information, which can be used to get the parameters in the URL through this.props.location. BrowserRouter is used in this project. If HashRouter is used, the parameters may be slightly different and are used according to the actual situation. According to the

    React16 server API

      rendering:

    1. browser used into ConnectedRouter history: import createHistory from'history/createBrowserHistory'
    2. server using history for some basic knowledge of import createHistory from'history/createMemoryHistory'

    server-side rendering here will not involve koa2, if the koa2 framework can not familiar with refer to my another blog. Here is the code that looks at the server side under the server folder. First, a simple app.js is used to ensure that each connection returns a new server - side instance, which is a key idea for a single thread JS language. The key point to introduce is the clientRouter.js file. Combined with /src/app/configureStore.js, this document understands the data acquisition process of the server side rendering and the rendering mechanism of React.

     /*configureStore.js*/ import {createStore, applyMiddleware, compose} from "Redux"; import thunkMiddleware thunkMiddleware ""; "


    This concludes the body part