2014-09-25 141 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擴展