Integrating React.js into a PHP Application @AndrewRota | #BGPHP16
JavaScript Ecosystem
Software Engineer at wayfair.com JavaScript Platform Team @AndrewRota Boston, MA Andrew Rota
Let’s take a step back.
Traditional Website Lifecycle ServerBrowser HTML Response HTML Request ServerBrowser HTML Response HTML Request ServerBrowser HTML Response HTML Request
Traditional Website Stack Server-Side MVC Framework Data Persistance JavaScript
Single Page Application Lifecycle Browser HTML Response HTML Request Server Data Response Data Request Server Data Response Data Request Server
Single Page Application Stack Server-Side MVC Framework Data Persistance JavaScript
• Introducing React.js • Client-Side React.js with PHP • Server-side rendering React.js with PHP • JSX • Fallback to server functionality • What does it all mean?
What is React.js? “A JavaScript library for building user interfaces”
Component driven Composable, reusable, testable
Entire component re-renders on data change No more manual DOM manipulation! Implemented under the hood with “virtual DOM” engine.
“Learn once, write anywhere” React Native for native iOS and Android Apps
var Greeting = React.createClass({
 render: function() {
 return <strong>
 Hello, {this.props.name}!
 </strong>;
 }
 });
 
 ReactDOM.render(<Greeting name="World"/>, el);

var Greeting = React.createClass({
 displayName: "Greeting",
 
 render: function render() {
 return React.createElement(
 "strong",
 null,
 "Hello, ",
 this.props.name,
 "!"
 );
 }
 });
 
 ReactDOM.render(React.createElement(
 Greeting,
 {name: "World"}),
 el);
var Greeting = React.createClass({
 render: function() {
 return <strong>
 Hello, {this.props.name}!
 </strong>;
 }
 });
 
 ReactDOM.render(<Greeting name="World"/>, el);

React.createClass({
 // ...
 render: function() {
 return (
 <div>
 <h3>TODO</h3>
 <TodoList items={this.state.items} />
 <form onSubmit={this.handleSubmit}>
 <input onChange={this.onChange} value={this.state.text} />
 <button>{'Add #' + (this.state.items.length + 1)}</button>
 </form>
 </div>
 );
 }
 });
 This is today’s demo based on the simple todo list app from facebook.github.io/react/
Client-Side Rendering
JavaScript renders react.js app Nearly-blank page load
JavaScript PHP React.js Clientside
Advantages of rendering React.js client-side • Server-agnostic • Isolates UI layer to one technology: JavaScript • Least amount of client-server sync complexity • Easiest way to get started with React.js
For many apps, client-side rendering with React.js is the most practical and least complex approach
So why might I need server-side rendering (SSR)? • Performance sensitive applications • Search engine optimization • Site needs to work without JavaScript
Server-Side Rendering + Performance More control to reduce time to first meaningful paint Client-Side +SSR JS Loads Rendered Interactive JS Loads
SEO • Allow site to be crawled by Search engines which don’t execute JavaScript • Google does crawl sites with JavaScript, though, so this may be less of an issue today
Site works without JavaScript • You may have users who disable JavaScript in their browser (for example by using NoScript) • The user should be able to interact with the site before JavaScript downloads • The site’s JavaScript fails to load 
 (poor connection, CDN issue, etc.)
Don’t let JavaScript become a single point of failure
React.js SSR
var Greeting = React.createClass({
 render: function() {
 return <strong>
 Hello, {this.props.name}!
 </strong>;
 }
 });
 
 ReactDOM.render(<Greeting name="World"/>, el);

var Greeting = React.createClass({
 render: function() {
 return <strong>
 Hello, {this.props.name}!
 </strong>;
 }
 });
 
 ReactDOMServer.renderToStaticMarkup(<Greeting name="World"/>); <strong>Hello, World!</strong>
var Greeting = React.createClass({
 render: function() {
 return <strong>
 Hello, {this.props.name}!
 </strong>;
 }
 });
 
 ReactDOMServer.renderToString(<Greeting name="World"/>); <strong data-reactroot="" data-reactid="1" data-react- checksum="1367554571"><!-- react-text: 2 -->Hello, <!-- /react- text --><!-- react-text: 3 -->World<!-- /react-text --><!-- react-text: 4 -->!<!-- /react-text --></strong>
This is great if our server runs JavaScript
The easiest way to do React.js SSR is by running Node.js on the server
“Universal JavaScript”
Server-Side JavaScript Client-Side JavaScript
But what if your server is PHP?
Two options for SSR with PHP on the server side
React.js SSR with a Node.js Service
React Node.js service JavaScript PHP React.js Clientside
curl -X POST -H 'Content-Type: application/json' -d ‘{"path":"./resources/assets/js/Greeting.js", "data": {"name": "BGPHP"}}' http://127.0.0.1:3333/ <div data-reactroot="" data-reactid="1" data-react- checksum="-520141946"><strong data-reactid="2"><!-- react-text: 3 -- >Hello, <!-- /react-text --><!-- react-text: 4 -->BGPPH<!-- /react- text --><!-- react-text: 5 -->!<!-- /react-text --></strong></div>
<?php
 $component_name = 'Greeting';
 $ch = curl_init("https://nodeserver.local:3333/");
 $props = ["name" => "BGPHP"];
 $data = ["data" => $props, "path" => "./resources/assets/js/" . $component_name . ".js"];
 $data_string = json_encode($data);
 $props_string = json_encode($props);
 
 curl_setopt(/* … */); $result = curl_exec($ch); <div id="app"><?= $result ?></div> 
 <script src="{{ asset('js/react-bundle.js') }}"></script>
 <script src="{{ asset('js/components.js') }}”></script> 
 <script>ReactDOM.render(React.createElement(<?= $component_name ?>, "<?= $props_string ?>"), document.getElementById('app'));</script>
But what if we could execute JavaScript from within PHP…
React.js SSR with PHP’s V8Js
JavaScript PHP . React.js Clientside React.js V8Js
What is V8Js? https://pecl.php.net/package/v8js
Installing V8Js • If you’re lucky there might be a binary available, otherwise… • Build and install the latest version of v8 • Build and install php-v8js • Enable the v8js extension in PHP • extension=v8js.so
- php v8js docs “it's way more tedious to install V8Js on Windows” Oh, and…
Success!
<?php
 $v8 = new V8Js();
 echo($v8->executeString("
 var name = 'World';
 const GREETING = 'Hello';
 function greeting(str) {
 return GREETING + ‘, ' + str + '!';
 }
 
 greeting(name);
 ")); JS!!!
nacmartin/phpexecjs V8js or node.js subprocess
JavaScript PHP . React.js Clientside V8JsNode.js
<?php
 $phpexecjs = new PhpExecJs();
 echo($phpexecjs->evalJs("
 var name = 'World';
 const GREETING = 'Hello';
 function greeting(str) {
 return GREETING + ‘, ' + str + '!';
 }
 
 greeting(name);
 "));
reactjs/react-php-v8js
<?php
 $react_source = file_get_contents(__DIR__ . 'path/to/react-bundle.js');
 $app_source = file_get_contents(__DIR__ . 'path/to/components.js'); 
 $rjs = new ReactJS($react_source, $app_source);
 $rjs->setComponent('Greeting', [ 'name' => 'world' ]); ?> <div id="app"><?= $rjs->getMarkup(); ?></div> <script src="path/to/react-bundle.js'"></script>
 <script src="path/to/components.js"></script> 
 <script><?= $rjs->getJS("#app"); ?></script>
talyssonoc/react-laravel

 <div>
 @react_component('Hello', $data )
 </div>
 Route::get('/foo', function() {
 return view('foo', ['data' => [ 'name' => 'world'] ]);
 });
Limenius/ReactBundle phpexecjs or node.js service (for Symfony)
node.js server Easier to install, update Standard environment for running react.js on the server Maintain separate server Fewer framework-level integrations v8js or node.js subprocess Write JS in PHP Complicated install and update process react-php-v8js library is experimental + + - + - - -
And remember, for any of these options: + Cache in production!
So what about all that JSX?
ReactDOM.render(<Greeting name="World"/>, el);
 Technically, this isn’t JavaScript
ReactDOM.render(<Greeting name="World"/>, el);
 Babel to the rescue! ReactDOM.render(React.createElement(Greeting, { name: "World" }), el);

Babel: Option 1 1. Transform JSX to JS on file change 2. Consume transformed bundle in V8js or node.js render server Use grunt, gulp, webpack, make, or a custom script. Or use your framework’s asset pipeline.
e.g., Using Laravel Elixir and Browserify elixir.config.js.browserify.transformers.push({
 name: 'babelify',
 options: {}
 });
Babel: Option 2 1. Use babel’s require hook 2. Also requires standalone build for production (only for dev, node.js) npm install babel-register require('babel-register');
…without JavaScript. Let’s talk functionality
• Use real links instead of buttons for navigation • Use forms with real submit actions for mutating data • Test without JavaScript!
this isn’t really a talk about React.js …or even PHP. But…
Let’s go a couple levels higher
What does MVC mean in a world of JavaScript frameworks?
View cohesion
Separate by concerns, not technologies
Architecture over individual technologies
Architecture over Technologies • React.js and PHP can work great together • But there are other options for client/server framework integration • reactjs/react-rails • laravel-angular (by @jadjoubran) • At Wayfair we wrote and use tungsten.js
Architecture over individual technologies
The library you choose is less important than how you choose to use it
Takeaways • React.js is most easily integrated in a PHP app if you’re ok with client-side only rendering • If you want server-side rendering, you have a few options too: node.js render server, or V8js • Focus primarily on architecture and design rather than just the choice of individual libraries
@AndrewRota Благодаря! Thank you!

Integrating React.js Into a PHP Application