SlideShare a Scribd company logo
Server-side Rendering of JavaScript
in PHP
Nacho Martín
Nacho Martín
I write code at Limenius.
We build tailor-made projects,
and provide consultancy and formation.
We are very happy with React, and have been
dealing with how to integrate with PHP for
some time now & publishing libraries about
it.
What is the problem that
Server Side Rendering
adresses?
Nacho Martín
nacho@limenius.com
@nacmartin
A long time ago in a galaxy far, far away
Server
Nacho Martín
nacho@limenius.com
@nacmartin
A long time ago in a galaxy far, far away
Server
HTML
</>
HTML
</> Client
Nacho Martín
nacho@limenius.com
@nacmartin
Very simple model that works
But to show a change we have to do a full
page reload.
Even for things like “your password must have
at least 6 characters”.
Nacho Martín
nacho@limenius.com
@nacmartin
Even for things like this
New password
New Submit
Nacho Martín
nacho@limenius.com
@nacmartin
Even for things like this
New password
New Submit
****
Nacho Martín
nacho@limenius.com
@nacmartin
Even for things like this
New password
New Submit
****
Your password must contain 6 characters!
Nacho Martín
nacho@limenius.com
@nacmartin
Adding dynamic elements
HTML
</>
Client
HTML
</>
Server
Nacho Martín
nacho@limenius.com
@nacmartin
Adding dynamic elements
HTML
</>
Client
HTML
</>
JS JS
Server
Nacho Martín
nacho@limenius.com
@nacmartin
Step 1: Client uses JS to modify the DOM
Client
HTML
</>
JS
$( "p" ).addClass( “myClass" );
Nacho Martín
nacho@limenius.com
@nacmartin
With DOM modification
We can now modify the document reacting to
user interaction.
What about loading new content based on
content interaction?
Nacho Martín
nacho@limenius.com
@nacmartin
Example
1 2 3 4 5
Nacho Martín
nacho@limenius.com
@nacmartin
Adding dynamic content
HTML
</>
Client
HTML
</>
JS JS
Server
Nacho Martín
nacho@limenius.com
@nacmartin
Adding dynamic content
HTML
</>
Client
HTML
</>
JS JS
Server
API
Nacho Martín
nacho@limenius.com
@nacmartin
Step 2: Dynamic content
Client
HTML
</>
JS
$(“#grid").load( “api/page2.html“ );
API
Nacho Martín
nacho@limenius.com
@nacmartin
Step 2: Dynamic content
Client
HTML
</>
JS
$(“#grid").load( “api/page2.html“ );
API
$.get( “api/page2.json“,
function(data) {
$(“#grid”).html(renderPage(data));
}
);
Nacho Martín
nacho@limenius.com
@nacmartin
DOM Manipulation
HTML
</>
This happens in the Browser
Element
<body>
Element
<div id=“grid”>
Element
<h1>
Text
“Hi there”
…
Element
<div>
Element
<div>
Nacho Martín
nacho@limenius.com
@nacmartin
DOM Manipulation
This happens in the Browser
Element
<body>
Element
<div id=“grid”>
Element
<h1>
Text
“Hi there”
…
Element
<div>
Element
<div>
API
$.get( “api/page2.json“,
function(data) {
$(“#grid”).html(renderPage(data));
}
);
Nacho Martín
nacho@limenius.com
@nacmartin
DOM Manipulation
This happens in the Browser
Element
<body>
Element
<div id=“grid”>
Element
<h1>
Text
“Hi there”
API
$.get( “api/page2.json“,
function(data) {
$(“#grid”).html(renderPage(data));
}
);
Nacho Martín
nacho@limenius.com
@nacmartin
DOM Manipulation
This happens in the Browser
Element
<body>
Element
<div id=“grid”>
Element
<h1>
Text
“Hi there”
…
Element
<div>
Element
<div>
API
$.get( “api/page2.json“,
function(data) {
$(“#grid”).html(renderPage(data));
}
);
Nacho Martín
nacho@limenius.com
@nacmartin
Problem: duplication of work
HTML
</>
We need a mechanism in the server to build the initial HTML…
Nacho Martín
nacho@limenius.com
@nacmartin
Problem: duplication of work
…and another to update the DOM in the client
API
$(“#grid”).html(renderPage(data));
Nacho Martín
nacho@limenius.com
@nacmartin
Possible solution: don’t render the content in HTML
HTML
</>
<div id=“grid”>
Nacho Martín
nacho@limenius.com
@nacmartin
And on document load do an API call
<div id=“grid”>
API
$(“#grid”).html(renderPage(data));
Nacho Martín
nacho@limenius.com
@nacmartin
This means that the first thing the user sees is this
…and also crawlers :(
Nacho Martín
nacho@limenius.com
@nacmartin
Slow page loads in mobile users
https://www.doubleclickbygoogle.com/articles/mobile-speed-matters/
• Average load time over 3G: 19 seconds.
• 53% of sites that take longer than 3s are abandoned.
• Going from 19s to 5s means:
• 25% more impressions of ads.
• 70% longer sessions.
• 35% lower bounce race.
• 2x ad revenue.
Nacho Martín
nacho@limenius.com
@nacmartin
When are these problems worse
Apps. Bearable.
Content pages. Probably unbearable.
Concurrent problem:
DOM manipulation
vs
State based JS libraries
Nacho Martín
nacho@limenius.com
@nacmartin
We want to build a TODO list
Pour eggs in the pan
How to cook an omelette
Buy eggs
Break eggs
Nacho Martín
nacho@limenius.com
@nacmartin
We want to build a TODO list
Pour eggs in the pan
Beat eggs
How to cook an omelette
Buy eggs
Break eggs
Nacho Martín
nacho@limenius.com
@nacmartin
Options
Nacho Martín
nacho@limenius.com
@nacmartin
Options
1: Re-render everything.
Nacho Martín
nacho@limenius.com
@nacmartin
Options
1: Re-render everything. Simple
Nacho Martín
nacho@limenius.com
@nacmartin
Options
1: Re-render everything. Simple Not efficient
Nacho Martín
nacho@limenius.com
@nacmartin
Options
2: Find in the DOM where to
insert elements, what to move,
what to remove…
1: Re-render everything. Simple Not efficient
Nacho Martín
nacho@limenius.com
@nacmartin
Options
2: Find in the DOM where to
insert elements, what to move,
what to remove…
1: Re-render everything. Simple
Complex
Not efficient
Nacho Martín
nacho@limenius.com
@nacmartin
Options
2: Find in the DOM where to
insert elements, what to move,
what to remove…
1: Re-render everything. Simple
EfficientComplex
Not efficient
Nacho Martín
nacho@limenius.com
@nacmartin
Options
2: Find in the DOM where to
insert elements, what to move,
what to remove…
1: Re-render everything. Simple
EfficientComplex
Not efficient
React allows us to do 1, although it does 2 behind the scenes
Nacho Martín
nacho@limenius.com
@nacmartin
Fundamental premise
Give me a state and a render() method that depends
on it and forget about how and when to render.
Nacho Martín
nacho@limenius.com
@nacmartin
Let’s write a React component
Click me! Clicks: 0
Nacho Martín
nacho@limenius.com
@nacmartin
Let’s write a React component
Click me! Clicks: 1Click me!
Nacho Martín
nacho@limenius.com
@nacmartin
Let’s write a React component
import React, { Component } from 'react';
class Counter extends Component {
constructor(props) {
super(props);
this.state = {count: 1};
}
tick() {
this.setState({count: this.state.count + 1});
}
render() {
return (
<div className="App">
<button onClick={this.tick.bind(this)}>Click me!</button>
<span>Clicks: {this.state.count}</span>
</div>
);
}
}
export default Counter;
Nacho Martín
nacho@limenius.com
@nacmartin
Let’s write a React component
import React, { Component } from 'react';
class Counter extends Component {
constructor(props) {
super(props);
this.state = {count: 1};
}
tick() {
this.setState({count: this.state.count + 1});
}
render() {
return (
<div className="App">
<button onClick={this.tick.bind(this)}>Click me!</button>
<span>Clicks: {this.state.count}</span>
</div>
);
}
}
export default Counter;
Initial state
Nacho Martín
nacho@limenius.com
@nacmartin
Let’s write a React component
import React, { Component } from 'react';
class Counter extends Component {
constructor(props) {
super(props);
this.state = {count: 1};
}
tick() {
this.setState({count: this.state.count + 1});
}
render() {
return (
<div className="App">
<button onClick={this.tick.bind(this)}>Click me!</button>
<span>Clicks: {this.state.count}</span>
</div>
);
}
}
export default Counter;
Set new state
Initial state
Nacho Martín
nacho@limenius.com
@nacmartin
Let’s write a React component
import React, { Component } from 'react';
class Counter extends Component {
constructor(props) {
super(props);
this.state = {count: 1};
}
tick() {
this.setState({count: this.state.count + 1});
}
render() {
return (
<div className="App">
<button onClick={this.tick.bind(this)}>Click me!</button>
<span>Clicks: {this.state.count}</span>
</div>
);
}
}
export default Counter;
Set new state
render(), called by React
Initial state
Nacho Martín
nacho@limenius.com
@nacmartin
Working with state
constructor(props) {
super(props);
this.state = {count: 1};
}
Initial state
Nacho Martín
nacho@limenius.com
@nacmartin
Working with state
constructor(props) {
super(props);
this.state = {count: 1};
}
Initial state
this.setState({count: this.state.count + 1});
Assign state
Nacho Martín
nacho@limenius.com
@nacmartin
render() and JSX
render() {
return (
<div className="App">
<button onClick={this.tick.bind(this)}>Clícame!</button>
<span>Clicks: {this.state.count}</span>
</div>
);
It is not HTML, it is JSX.
React transforms it internally to HTML elements.
Good practice: make render() as clean as possible, only a return.
Nacho Martín
nacho@limenius.com
@nacmartin
render() and JSX
render() {
return (
<div className="App">
<button onClick={this.tick.bind(this)}>Click me!</button>
<span>Clicks: {this.state.count}</span>
</div>
);
}
Nacho Martín
nacho@limenius.com
@nacmartin
render() and JSX
render() {
return (
<div className="App">
<button onClick={this.tick.bind(this)}>Click me!</button>
<span>Clicks: {this.state.count}</span>
</div>
);
}
Here we don’t modify the state
Nacho Martín
nacho@limenius.com
@nacmartin
render() and JSX
render() {
return (
<div className="App">
<button onClick={this.tick.bind(this)}>Click me!</button>
<span>Clicks: {this.state.count}</span>
</div>
);
}
Here we don’t make Ajax calls
Nacho Martín
nacho@limenius.com
@nacmartin
render() and JSX
render() {
return (
<div className="App">
<button onClick={this.tick.bind(this)}>Click me!</button>
<span>Clicks: {this.state.count}</span>
</div>
);
}
Here we don’t calculate decimals of PI and send an e-mail
with the result
Nacho Martín
nacho@limenius.com
@nacmartin
Components hierarchy
Nacho Martín
nacho@limenius.com
@nacmartin
Components hierarchy
Nacho Martín
nacho@limenius.com
@nacmartin
Components hierarchy: props
class CounterGroup extends Component {
render() {
return (
<div>
<Counter name="amigo"/>
<Counter name="señor"/>
</div>
);
}
}
Nacho Martín
nacho@limenius.com
@nacmartin
Components hierarchy: props
render() {
return (
<div className="App">
<button onClick={this.tick.bind(this)}>
Click me! {this.props.name}
</button>
<span>Clicks: {this.state.count}</span>
</div>
);
}
and in Counter…
class CounterGroup extends Component {
render() {
return (
<div>
<Counter name="amigo"/>
<Counter name="señor"/>
</div>
);
}
}
Nacho Martín
nacho@limenius.com
@nacmartin
Components hierarchy: props
render() {
return (
<div className="App">
<button onClick={this.tick.bind(this)}>
Click me! {this.props.name}
</button>
<span>Clicks: {this.state.count}</span>
</div>
);
}
and in Counter…
class CounterGroup extends Component {
render() {
return (
<div>
<Counter name="amigo"/>
<Counter name="señor"/>
</div>
);
}
}
Nacho Martín
nacho@limenius.com
@nacmartin
Everything depends on the state, therefore we can:
Nacho Martín
nacho@limenius.com
@nacmartin
Everything depends on the state, therefore we can:
•Reproduce states,
Nacho Martín
nacho@limenius.com
@nacmartin
Everything depends on the state, therefore we can:
•Reproduce states,
•Rewind,
Nacho Martín
nacho@limenius.com
@nacmartin
Everything depends on the state, therefore we can:
•Reproduce states,
•Rewind,
•Log state changes,
Nacho Martín
nacho@limenius.com
@nacmartin
Everything depends on the state, therefore we can:
•Reproduce states,
•Rewind,
•Log state changes,
•…
Nacho Martín
nacho@limenius.com
@nacmartin
Everything depends on the state, therefore we can
Nacho Martín
nacho@limenius.com
@nacmartin
Everything depends on the state, therefore we can
render the initial state to a HTML string
Server side rendering
Nacho Martín
nacho@limenius.com
@nacmartin
First page load
HTML
</>
Client
HTML
</>
JS JS
Server
API
Includes initial state
Nacho Martín
nacho@limenius.com
@nacmartin
When we need more data
Client
Server
APIAPI
API calls to update the state
and therefore update
its representation (UI)
Nacho Martín
nacho@limenius.com
@nacmartin
ReactDOMServer.renderToString(element)
ReactDOM.hydrate(element, container[, callback])
SSR in React
Nacho Martín
nacho@limenius.com
@nacmartin
ReactDOMServer.renderToString(<MyApp/>)
SSR in React. 1) In the server:
<div data-reactroot="">
This is some <span>server-generated</span> <span>HTML.</span>
</div>
Nacho Martín
nacho@limenius.com
@nacmartin
SSR in React. 2) insert in our template
<html>
…
<body>
<div id=“root”>
<div data-reactroot="">
This is some <span>server-generated</span> <span>HTML.</span>
</div>
</div>
…
Nacho Martín
nacho@limenius.com
@nacmartin
ReactDOM.hydrate(
<MyApp/>,
document.getElementById('root')
)
SSR in React. 1) In the client:
<div id=“root”>
<div data-reactroot="">
This is some <span>server-generated</span> <span>HTML.</span>
</div>
</div>
…
The client takes control over it
Nacho Martín
nacho@limenius.com
@nacmartin
renderer.renderToString(app, (err, html) => {
if (err) throw err
console.log(html)
// => <div data-server-rendered="true">Hello World</div>
})
var app = new Vue({
el: ‘#root',
data: {
message: 'Hello Vue!'
}
})
Similar, in Vue
Nacho Martín
nacho@limenius.com
@nacmartin
React, Vue, but does my library support this?
If what is rendered depends on the state then
we are probably good.
If your JS depends on having the DOM loaded
and manipulate it, then we are not good.
Nacho Martín
nacho@limenius.com
@nacmartin
Problematic Example
Page
Nacho Martín
nacho@limenius.com
@nacmartin
Problematic Example
Page
API
My React Component
Nacho Martín
nacho@limenius.com
@nacmartin
Problematic Example
Page
API
My React Component
API
“React Component” that renders CkEditor,
d3, or other lib that relies on DOM manipulation
Nacho Martín
nacho@limenius.com
@nacmartin
Problematic Example
Page
API
My React Component
API
“React Component” that renders CkEditor,
d3, or other lib that relies on DOM manipulation
SSR in PHP
Nacho Martín
nacho@limenius.com
@nacmartin
Why?
SSR in JavaScript (node.js) is more natural.
But it may not be the right choice for the project.
Maybe the team has expertise in PHP.
Maybe the project already exists.
Maybe we want to combine it with sections
rendered from PHP.
The Real World is not as simple as tutorials.
Nacho Martín
nacho@limenius.com
@nacmartin
We need
Nacho Martín
nacho@limenius.com
@nacmartin
WebpackAssets
JS JS
TS SASS
PNG JPEG
JS
Client App
Nacho Martín
nacho@limenius.com
@nacmartin
WebpackAssets
JS JS
TS SASS
PNG JPEG
JS
Client App
JS
Server side App
Nacho Martín
nacho@limenius.com
@nacmartin
JS Code to execute
Server side JS App
+
Component and state that we want to render
A few bytes,
Changes between
requests
As big as your app.
Doesn’t change
between requests
Options
Nacho Martín
nacho@limenius.com
@nacmartin
This is what we would do for SSR in JS
Client
JS
Front
PHP
API
JS
Client side App
Server side JS App
+
Component and state
Nacho Martín
nacho@limenius.com
@nacmartin
This is what we would do for SSR in JS
Client
JS
Front
PHP
API
JS
Client side App
Server side JS App
+
Component and state
Nacho Martín
nacho@limenius.com
@nacmartin
This is what we would do for SSR in JS
Client
JS
Front
PHP
API
JS
Client side App
Server side JS App
+
Component and state
Nacho Martín
nacho@limenius.com
@nacmartin
Option 1: node.js as subprocess
Client
PHP
App
Node.js
JS
Client side App
Server side JS App
+
Component and state
Nacho Martín
nacho@limenius.com
@nacmartin
Option 1: node.js as subprocess
Client
PHP
App
Node.js
JS
Client side App
Server side JS App
+
Component and state
Nacho Martín
nacho@limenius.com
@nacmartin
Make a call to node.js using Symfony Process component
* Easy to setup.
* Slow.
Library: https://github.com/nacmartin/phpexecjs
Option 1: Call a node.js subprocess
Nacho Martín
nacho@limenius.com
@nacmartin
Option 2: V8JS
Client
PHP
App
V8js
JS
Client side App
Server side JS App
+
Component and state
Nacho Martín
nacho@limenius.com
@nacmartin
Option 2: V8JS
Client
PHP
App
V8js
JS
Client side App
Server side JS App
+
Component and state
Nacho Martín
nacho@limenius.com
@nacmartin
But we can cache
public function createContext($code, $cachename = null)
{
if ($cachename) {
$cacheItem = $this->cache->getItem($cachename);
if ($cacheItem->isHit()) {
$snapshot = $cacheItem->get();
} else {
$snapshot = V8Js::createSnapshot($code);
$cacheItem->set($snapshot);
$this->cache->save($cacheItem);
}
} else {
$snapshot = V8Js::createSnapshot($code);
}
$this->v8 = new V8Js('PHP', [], [], true, $snapshot);
}
Nacho Martín
nacho@limenius.com
@nacmartin
Option 2: V8JS
Client
PHP
App
V8js
JS
Client side App
Server side JS App
Component and state
Nacho Martín
nacho@limenius.com
@nacmartin
Option 2: V8JS
Client
PHP
App
V8js
JS
Client side App
Server side JS App
Component and state
📷
Nacho Martín
nacho@limenius.com
@nacmartin
Option 2: V8JS
Client
PHP
App
V8js
JS
Client side App
Server side JS App
Component and state
📷
Nacho Martín
nacho@limenius.com
@nacmartin
Use PHP extension v8js
* Fast.
* Need to compile v8, v8js, find Docker images… (this problem is not
small).
Library: https://github.com/nacmartin/phpexecjs
Option 2: v8js PHP extension
Nacho Martín
nacho@limenius.com
@nacmartin
Option 3: External JS server
Client
PHP
App
JS
renderer
JS
Client side App
Server side JS App
Component and state
Nacho Martín
nacho@limenius.com
@nacmartin
Option 3: External JS server
Client
PHP
App
JS
renderer
JS
Client side App
Server side JS App
Component and state
Nacho Martín
nacho@limenius.com
@nacmartin
We have “stupid” node.js server used only to render components.
It has <100 LoC, and it doesn’t know anything about our logic.
* Fast.
There is an example a dummy JS server for this purpose at
https://github.com/Limenius/symfony-react-sandbox
Option 3: External node.js server
ReactRenderer &
ReactBundle
Nacho Martín
nacho@limenius.com
@nacmartin
Some libraries
phpexecjsReactRendererReactBundle
node.js
v8js
…
Twig extension
External renderer
Selects JS runner
Runs it
Uses snapshots if available
Integration with
Symfony
Nacho Martín
nacho@limenius.com
@nacmartin
Options 1 & 2
$renderer = new PhpExecJsReactRenderer(‘path_to/server-bundle.js’);
$ext = new ReactRenderExtension($renderer, 'both');
$twig->addExtension($ext);
phpexecjs detects the presence of the extension v8js,
if not, calls node.js
Nacho Martín
nacho@limenius.com
@nacmartin
Option 3: external renderer
$renderer = new ExternalServerReactRenderer(‘../some_path/node.sock’);
$ext = new ReactRenderExtension($renderer, 'both');
$twig->addExtension($ext);
Nacho Martín
nacho@limenius.com
@nacmartin
JS side part: React on Rails
https://github.com/shakacode/react_on_rails
Used among others by
Nacho Martín
nacho@limenius.com
@nacmartin
JS side part: React on Rails
{{ react_component('RecipesApp', {'props': props}) }}
import ReactOnRails from 'react-on-rails';
import RecipesApp from './RecipesAppServer';
ReactOnRails.register({ RecipesApp });
Twig:
JavaScript:
Nacho Martín
nacho@limenius.com
@nacmartin
Redux integration
Nacho Martín
nacho@limenius.com
@nacmartin
Redux integration
Redux
Store
Nacho Martín
nacho@limenius.com
@nacmartin
Redux integration
import ReactOnRails from 'react-on-rails'
import RecipesAppRedux from './RecipesApp'
import configureStore from ' ../store/RecipesStore'
const recipesStore = configureStore
ReactOnRails.registerStore({ recipesStore })
ReactOnRails.register({ RecipesAppRedux })
Twig:
JavaScript:
{{ redux_store(‘recipesStore’, initialState) }}
{{ react_component('RecipesAppRedux') }}
Nacho Martín
nacho@limenius.com
@nacmartin
Share store between components
Nacho Martín
nacho@limenius.com
@nacmartin
React
React
React
Twig
Twig
React
By sharing store they
can share state
Twig
Share store between components
Things to consider
Context
Nacho Martín
nacho@limenius.com
@nacmartin
Context variables. PHP
[
'serverSide' => $serverSide,
'href' => $request ->getSchemeAndHttpHost() . $request ->getRequestUri(),
'location' => $request ->getRequestUri(),
'scheme' => $request ->getScheme(),
'host' => $request ->getHost(),
'port' => $request ->getPort(),
'base' => $request ->getBaseUrl(),
'pathname' => $request ->getPathInfo(),
'search' => $request ->getQueryString(),
];
Nacho Martín
nacho@limenius.com
@nacmartin
Context in the JS side
export default (initialProps, context) => {
if (context.serverSide) {
return <StaticRouter basename={context.base} location={context.location} />;
} else {
return <BrowserRouter basename={context.base} />;
}
};
Header tags
Nacho Martín
nacho@limenius.com
@nacmartin
Extracting headers
react-helmet (vue-helmet)
import { Helmet } from "react-helmet";
class Application extends React.Component {
render() {
return (
<div className="application">
<Helmet>
<meta charSet="utf-8" />
<title>My Title </title>
<link rel="canonical" href="http: //mysite.com/example" />
</Helmet>
...
</div>
);
}
}
Nacho Martín
nacho@limenius.com
@nacmartin
Extracting headers
export default (initialProps, context) => ({
renderedHtml: {
componentHtml: renderToString(
<StaticRouter
basename={context.base}
location={context.location}
context={{}}>
<App initialProps={initialProps} appContext={context} />
</StaticRouter>
),
title: Helmet.renderStatic().title.toString()
}
});
Return array instead of component
Nacho Martín
nacho@limenius.com
@nacmartin
Then in Twig
{% set recipes = react_component_array('RecipesApp', {'props': props}) %}
{% block title %}
{{ recipes.title is defined ? recipes.title | raw : '' }}
{% endblock title %}
{% block body %}
{{ recipes.componentHtml | raw }}{{ redux_store('recipesStore', initialState) }}
{% endblock body %}
Make reality checks
Nacho Martín
nacho@limenius.com
@nacmartin
Better to try it soon
Certain JS code doesn’t make sense in SSR:
• Timers: SetTimeout, setInterval.
• Access to window, or document objects.
• Access to the DOM.
• First render that depends on weird things like API calls (this is a smell).
Don’t wait until the last moment to check SSR if it is in the roadmap
Summary:
What is SSR and what is it for
Ways to do it in PHP (pros & cons)
Some libraries
Tips & practical problems
Thanks!
Questions?
Nacho Martín
nacho@limenius.com
@nacmartin

More Related Content

PDF
Migrating existing monolith to serverless in 8 steps
PDF
Best Laravel Eloquent Tips and Tricks
PPT
Controls
PDF
Implementing Google Analytics in WordPress
PPT
DOC
Cis407 a ilab 5 web application development devry university
PDF
Laravel mail example how to send an email using markdown template in laravel 8
PPT
Security Risks with using CAPTCHAs
Migrating existing monolith to serverless in 8 steps
Best Laravel Eloquent Tips and Tricks
Controls
Implementing Google Analytics in WordPress
Cis407 a ilab 5 web application development devry university
Laravel mail example how to send an email using markdown template in laravel 8
Security Risks with using CAPTCHAs

Similar to Server Side Rendering of JavaScript in PHP (20)

PDF
Server side rendering with React and Symfony
PPTX
M365 global developer bootcamp 2019 PA
PDF
Introduction to React Native Workshop
PPTX
M365 global developer bootcamp 2019
PDF
Chris Wilson: Progressive Web Apps
PDF
Integrating React.js with PHP projects
PDF
Composable and streamable Play apps
PDF
URL Hacking 101: An Easy Way to Streamline Processes in Salesforce
PPTX
The Art of Gherkin Scripting - Matt Eakin
PPTX
Developing Business Blockchain Applications on Hyperledger
PPTX
MongoDB.local Dallas 2019: MongoDB Stitch Tutorial
PPTX
Battle of React State Managers in frontend applications
PPTX
ASP DOT NET
PDF
[Meetup] a successful migration from elastic search to clickhouse
PPTX
Bootstrapping an App for Launch
PPTX
MongoDB.local Atlanta: MongoDB Stitch Tutorial
PDF
Intro to WebSockets (in Java)
PDF
A Journey with React
PPTX
Presentation Tier optimizations
PPT
Rutgers - FrontPage 98 (Advanced)
Server side rendering with React and Symfony
M365 global developer bootcamp 2019 PA
Introduction to React Native Workshop
M365 global developer bootcamp 2019
Chris Wilson: Progressive Web Apps
Integrating React.js with PHP projects
Composable and streamable Play apps
URL Hacking 101: An Easy Way to Streamline Processes in Salesforce
The Art of Gherkin Scripting - Matt Eakin
Developing Business Blockchain Applications on Hyperledger
MongoDB.local Dallas 2019: MongoDB Stitch Tutorial
Battle of React State Managers in frontend applications
ASP DOT NET
[Meetup] a successful migration from elastic search to clickhouse
Bootstrapping an App for Launch
MongoDB.local Atlanta: MongoDB Stitch Tutorial
Intro to WebSockets (in Java)
A Journey with React
Presentation Tier optimizations
Rutgers - FrontPage 98 (Advanced)
Ad

More from Ignacio Martín (15)

PDF
Elixir/OTP for PHP developers
PDF
Symfony 4 Workshop - Limenius
PDF
Extending Redux in the Server Side
PDF
Redux Sagas - React Alicante
PDF
React Native Workshop - React Alicante
PDF
Asegurando APIs en Symfony con JWT
PDF
Redux saga: managing your side effects. Also: generators in es6
PDF
Introduction to Redux
PDF
Keeping the frontend under control with Symfony and Webpack
PDF
Integrando React.js en aplicaciones Symfony (deSymfony 2016)
PDF
Adding Realtime to your Projects
PDF
Symfony & Javascript. Combining the best of two worlds
PDF
Symfony 2 CMF
PDF
Doctrine2 sf2Vigo
PDF
Presentacion git
Elixir/OTP for PHP developers
Symfony 4 Workshop - Limenius
Extending Redux in the Server Side
Redux Sagas - React Alicante
React Native Workshop - React Alicante
Asegurando APIs en Symfony con JWT
Redux saga: managing your side effects. Also: generators in es6
Introduction to Redux
Keeping the frontend under control with Symfony and Webpack
Integrando React.js en aplicaciones Symfony (deSymfony 2016)
Adding Realtime to your Projects
Symfony & Javascript. Combining the best of two worlds
Symfony 2 CMF
Doctrine2 sf2Vigo
Presentacion git
Ad

Recently uploaded (20)

PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
PPTX
ai tools demonstartion for schools and inter college
PPTX
L1 - Introduction to python Backend.pptx
PPTX
Introduction to Artificial Intelligence
PDF
How Creative Agencies Leverage Project Management Software.pdf
PPTX
AIRLINE PRICE API | FLIGHT API COST |
PDF
2025 Textile ERP Trends: SAP, Odoo & Oracle
PDF
Build Multi-agent using Agent Development Kit
PDF
A REACT POMODORO TIMER WEB APPLICATION.pdf
PPTX
Online Work Permit System for Fast Permit Processing
PDF
System and Network Administraation Chapter 3
PPTX
ManageIQ - Sprint 268 Review - Slide Deck
PDF
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PDF
IEEE-CS Tech Predictions, SWEBOK and Quantum Software: Towards Q-SWEBOK
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
DOCX
The Five Best AI Cover Tools in 2025.docx
PDF
Softaken Excel to vCard Converter Software.pdf
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
ai tools demonstartion for schools and inter college
L1 - Introduction to python Backend.pptx
Introduction to Artificial Intelligence
How Creative Agencies Leverage Project Management Software.pdf
AIRLINE PRICE API | FLIGHT API COST |
2025 Textile ERP Trends: SAP, Odoo & Oracle
Build Multi-agent using Agent Development Kit
A REACT POMODORO TIMER WEB APPLICATION.pdf
Online Work Permit System for Fast Permit Processing
System and Network Administraation Chapter 3
ManageIQ - Sprint 268 Review - Slide Deck
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
Upgrade and Innovation Strategies for SAP ERP Customers
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
IEEE-CS Tech Predictions, SWEBOK and Quantum Software: Towards Q-SWEBOK
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
The Five Best AI Cover Tools in 2025.docx
Softaken Excel to vCard Converter Software.pdf

Server Side Rendering of JavaScript in PHP