前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >React16中的服务端渲染(译)

React16中的服务端渲染(译)

作者头像
IMWeb前端团队
发布2019-12-03 17:04:05
1.5K0
发布2019-12-03 17:04:05
举报
文章被收录于专栏:IMWeb前端团队IMWeb前端团队

本文作者:IMWeb zzbozheng 原文出处:IMWeb社区 未经同意,禁止转载

React 16发布了。 React 16有很多令人兴奋的新东西(尤其是Fiber),而且React 16对服务器端渲染所做了许多改进,让我们深入剖析React16的服务端渲染有什么不一样。

React 15 SSR是如何工作的

首先,我们先回顾一下React 15的服务端渲染,为了实现SSR,你可能会用nodejs框架(Express、Hapi、Koa)来启动一个web服务器,接着调用 renderToString 方法去渲染你的根组件成为字符串,最后你再输出到 response。

代码语言:javascript
复制
// using Express
import { renderToString } from "react-dom/server"
import MyPage from "./MyPage"
app.get("/", (req, res) => {
  res.write("<!DOCTYPE html><html><head><title>My Page</title></head><body>");
  res.write("<div id='content'>");  
  res.write(renderToString(<MyPage/>));
  res.write("</div></body></html>");
  res.end();
});

然后,在客户端bootstrap代码,再次使用render方法来生成HTML:

代码语言:javascript
复制
import { render } from "react-dom"
import MyPage from "./MyPage"
render(<MyPage/>, document.getElementById("content"));

讲道理,客启端渲染会使用服务端渲染好的HTML,而不是去更新DOM。

那么,服务端渲染在React 16会有不同呢?

React 16 向后兼容

React开发团队有强烈的意愿表示会向后兼容,如果你的代码能够在React 15中运行,那么也可以在React 16中运行,并且不会出现任何弃用警告,正如上面的代码,他可以很好地运行在React 15 和 React 16 中。如果你在App中使用React 16并且发现错误,请在这里提issue,这将会帮助核心团队修复React 16的各种错误。

render() 变为 hydrate() 当你将直出代码从React 15升级到React 16时,你有可能会在浏览器看到以下警告:

事实证明React 16现在有两种不同的客户端渲染方法:当您仅在客户端呈现内容时,使用render() 方法,如果你在服务端渲染结果之上再次渲染则使用hydrate()方法。因为React向后兼容,在React 16中,render()方法会继续可用于服务端渲染。但为了不出现警告信息你最好使用hydrate()方法来代替render():

代码语言:javascript
复制
import { hydrate } from "react-dom"
import MyPage from "./MyPage"
hydrate(<MyPage/>, document.getElementById("content"))

React 16可以处理数组、字符串和数值 在React 15中,,一个组件的render方法必须返回单一的React元素。在React 16, 客户端渲染和服务端渲染允许组件的render 方法返回字符串,数值或者是一个元素数组。

所以,你可以在服务端渲染中写类似以下的代码

代码语言:javascript
复制
class MyArrayComponent extends React.Component {
  render() {
    return [
      <div key="1">first element</div>, 
      <div key="2">second element</div>
    ];
  }
}
class MyStringComponent extends React.Component {
  render() {
    return "hey there";
  }
}
class MyNumberComponent extends React.Component {
  render() {
    return 2;
  }
}

您甚至可以将一个字符串,数字或一组组件传递给顶层的renderToString方法:

代码语言:javascript
复制
res.write(renderToString([
      <div key="1">first element</div>, 
      <div key="2">second element</div>
    ]));
// it’s not entirely clear why you would do this, but it works!
res.write(renderToString("hey there"));
res.write(renderToString(2));

这样你就可以不用为React组件添加div和span,从而使减少HTML的体积。

React16 会更快

说到性能,尽管我们对每一个地方都做到了最佳实践,但是生产环境中的React服务器端渲染依然很慢。在React 16中,跨多个不同版本的Node的服务器端呈现出现惊人的速度:

当将React 15与process.env进行比较时,节点4大约有2.4倍的改进,节点6的性能提升了3倍,而新的Node 8.4版本的增加了3.8倍。 如果您与React 15进行比较而不进行编译,则React 16在最新版本的Node中的SSR中有一个完整的数量级增益。

为什么React 16 SSR比React 15快得多? 在React 15中,服务器和客户端渲染路径或多或少是相同的代码。 这意味着维护虚拟DOM所需的数据结构都将在服务器呈现时进行设置,即使在对renderToString的调用返回时,vDOM也被丢弃。 这意味着在服务器渲染路径上有很多浪费的工作。

然而,在React 16中,核心团队从头开始重写了服务器渲染器,并且根本没有进行任何vDOM的工作。 这意味着它可以快得多。

我做的测试只是用一个非常简单的递归React组件生成一个span的巨型树,这是一个非常极端的基准,不一定能够反映出真实应用场景。

React 16 支持 Streaming

React 16现在支持直接渲染到节点流。渲染到流可以减少你的内容的第一个字节(TTFB)的时间,在文档的下一部分生成之前,将文档的开头至结尾发送到浏览器。 当内容从服务器流式传输时,浏览器将开始解析HTML文档。

渲染到流的另一个好处是能够响应背压。 实际上,这意味着如果网络被备份并且不能接受更多的字节,则渲染器会获得信号并暂停渲染,直到堵塞清除。 这意味着您的服务器使用更少的内存,并更加适应I / O条件,这两者都可以帮助您的服务器处于具有挑战性的条件。

要使用React 16的渲染流,您需要分别在对应于renderToStringrenderToStaticMarkup的react-dom / server:renderToNodeStreamrenderToStaticNodeStream上调用两个新方法其一。 这些新方法不是返回一个字符串,而是返回一个可读流,一个用于发送字节流的对象的Node Stream类。

当从renderTo(Static)NodeStream返回可读流时,它处于暂停模式,并且没有发生渲染。 只有当您调用read或更有可能将可读流导入到可写流中时,才能启动渲染。 大多数Node Web框架都有一个从Writable继承的响应对象,所以通常可以将Readable传递给响应。

代码语言:javascript
复制
// using Express
import { renderToNodeStream } from "react-dom/server"
import MyPage from "./MyPage"
app.get("/", (req, res) => {
  res.write("<!DOCTYPE html><html><head><title>My Page</title></head><body>");
  res.write("<div id='content'>"); 
  const stream = renderToNodeStream(<MyPage/>);
  stream.pipe(res, { end: false });
  stream.on('end', () => {
    res.write("</div></body></html>");
    res.end();
  });
});

请注意,当我们pipe到响应对象时,我们必须包含可选参数{end:false},以便在渲染器完成时不要自动结束响应。 一旦流完全写入到响应中,我们就可以完成HTML体,并结束响应。

原文: https://hackernoon.com/whats-new-with-server-side-rendering-in-react-16-9b0d78585d67

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-10-10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • React 15 SSR是如何工作的
    • 那么,服务端渲染在React 16会有不同呢?
      • React 16 向后兼容
        • React16 会更快
          • React 16 支持 Streaming
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档