简体   繁体   中英

Render React Components from PHP

I'm using ReactJS to power a simple filterable item list and it works quite well for my need.

The problem is that I need to render the markup on the server for SEO reasons, but when I call React.renderComponent() it replace the existing markup with the one generated by React.

Searching in React's docs I found this note:

React.renderComponent() replaces the contents of the container node you pass in. In the future, it may be possible to insert a component to an existing DOM node without overwriting the existing children.

Moreover I can't use React.renderComponentToString() to generate the markup server-side because my backend runs on PHP...

Is there any (even if hackish) way to achieve this with the current release (0.11.2)?

I suppose that if that's possible with markup generated by renderComponentToString() there should be a way to mock that result?

Thank you for any advice!

You can look at https://github.com/reactjs/react-php-v8js

It renders react UI components on the server-side with PHP.

The implementation is very simple and the only requirement is that you need to be able to setup the V8Js PHP extension on your server.

The short answer is: not really.

The only sensible way to do it would be having a node process running which php can request renders from. This isn't a bad solution especially for pages that are heavily cached.

I suggest setting it up in a very dynamic way:

<?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>

In 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);

This of course assumes your components are in commonjs modules. If they're not, this is another reason to do so!


I haven't used php in a few years, so please update this answer if I made any mistakes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM