详解超简单的react服务器渲染(ssr)入坑指南

本文是基于react ssr的入门教程,在实际项目中使用还需要做更多的配置和优化,比较适合第一次尝试react ssr的小伙伴们。技术涉及到 koa2 + react,案例使用create-react-app创建

SSR 介绍

Server Slide Rendering,缩写为 ssr 即服务器端渲染,这个要从SEO说起,目前react单页应用HTML代码是下面这样的

<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <link href="https://www.jb51.net/favicon.ico" /> <meta content="width=device-width, initial-scale=1, shrink-to-fit=no"/> <meta content="#000000" /> <title>React App</title> </head> <body> <noscript>You need to enable JavaScript to run this app.</noscript> <div></div> <script src="https://www.jb51.net/js/main.js"></script> </body> </html>

如果main.js 加载比较慢,会出现白屏一闪的现象。

传统的搜索引擎爬虫因为不能抓取JS生成后的内容,遇到单页web项目,抓取到的内容啥也没有。在SEO上会吃很多亏,很难排搜索引擎到前面去。

React SSR(react服务器渲染)正好解决了这2个问题。

React SSR介绍

这里通过一个例子来带大家入坑!先使用create-react-app创建一个react项目。因为要修改webpack,这里我们使用react-app-rewired启动项目。根目录创建一个server目录存放服务端代码,服务端代码我们这里使用koa2。目录结构如下:

这里先来看看react ssr是怎么工作的。

这个业务流程图比较清晰了,服务端只生成HTML代码,实际上前端会生成一份main.js提供给服务端的HTML使用。这就是react ssr的工作流程。有了这个图会更好的理解,如果这个业务没理解清楚,后面的估计很难理解。

react提供的SSR方法有两个renderToString 和 renderToStaticMarkup,区别如下:

renderToString 方法渲染的时候带有 data-reactid 属性. 在浏览器访问页面的时候,main.js能识别到HTML的内容,不会执行React.createElement二次创建DOM。

renderToStaticMarkup 则没有 data-reactid 属性,页面看上去干净点。在浏览器访问页面的时候,main.js不能识别到HTML内容,会执行main.js里面的React.createElement方法重新创建DOM。

实现流程

好了,我们都知道原理了,可以开始coding了,目录结构如下:

create-react-app 的demo我没动过,直接用这个做案例了,前端项目基本上就没改了,等会儿我们服务器端要使用这个模块。代码如下:

render() { return ( <div className="App"> <header className="App-header"> <img src=https://www.jb51.net/article/{logo} className="App-logo" alt="logo" /> <p> Edit <code>src/App.js</code> and save to reload. </p> <a className="App-link" href="https://reactjs.org" target="_blank" > Learn React </a> </header> </div> ); } } export default App;

在项目中新建server目录,用于存放服务端代码。为了简化,我这里只有2个文件,项目中我们用的ES6,所以还要配置下.babelrc

.babelrc 配置,因为要使用到ES6

{ "presets": [ "env", "react" ], "plugins": [ "transform-decorators-legacy", "transform-runtime", "react-hot-loader/babel", "add-module-exports", "transform-object-rest-spread", "transform-class-properties", [ "import", { "libraryName": "antd", "style": true } ] ] }

index.js 项目入口做一些预处理,使用asset-require-hook过滤掉一些类似 import logo from "./logo.svg"; 这样的资源代码。因为我们服务端只需要纯的HTML代码,不过滤掉会报错。这里的name,我们是去掉了hash值的

require("asset-require-hook")({ extensions: ["svg", "css", "less", "jpg", "png", "gif"], name: '/static/media/[name].[ext]' }); require("babel-core/register")(); require("babel-polyfill"); require("./app");

public/index.html html模版代码要做个调整,{{root}} 这个可以是任何可以替换的字符串,等下服务端会替换这段字符串。

<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <link href="https://www.jb51.net/%PUBLIC_URL%/favicon.ico" /> <meta content="width=device-width, initial-scale=1, shrink-to-fit=no"/> <meta content="#000000" /> <link href="https://www.jb51.net/%PUBLIC_URL%/manifest.json" /> <title>React App</title> </head> <body> <noscript>You need to enable JavaScript to run this app.</noscript> <div>{{root}}</div> </body> </html>

app.js 服务端渲染的主要代码,加载App.js,使用renderToString 生成html代码,去替换掉 index.html 中的 {{root}} 部分

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/08d27739329d66bbabfc944476126dab.html