2014-09-25 185 views
2

我使用ReactJS为一个简单的可过滤项目列表提供支持,它对我的​​需求非常有效。从PHP渲染React组件

问题是,我需要在服务器上为搜索引擎优化原因呈现标记,但是当我打电话给React.renderComponent()时,它将使用由React生成的标记替换现有标记。

搜索在阵营的文档,我发现这样一个字条:

React.renderComponent()代替你传递的容器节点的内容在未来,有可能插入组件到现有的。 DOM节点而不覆盖现有的子节点。

而且我不能使用React.renderComponentToString(),因为我的后端上的PHP运行生成的标记服务器端...

是否有任何(即使hackish的)的方式与当前版本来实现这一( 0.11.2)?

我想,如果renderComponentToString()生成的标记可能会出现这种情况,那么应该有一种方法来模拟该结果?

谢谢你的任何建议!

回答

1

简短的回答是:不是真的。

唯一明智的做法是将一个节点进程运行,哪个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')(); // [email protected] 
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,所以如果我犯了什么错误,请更新这个答案。

+0

感谢您的详细解答!这是一个很酷的解决方案,但我认为这对我的小型需求来说是一种矫枉过正,无论是在复杂性和成本方面(对于Node服务器而言)。如果这是我担心的事情的状态,那么我将不得不重写我的组件,使其能够将其注入到现有的DOM元素中,例如Marionette。无论如何,这真是太糟糕了,我真的很喜欢React :( – Ingro 2014-09-25 23:17:04

+0

除了复杂性之外,你可以在与你的web服务器/ php应用程序相同的服务器/ vps上运行它,这就是它被写入的工作方式(在本地主机上)。 – FakeRainBrigand 2014-09-25 23:28:22

+0

不幸的是,我们没有拥有最终网站上线的网络服务器,所以我们不可能让Node应用程序在其上运行:( – Ingro 2014-09-26 07:31:05

7

你可以看一下https://github.com/reactjs/react-php-v8js

它使得在服务器端使用PHP反应UI组件。

实现非常简单,唯一的要求是您需要能够在您的服务器上设置V8Js PHP扩展