从PHP中呈现React组件

5
我正在使用ReactJS来驱动一个简单的可过滤项目列表,它非常适合我的需求。问题是,出于SEO的原因,我需要在服务器上渲染标记,但当我调用React.renderComponent()时,它会用React生成的标记替换现有的标记。在React的文档中搜索后,我发现了这个注释:React.renderComponent()替换您传入的容器节点的内容。将来,可能可以将组件插入到现有的DOM节点中,而不覆盖现有的子元素。此外,我不能使用React.renderComponentToString()来生成服务器端的标记,因为我的后端运行在PHP上...有没有任何(即使是hackish)方法来在当前版本(0.11.2)中实现这一点?我想,如果可以使用renderComponentToString()生成的标记来实现这一点,那么应该有一种方法来模拟该结果吧?谢谢您的任何建议!
2个回答

7
你可以查看 https://github.com/reactjs/react-php-v8js ,它可以使用 PHP 在服务器端渲染 React UI 组件。
这个实现非常简单,唯一的要求是你需要在服务器上安装 V8Js PHP 扩展

1
@ksyrium ReactPHP似乎与ReactJS无关,而是一个用于PHP的响应式编程库。 - Alan H.
@AlanH。你说得对,谢谢指出!我已经删除了我的评论。 - ksyrium

0

简短的回答是:不太可能。

唯一明智的方法是运行一个节点进程,PHP可以从中请求渲染。这并不是一个坏的解决方案,特别是对于经常缓存的页面。

我建议以非常动态的方式设置它:

<?php 
function render_component_to_string($component, $data) 
{
  $url = "http://localhost:9000/components/" 
    . $component 
    . "?data=" 
    . rawurlencode(json_encode($data));
  return file_get_contents($url)
}
?>

<div id="myFilteredList">
  <?= render_component_to_string("FilteredList", 
        array("items" => items, "title" => "My List")) ?>
</div>

在node.js中:

var app = require('express')(); // express@4.x
var React = require('react');

// create a dictionary of components 
// Object.create(null) because the key is supplied
var components = Object.create(null);
components.FilteredList = require('./components/filtered-list.js');

app.get('/component/:componentName', function(req, res){
  var component = components[req.params.componentName];

  // safety first!
  if (!component) {
    console.error("Invalid component", req.params.componentName);
    return res.send(404);
  }

  // more safety
  try {
    var data = JSON.parse(req.query.data);
  }
  catch (e) {
    console.error("Invalid JSON", req.params.componentName, req.query.data);
    return res.send(400);
  }

  // render and send the result back
  try {
    var result = React.renderComponentToString(component(data));
  }
  catch (e) {
    console.error('Could not render', req.params.componentName,
                  'with props', data);
    console.error(e.message, '\n', e.stack);
    return res.send(400);
  }
  res.send(result);
});


app.listen(9000);

当然,这假设您的组件是在commonjs模块中。如果不是,这就是另一个原因去这样做!


我已经好几年没用 PHP 了,如果我有任何错误,请更新这个答案。


感谢您提供如此详细的答案!这是一个很酷的解决方案,但我认为对于我的小需求来说,无论是在复杂性还是成本(对于Node服务器)方面都有些过度了。如果事情就是这样,我担心我将不得不重写我的组件,使用像Marionette这样的东西来注入到现有的DOM元素中。无论如何,这太糟糕了,我真的很喜欢React :( - Ingro
除了复杂性之外,您可以在与您的Web服务器/PHP应用程序相同的服务器/VPS上运行它。这就是它被编写为在本地主机上工作的方式。 - Brigand
很不幸,我们并不拥有最终网站将要运行的web服务器,所以我们无法让Node应用程序在其中运行:( - Ingro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接