Symfony 4 and ReactJS

We know that Symfony is a PHP framework used to create web applications. And deciding how to implement the front end stack,  is entirely up to you. Classically we use jQuery for writing dynamic client side code. But can we also use a more modern JavaScript framework like ReactJS?

Well, we live in this modern age of web development, were we need tools that compile and minimize our less and JavaScript. Because compilation of JavaScript has become a standard these days. We now have compilers like babel. Babel allows us to compile any JavaScript to a compiled version that works for any modern browser. This allows us to use the newest and latest JavaScript version in any browser.

This revolution opened a whole new world for JavaScript developers. This is also the reason of the continued rise and popularity of JavaScript. Babel transform the old and clunky JavaScript to a more modern and powerful language.

Now, because all of this. We have JavaScript libraries like Angular, Vue.js and ReactJS.  These libraries have raised in popularity, and are in my opinion better alternatives then the old and slow jQuery we have today.

In this article we will use ReactJS. And the only reason for this is simple; it is currently my favorite. This does not mean its the best for every situation. I can only recommend you to dive deeper in the 3 big ones.

So lets get started!

Setting up Symfony

Well we should to start from the beginning; and create a Symfony Skeleton application.

composer create symfony-skeleton SymfonyReactJS

Next we install the basic components for creating a front end. So lets install annotations, twig and asset.

composer require annotations twig asset

Setting up Webpack Encore for React JS

Next we also require webpack encore to compile our JavaSript. Before you can install this,  you need to have node.js and the yarn package manager installed.

When you have done this you can install webpack in your project:

composer require symfony/webpack-encore-pack

And then run yarn install in your root directory. This will install all dependent node modules for webpack encore.

We now have a webpack.config.js file. In this file we can configure webpack. So lets install React JS now.

yarn add react react-dom prop-types babel-preset-react --dev

Now to enable ReactJS in Webpack Encore we need to add .enableReactPreset(); at the bottom of the file.

Then we end up with this:

var Encore = require('@symfony/webpack-encore');

Encore
    // the project directory where compiled assets will be stored
    .setOutputPath('public/build/')
    // the public path used by the web server to access the previous directory
    .setPublicPath('/build')
    .cleanupOutputBeforeBuild()
    .enableSourceMaps(!Encore.isProduction())
    .enableReactPreset();
;

module.exports = Encore.getWebpackConfig();

But off course we also want to use some of the newer JavaScript functions in our ReactJS front end. One of those new features that I’m loving is arrow functions. We can’t use this on our current setup.

We need to install babel-polyfill and babel-preset-env. This will make sure we can use all the latest ES6 features in any browser.

yarn add babel-polyfill babel-preset-env --dev

The in our webpack.config.js file we confure the babel-preset-env.

var Encore = require('@symfony/webpack-encore');

Encore
    // the project directory where compiled assets will be stored
    .setOutputPath('public/build/')
    // the public path used by the web server to access the previous directory
    .setPublicPath('/build')
    .cleanupOutputBeforeBuild()
    .enableSourceMaps(!Encore.isProduction())
    .configureBabel(function(babelConfig) {
      babelConfig.presets.push('env');
    })
    .enableReactPreset();
;

module.exports = Encore.getWebpackConfig();

Now we have setup our Symfony project and webpack to use ReactJS.

Create our first ReactJS page

To start creating our first ReactJS application we need to have a mount point. We can add an index.html.twig and in this add a div with an id of root. We will use this to mount our ReactJS application.

#dashboard/index.html.twig

{% extends 'base.html.twig' %}

{% block body %}
    <div id="root"><div>
{% endblock %}

The next step is to create a simple controller that will render this twig template we created on route. We will look at how we can implement routing together with our ReactJS application in a future blog post.

<?php
namespace App\Controller;


use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

final class DashboardController extends Controller
{
    /**
     * @Route("/", name="dashboard")
     */
    public function dashboard(): Response
    {
        return $this->render('dashboard/index.html.twig');
    }
}

The assets directory in our application is the place where we place our cs and js. So lets create a new file js/app.js and create a simple React JS application that can mount to an element with a id named root.

import React from 'react';
import ReactDOM from 'react-dom';

class App extends React.Component {
  render() {
    return (
      <div>
        <p>Hello</p>
      </div>
    )
  }
}

ReactDOM.render(<App/>, document.getElementById('root'));

We need to add this js file as an entry to our webpack config. This allows webpack encore to know about our js file, and then it can be build using the babel polyfill to support ES6 features in any current browser.

.addEntry('js/app', ['babel-polyfill', './assets/js/app.js'])

To actually start compiling our js code, we need to run yarn encore dev

The compiled javascript code is now build to the build/js directory. We can now include this js file in our twig template.

{% extends 'base.html.twig' %}

{% block body %}
    <div id="root"><div>
{% endblock %}

{% block javascripts %}
    <script type="text/javascript" src="{{ asset('build/js/app.js') }}"></script>
{% endblock %}

Now if you reload the page you will see Hello. You probably don’t use ReactJS just to show hello. We want to make components and create a whole application using ReactJS. We will continue on this next week.

You can find the finished project here.