react 服务器端渲染_使用PHP的服务器端React –第2部分

news/2024/7/10 2:42:54 标签: java, python, php, javascript, vue
react 服务器端渲染

react 服务器端渲染

Part 1 ended with todos. The first one was to couple the server-side generated code with the client-side React, so that any updates past the initial page load will be handled by React's client JS, which is where React shines. Let's see how you can do just that.

第1部分以待办事项结尾。 第一个是将服务器端生成的代码与客户端React耦合,以便超过初始页面加载的任何更新都将由React的客户端JS处理,这是React的亮点。 让我们看看如何做到这一点。

PHP数据获取,将JS for v8粘合 (PHP data fetch, gluing JS for v8)

This part is the same as before, pasting here with no additional comments. The point is: you fetch the data with PHP somehow. You concatenate React with your app, pass the PHP data to the app and get ready to execute this JS with v8. (The concat stuff could, and should, be done by a build process actually, not at runtime, but this is just an illustration)

此部分与之前相同,在此处粘贴,没有其他注释。 关键是:您以某种方式使用PHP获取数据。 您将React与您的应用程序连接起来,将PHP数据传递给应用程序,并准备好使用v8执行此JS。 (concat的东西实际上可以并且应该由构建过程来完成,而不是在运行时完成,但这只是一个示例)

<?php
$react = array();
 
// stubs, react
$react[] = "var console = {warn: function(){}, error: print}";
$react[] = "var global = {}";
$react[] = file_get_contents('react/build/react.js');
$react[] = "var React = global.React";
 
// my custom components
$react[] = file_get_contents('react/build/table.js');
 
// my application, fetch the data
$data = array( // database, web services, whatevers
    array(1, 2, 3),
    array(4, 5, 6),
    array(7, 8, 9));
// my application, render the data
$react[] = sprintf(
  "React.renderComponentToString(Table({data: %s}), print)",
  json_encode($data));
 
// concat all JS
$react = implode(";\n", $react);

运行JS并缓冲 (Run JS and buffer)

While before I just printed the result of the JS code (which is rendered HTML), here I want to keep it in a variable and use it later as part of a bigger template. So I execute the JS string but buffer the output to a variable. (I tried without a buffer, only using the return value of $v8->executeString() but couldn't make it happen, as React's renderComponentToString() is async and takes a callback)

在我刚刚打印JS代码(呈现为HTML)的结果之前,这里我想将其保留在变量中,以后将其用作更大的模板的一部分。 因此,我执行JS字符串,但将输出缓冲到变量中。 (我尝试不使用缓冲区,仅使用$v8->executeString()的返回值,但无法实现,因为React的renderComponentToString()是异步的并且需要回调)

$v8 = new V8Js();
try {
  // buffer v8 output to $markup
  ob_start();
  $v8->executeString($react);
  $markup = ob_get_clean();
} catch (V8JsException $e) {
  // blow up spectacularly
  echo "<pre>"; var_dump($e); die();
}

呈现整个页面 (Render a whole page)

Finally, you take the rendered markup and replace a simple template which takes care of all the html/body/doctype, etc. Then you print it out.

最后,使用呈现的标记并替换一个简单的模板,该模板处理所有html / body / doctype等。然后将其打印出来。

// page template
$page = file_get_contents('page_template.html');
 
printf($page, $markup, json_encode($data));

In fact, this template will also take care of initializing React on the client.

实际上,该模板还将负责在客户端上初始化React。

模板/客户端 (The template/client)

So what goes into this page_template.html? It takes care of the HTML boilerplate, load CSS, and so on. Then it puts all the server-rendered HTML in a div id=page. Finally it loads React.js and custom app .js (which could very well be concatenated into one). Once React is loaded you initialize the client-side, by passing the same $data used to render server-side.

那么,此page_template.html什么? 它负责处理HTML样板文件,加载CSS等。 然后将所有服务器呈现HTML放入div id=page 。 最后,它加载React.js和自定义应用程序.js(可以很好地合并为一个)。 一旦加载了React,您就可以通过传递用于渲染服务器端的$data来初始化客户端。

<!doctype html>
<html>
  <head>
    <title>React page</title>
    <!-- css and stuff -->
  </head>
  <body>
    
    <!-- render server content here -->
    <div id="page">%s</div> 
    
    <!-- load react and app code -->
    <script src="react/build/react.min.js"></script>
    <script src="react/build/table.js"></script>
    
    <script>
    // client init/render
    var r = React.renderComponent(
      Table({data: %s}), 
      document.getElementById('page'));
    </script>
  </body>
</html>

So clearly there's a duplication of the data sent to the client: once rendered as HTML and once JSON-encoded. But the JSON encoded data should be very small in most cases. Alternatively you can always DOM-scrape the rendered HTML for the data and pass that back to React, but in most cases the scraping code will probably be longer than the JSON encoded thing.

显然,发送给客户端的数据是重复的:一次呈现为HTML,一次以JSON编码。 但是在大多数情况下,JSON编码的数据应该很小。 或者,您总是可以对数据的呈现HTML进行DOM爬取,然后将其传递回React,但是在大多数情况下,爬取代码可能比JSON编码的要长。

Yet another strategy is to flush only partial data rendered as HTML, only as much (or as little) as needed to make the page appear responsive. Then in a second flush pass all the data as JSON and let React update the UI.

另一策略是仅刷新呈现为HTML的部分数据,仅刷新(或减少)所需的数量,以使页面显示响应。 然后在第二次刷新中将所有数据作为JSON传递,并让React更新UI。

结果 (Results)

Rendered markup on the server:

服务器上的渲染标记:

1

Updating the data client-side to make sure client React is initialized and knows what it's doing

在客户端更新数据以确保客户端React已初始化并知道它在做什么

e2

Here's a static version of the end result (can't install v8 on dreamhost's shared server) if you want to explore.

如果您想探索的话,这是最终结果的静态版本(无法在Dreamhost的共享服务器上安装v8)。

请享用! (Enjoy!)

Thanks for reading, now go play with React. Meanwhile I'll try to clean this code up and setup a standalone project you can fork.

感谢您的阅读,现在开始玩React。 同时,我将尝试清理此代码并设置一个可以分叉的独立项目。

Tell your friends about this post on Facebook and Twitter

在Facebook和Twitter上告诉您的朋友有关此帖子的信息

翻译自: https://www.phpied.com/server-side-react-with-php-part-2/

react 服务器端渲染


http://www.niftyadmin.cn/n/1306947.html

相关文章

dojo级联步骤

dojo级联步骤 1、数据请求回来后&#xff0c;检查数据格式是否满足下拉框的数据格式&#xff1b; 2、通过firebug进行调试&#xff0c;检查select下拉框子项结点是否取道&#xff1b; 3、查看API文档&#xff0c;保证改变store的方法是正确的。

Python元类的理解

什么是元类 Python中&#xff0c;一切皆对象&#xff0c;我们定义的数字、字符串、函数、列表等都是对象&#xff0c;对象是类&#xff08;class&#xff09;的是实例&#xff0c;而类&#xff08;class&#xff09;其实也是对象&#xff0c;是type的实例。这个type就是Python…

矩阵卷积的卷积核_画布像素2:卷积矩阵

矩阵卷积的卷积核In the previous post I talked about manipulating and changing pixels in an image (using JavaScript and canvas) one at a time. We took a single pixel and messed around with its R, G, B or A values. 在上一篇文章中&#xff0c;我谈到了一次处理和…

dojo省份地市级联之省份封装类(一)

省份封装类 Province.java /*** 省份封装类*/ package com.you.model;import java.io.Serializable;/*** author YHD**/ public class Province implements Serializable {/*** */private static final long serialVersionUID 1L;/*** ID*/private String id;/*** name*/pri…

wordpress显示摘要_在WordPress中突出显示php源代码

wordpress显示摘要The source code highlighting was probably the first feature I was missing in WordPress. I briefly googled my options and decided it would be quicker to add the missing feature myself, since it looked pretty straightforward. 突出显示源代码可…

Python logging日志模块的使用

在实际的开发过程中&#xff0c;为了方便调试程序&#xff0c;记录系统的运行状态及错误等&#xff0c;及时发现系统的问题并快速定位问题&#xff0c;通常会使用日志。下面来介绍下在Python项目中如何使用日志。 Python提供了一个用于记录日志的标准库模块logging&#xff0c…

进入论坛出现403

1、今天登陆论坛&#xff0c;出现以下问题 2、论坛自己回复不能超过三次

dojo拼接成CSV格式字符串

var student "学号,姓名,年龄\n"; for(var i 0;i<resp.items.length;i) { student resp.items[i].id "," resp.items[i].name "," resp.items[i].age "\n"; } console.info(student);