React16.x中的服务端渲染(SSR)

简介:

简要介绍:为了SEO和加快首屏加载速度,React提供了服务端渲染(Server Side Render)。本文结合express,来介绍一下React16.x中的SSR。

本例代码:https://github.com/forthealllight/react16.0-ssr

一、为什么要SSR

单页应用将UI层和内容都由javascript来渲染,搜索引擎或网页爬虫需要完成的HTML结构,因此单页应用如果只在客户端渲染,不利于SEO,此外尽管我们可以通过按需加载的形式来减少首页加载的js,但是通过js来渲染DOM的时候还是会有一定的时间延迟。

因此SSR解决的问题有两个:

  • SEO

  • 加速首屏加载

在React和Vue等前端框架中,SSR的本质就是由服务端执行渲染,直接将渲染结果以HTML结构的形式返回给客户端。也就是将Virtual DOM转化成字符串的形式返回给客户端。

二、React15.x中的SSR

在React15.x中,有两个方法来处理SSR:

  • renderToString

  • renderToStaticMarkup

这两个方法都是在react-dom/server中提供的,用来在服务端将virtual dom渲染成字符串。

(1) 相同点

renderToString和renderToStaticMarkup都接受一个参数,这个参数是react的组件,返回一段HTML字符串。



renderToString(react element):string

renderToStaticMarkup(react element):string

此外react-dom中给浏览器端提供了一个render方法,render方法将react组件,添加到真实的DOM节点中。render实现的就是浏览器端渲染。

归类一下:

服务端渲染:renderToString、renderToStaticMarkup——>string 客户端渲染:render——>HTML结构

(2) SSR实现

下面我们以renderToString为例,通过express来实现一个服务端渲染的例子。

首先node最新版本为8.9.3,还不支持es6语法,同时为了使node支持jsx,我们需要安装babel,本文为了方便,采用了babel-cli。

首先安装babel-cli:



npm install -d babel-cli

接着安装presets:

npm install -d babel-preset-latest babel-preset-stage-0 babel-preset-react

接着我们在script中:

"start":"babel-node ./server/server.js --presets es2015,stage-0,react"

最后,就可以通过 npm run start的方式实现启动server.js,server.js是经过babel处理,可以支持ES6和jsx.

在server.js中,我们利用了express的路由和中间件模块。


let express=require('express');
let app=express();
import React from 'react';
import {renderToString,renderToStaticMarkup} from 'react-dom/server';
import HomePage from '../src/components/homepage/index.js';

var server=app.listen(8080,()=>{
  var host=server.address().address;
  var port=server.address().port;
  console.log('server is start at',host,port);
});
//static
app.use('/dist',express.static('dist'));

app.get('/',(req,res)=>{
  res.write('<!DOCTYPE html><html><head><title>Hello HomePage</title></head><body>');
  res.write('<div id="app">');
  res.write(renderToString(<HomePage/>));
  res.write('</div></body>');
  res.write('<script type="text/javascript" src="../dist/vendor.bundle.js"></script><script type="text/javascript" src="../dist/js/app.js"></script>');
  res.write('</html>');
})

结构很简单,因为返回的html页面要加载静态资源,因此我们在上述的代码中还使用了express内置的静态文件模块express.static.

最后,通过npm start就能启动本地服务器,在浏览器中打开:

http://localhost:8080/ 就能看到我们SSR的例子。

672a7c6fd4789e3b4823d4e83958c44a2d0ba820


(3) renderToString和renderToStaticMarkup的区别

  • renderToString:渲染的结果是带有data-reactid属性的,此时,在服务端的基础上,客户端的render不会重新渲染,只会执行组件componetDidmout中的业务,以及绑定事件等等。

  • renderToStaticMarkup:渲染的结果是不带有data-reactid属性的,此时不管服务端有没有渲染,在客户端中都会重新渲染该组件。

比如在renderToString的关于HomePage的返回HTML字符串结果为:



<h1 data-reactroot>Home Page</h1>

而在renderToStaticMarkup中,关于HomePage的返回HTML字符串结果为:

<h1>Home Page</h1>

三、React16.x中的SSR

(1) hydrate

在React16.x中,在客户端渲染的render的方法的基础上,增加了一个新的方法hydrate.

简单来说,如果在仅在客户端呈现内容,那么使用render方法就已经足够,如果客户端要在服务端的基础上进行渲染,那么可以使用hydrate. 使用的方法和render一样:



import {hydrate} from 'react-dom';
hydrate(<HomePage/>,document.getElementById('app'));

运行后发现提示:

Warning: render(): Calling ReactDOM.render() to hydrate server-rendered markup will stop working in React v17. Replace the ReactDOM.render() call with ReactDOM.hydrate() if you want React to attach to the server HTML.

说明React16.x中,客户端“水合”服务端,是兼容之前的render方法的,之后的版本中会移除render方法,完全用hydrate来代替。

hydrate方法,解决的是如何复用server端,ReactDOMServer的结果。

(2) stream

此外React16.x中,针对renderToString和renderToStaticMarkup提供了stream的方法:

  • renderToNodeStream
  • renderToStaticNodeStream

这两个方法同样接受的参数为react element,但是返回的不是HTML字符串,而是一个可读流。

最后给出完整代码的地址,直接npm start就可以运行:

https://github.com/forthealllight/react16.0-ssr

四、注意事项

如果不用babel-cli的方法,来babel node文件,用webpack的话可能会报一下错误:



RROR in ./node_modules/destroy/index.js
Module not found: Error: Can't resolve 'fs' in 'C:\Users\yuxl\Desktop\react-Scaffold-master\node_modules\destroy'
 @ ./node_modules/destroy/index.js 14:17-30
 @ ./node_modules/send/index.js
 @ ./node_modules/express/lib/response.js
 @ ./node_modules/express/lib/express.js
 @ ./node_modules/express/index.js
 @ ./src/server.js

ERROR in ./node_modules/etag/index.js
Module not found: Error: Can't resolve 'fs' in 'C:\Users\yuxl\Desktop\react-Scaffold-master\node_modules\etag'
 @ ./node_modules/etag/index.js 22:12-25
 @ ./node_modules/express/lib/utils.js
 @ ./node_modules/express/lib/application.js
 @ ./node_modules/express/lib/express.js
 @ ./node_modules/express/index.js
 @ ./src/server.js

ERROR in ./node_modules/express/lib/view.js
Module not found: Error: Can't resolve 'fs' in 'C:\Users\yuxl\Desktop\react-Scaffold-master\node_modules\express\lib'
 @ ./node_modules/express/lib/view.js 18:9-22
 @ ./node_modules/express/lib/application.js
 @ ./node_modules/express/lib/express.js
 @ ./node_modules/express/index.js
 @ ./src/server.js

ERROR in ./node_modules/send/index.js
Module not found: Error: Can't resolve 'fs' in 'C:\Users\yuxl\Desktop\react-Scaffold-master\node_modules\send'
 @ ./node_modules/send/index.js 23:9-22
 @ ./node_modules/express/lib/response.js
 @ ./node_modules/express/lib/express.js
 @ ./node_modules/express/index.js
 @ ./src/server.js

ERROR in ./node_modules/send/node_modules/mime/mime.js
Module not found: Error: Can't resolve 'fs' in 'C:\Users\yuxl\Desktop\react-Scaffold-master\node_modules\send\node_modules\mime'
 @ ./node_modules/send/node_modules/mime/mime.js 2:9-22
 @ ./node_modules/send/index.js
 @ ./node_modules/express/lib/response.js
 @ ./node_modules/express/lib/express.js
 @ ./node_modules/express/index.js


也就是webpack在打包的时候找不到 node自带的模块,比如fs等,解决的方法是在webpack的配置文件里面增加:


target:'node'


原文发布时间为:2018年07月02日
原文作者:yuxiaoliang
本文来源: 掘金    如需转载请联系原作者

相关文章
|
2月前
|
前端开发 应用服务中间件 数据库
react服务端组件
react服务端组件
21 0
|
编解码 前端开发 JavaScript
【长文慎入】一文吃透React SSR服务端同构渲染
前段时间一直在研究 react ssr技术,然后写了一个完整的 ssr开发骨架。今天写文,主要是把我的研究成果的精华内容整理落地,另外通过再次梳理希望发现更多优化的地方,也希望可以让更多的人少踩一些坑,让更多的人理解和掌握这个技术。 相信看过本文(前提是能对你的胃口,也能较好的消化吸收)你一定会对 react ssr服务端渲染技术有一个深入的理解,可以打造自己的脚手架,更可以用来改造自己的实际项目,当然这不仅限于 react ,其他框架都一样,毕竟原理都是相似的。
1205 0
|
10月前
|
数据采集 移动开发 前端开发
|
数据采集 JavaScript 前端开发
React与Vue服务端渲染(一)--Nuxt.js
React与Vue服务端渲染(一)--Nuxt.js
React与Vue服务端渲染(一)--Nuxt.js
|
数据采集 前端开发 JavaScript
一起了解基于React的服务端渲染&同构
一起了解基于React的服务端渲染&同构
|
数据采集 Web App开发 JavaScript
快速在你的vue/react应用中实现ssr(服务端渲染)
我们都知道, Vue和React是构建客户端应用程序的框架。默认情况下,可以在浏览器中输出自定义组件,进行生成 DOM 和操作 DOM, 也就是我们常说的客户端渲染, 并且我们大部分主流的场景都是SPA(单页面)应用, 而随着 SPA尤其是 React、Vue、Angular 为代表的前端框架的流行,越来越多的 Web App 使用的是客户端渲染。
296 0
|
JavaScript 前端开发
React 16 服务端渲染的新特性
React 16 服务端渲染的新特性 React 16 中关于服务端渲染的新特性 快速介绍React 16 服务端渲染的新特性,包括数组、性能、流等 React 16 终于来了!������ React 16 中有许多令人激动的新特性(最著名的是Fiber的重写),但是对我个人而言,最兴奋的还是React 16 对服务器端渲染所做的许多改进。
1139 0
|
Web App开发 JavaScript 前端开发
【redux】详解react/redux的服务端渲染:页面性能与SEO
  亟待解决的疑问 为什么服务端渲染首屏渲染快?(对比客户端首屏渲染)   react客户端渲染的一大痛点就是首屏渲染速度慢问题,因为react是一个单页面应用,大多数的资源需要在首次渲染前就加载好,这较大程度地拖慢了首屏渲染速度。
1489 0
|
前端开发
[译]React 在服务端渲染的实现
作者:牧云云 出处:http://www.cnblogs.com/MuYunyun/" 本文版权归作者和博客园所有,欢迎转载,转载请标明出处。 如果您觉得本篇博文对您有所收获,请点击右下角的 [推荐],谢谢!
877 0