ReactJS服务器端呈现与客户端呈现

时间:2014-12-04 09:25:39

标签: javascript node.js client-server reactjs

我刚刚开始研究ReactJS并发现它为您提供了两种呈现页面的方式:服务器端和客户端。但是,我无法理解如何一起使用它。它是构建应用程序的两种不同方式,还是可以一起使用?

如果我们可以一起使用它,怎么做 - 我们是否需要在服务器端和客户端复制相同的元素?或者,我们可以在服务器上构建应用程序的静态部分,以及客户端上的动态部分,而不与已经预呈现的服务器端建立任何连接吗?

4 个答案:

答案 0 :(得分:90)

对于给定的网站/网络应用程序,您可以使用客户端服务器端两者做出反应。

客户端

在这里,您在浏览器上完全运行ReactJS。这是最简单的设置,包括大多数示例(包括http://reactjs.org上的示例)。服务器呈现的初始HTML是占位符,一旦所有脚本加载,整个UI就会在浏览器中呈现。

服务器端

将ReactJS视为服务器端模板引擎(如jade,handlebars等......)。服务器呈现的HTML包含应该使用的UI,您不必等待加载任何脚本。您的页面可以被搜索引擎编入索引(如果没有执行任何javascript)。

由于UI是在服务器上呈现的,因此没有任何事件处理程序可以工作,并且没有交互性(您有一个静态页面)。

两个

这里,初始渲染在服务器上。因此,浏览器接收的HTML具有应有的UI。加载脚本后,将再次重新呈现虚拟DOM以设置组件的事件处理程序。

在这里,您需要确保使用您在服务器上呈现的相同props重新呈现完全相同的虚拟DOM(根ReactJS组件)。否则,ReactJS会抱怨服务器端和客户端虚拟DOM不匹配。

由于ReactJS在重新渲染之间区分虚拟DOM,因此真正的DOM不会发生变异。只有事件处理程序绑定到真正的DOM元素。

答案 1 :(得分:30)

图片来源:Walmart Labs Engineering Blog

SSR

CSR

注意: SSR (服务器端呈现), CSR (客户端呈现)。

主要区别在于SSR,服务器响应客户端浏览器,包括要呈现的页面的HTML。 同样重要的是要注意,尽管使用SSR,页面渲染速度更快。在下载JS文件并且浏览器已执行React之后,页面将无法进行用户交互。

一个缺点是SSR TTFB(第一个字节的时间)可能稍微长一些。可以理解的是,因为服务器需要一些时间来创建HTML文档,这反过来会增加服务器的响应大小。

答案 2 :(得分:3)

我实际上想知道相同的研究相当多,虽然你正在寻找的答案在评论中给出但我觉得它应该更加突出因此我写这篇文章(我会更新一次我可以提出一个更好的方法,因为我发现架构上的解决方案至少是有问题的。)

您需要用两种方式编写组件,因此基本上将if个开关放在任何地方,以确定您是在客户端还是服务器上然后执行数据库查询(或服务器上的任何适当的)或REST调用(在客户端上)。然后,您必须编写生成数据的端点并将其公开给客户端,然后就可以了。

再次,很高兴了解更清洁的解决方案。

答案 3 :(得分:1)

  

是构建应用程序的两种单独方法,还是可以一起使用?

它们可以一起使用。

  

如果我们可以一起使用它,怎么做-我们是否需要复制   服务器端和客户端的相同元素?或者,我们可以   在服务器上构建应用程序的静态部分,然后   客户端上的动态部件,无需与服务器建立任何连接   已经预渲染的一面?

最好渲染相同的布局,以避免重排和重画操作,减少闪烁/闪烁,页面会更平滑。但是,这不是一个限制。您可以很好地缓存SSR html(Electrode可以减少响应时间)/发送一个静态html,它会被CSR(客户端渲染)覆盖。

如果您只是从SSR开始,我建议您从简单开始,SSR很快就会变得非常复杂。在服务器上构建html意味着无法访问诸如窗口,文档之类的对象(您在客户端上拥有这些对象),无法合并异步操作(开箱即用),并且通常进行大量代码编辑以使您的代码与SSR兼容(因为您必须使用webpack打包bundle.js)。诸如CSS导入之类的要求vs导入之类的事情突然开始对您造成困扰(在没有webpack的默认React应用中情况并非如此)。

SSR的一般模式如下所示。 Express服务器可处理请求:

const app = Express();
const port = 8092;

// This is fired every time the server side receives a request
app.use(handleRender);
function handleRender(req, res) {
    const fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
    console.log('fullUrl: ', fullUrl);
    console.log('req.url: ', req.url);

    // Create a new Redux store instance
    const store = createStore(reducerFn);

    const urlToRender = req.url;
    // Render the component to a string
    const html = renderToString(
        <Provider store={store}>
            <StaticRouter location={urlToRender} context={{}}>
                {routes}
            </StaticRouter>
        </Provider>
    );
    const helmet = Helmet.renderStatic();

    // Grab the initial state from our Redux store
    const preloadedState = store.getState();

    // Send the rendered page back to the client
    res.send(renderFullPage(helmet, html, preloadedState));
}

我对从SSR开始的人们的建议是提供静态html。您可以通过运行CSR SPA应用程序获取静态html:

document.getElementById('root').innerHTML

别忘了,使用SSR的唯一原因应该是:

  1. SEO
  2. 更快的负载(我会打折)

Hack:https://medium.com/@gagan_goku/react-and-server-side-rendering-ssr-444d8c48abfc