When Revinate Marketing™, inGuest™ at that moment, was started couple of years ago, a few choices of technologies were made based on what we have learnt from Reputation™ and Surveys™. PHP 5.3 + Symfony 2.x + Angular1.x was it. With the time being, the idea of single page web app and ReactJs caught our sight, then the banquet with ReactJs started. By building a few micro services in ReactJs as appetizers, we would serve the main course, moving Revinate Marketing™ to ReactJs.

Hybrid Routes

Hybrid routing happens on every frontend migrations. In our case, we have to keep 3 kinds of routes at the same moment:

  • ReactJs single page apps

  • legacy page (angular 1.x)

  • api endpoints (required by both angular and react pages)

The routing is still managed by symfony, but we employed a trick for the reactJs apps to hybrid routing on both symfony and react, which is wild card matching in the symfony routes. Below are the examples we have for reactJs app:

SinglePageAppController
/**
 * @Route("/mgmt/app/{slug}/{subroute}", name="marketing_app", options={"expose"=true}, requirements={"subroute"=".*"}, defaults={"params"=""})
 * @Method({"GET"})
 * @param string $slug
 * @return Response
 */
public function renderApp($slug) {
        $account = $this->getAccount();

        return $this->render('InguestSinglePageAppBundle::app.html.twig');
}

Here we build a single route named "marketing_app". And it contains a wild card subroute and an account identifier which is the slug. So however complex route in the react page, it will return the same base html page. And the url doesn’t have to contain a hashtag in btween, where user can hardly tell that your pages are hybrided.

InguestSinglePageAppBundle::app.html.twig
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="static/guests/style/layout.css"/>
    </head>
    <body>
        <div id="guest-app-container"></div>
        <script type="text/javascript" src="static/guests/bundle.js"></script>
    </body>
</html>

With the route done, the only thing you need is a base html file, doing it in twig should be nothing hard to a symfony developer. The bundle.js and layout.css are the ReactJs js and css files. The files are compiled by webpack, nothing tricky there.

FosRouting in react

FOS(https://github.com/FriendsOfSymfony/FOSJsRoutingBundle) is a very powerful tool we employed for frontend url generation. It builds up an url based on the symfony routing. And it works together with reactJs perfectly.

InguestSinglePageAppBundle::app.html.twig
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="static/guests/style/layout.css"/>

        <script src=""></script>
        <script src=""></script>
    </head>
    <body>
        <div id="guest-app-container"></div>
        <script type="text/javascript" src="static/guests/bundle.js"></script>
    </body>
</html>

To use FOS, just do it as suggested. Simple, isn’t it?

dashboarApi.js
const url = window.Routing.generate('api_property_dashboard_lifetime_revenue', { slug: 'demo' });

Twig variable injection

Twig variable injection is a feature twig input static variables into the dom. To use them in reactJs, we just need to expose them as the global js variables. Now the base html is like below:

InguestSinglePageAppBundle::app.html.twig
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="static/guests/style/layout.css"/>

        <script src=""></script>
        <script src=""></script>

        <script type="text/javascript">
            var globalConfig = ;
            var isFullSpa = true;
        </script>
    </head>
    <body>
        <div id="guest-app-container"></div>
        <script type="text/javascript" src="static/guests/bundle.js"></script>
    </body>
</html>

Multiple react single page apps

In Revinate Marketing’s business, we serve both hotelier users and guest users. Therefore we have something not common to everybody, which is 2 isolated react apps are needed. Doing it is not hard, but just having another base route and then you are all done.

Session handling

Authentication is another challenging thing in the single page app. Luckily, hybrid modal fixes/defers the issue. We used the legacy angular pages for login and once authenticated we will redirect to a react page.

Now our hybrid application works great on production and such design bought us time and buffer to migrate old pages.