Alexander-Schranz
Alexander Schranz
Core Developer – Sulu GmbH
Core developer and support king. So dedicated to his work that we couldn't find a hobby to mention.
@alex_s_
2020-11-24

Setting up your Sulu frontend

If you read our new guide to templating in Sulu, you already know you’re free to use your own frontend stack. There’s no default HTML when you install Sulu, and no pre-installed JS libraries. We do this on purpose, but new developers can feel a little bit overwhelmed by all the possibilities. Some say their projects would get started quicker if they had some pointers from the Sulu team.

So without telling you exactly what to do, we’d like to give you a glimpse into the frontend setup we use in our projects. We’ve developed a Twig extension and JavaScript library, and we’re going to show you how they help, how to set them up, and how they’re used in actual code. We’re also going to tell you when we use React vs. the lighter-weight approach outlined here.

WebJS — add event listeners and instantiate third-party JS

WebJS is a library with some very basic JavaScript components. The components cover some of the most common use cases for a website, like:

  1. Event Listeners: when a user clicks, scrolls, or hovers over an element, the Web JS component modifies CSS classes to show, hide, or animate specific content.
  2. Calling third-party libraries: when your website needs a specific library like Google Maps or an image carousel, our Web JS components can invoke them.

Through Web JS, you can avoid loading JavaScript libraries not in use for a particular page. WebJS consists of just 300 lines of code, and is 1.22KB when gzipped, compared to 2.6KB for React, or 38.5KB if you include ReactDOM.This makes WebJS a lightweight alternative to React for simple use cases — things like Google Maps and image sliders.

Web Twig — load JS libraries only where needed

Web Twig is a PHP library that contains several Twig extensions. Here, we will focus on the Twig extension called Component, which integrates with WebJS and gives you a simple and efficient way of handling your JS components in Twig. WebJS tells the Component extension which JS components it’s using, then Component registers them by name on the backend, so it can check whether a JS library is needed for a specific page before loading it.

Web Twig also protects you from one “gotcha” that often thwarts junior developers: if you have two or more of the same element type (such as an image gallery) on a single page, they’ll need different IDs. Web Twig manages this situation automatically, assigning each element a separate ID. That way, a content manager can add as many elements of a single type as needed, while the user interacts with them individually. So when the user clicks on one image gallery, the page’s other image galleries stoically continue going about their business as though nothing has happened.

Another boon: with the HTTP/2 protocol, you can boost performance by preloading libraries. For example, if you need a large third party library, you can split your JS libraries into multiple files. This way, Web Twig can preload the larger files with HTTP/2 only if necessary and load the other files later, as they are needed. 

A general takeaway: If you’re using WebJS, you should use Web Twig, too.

Example: embedding a Google Map

For those who like rolling up their sleeves and getting their hands dirty, here’s a working example of how you can set up a block featuring Google Maps. To follow along and try it out yourself, see our demo project on GitHub.

1. Register the block type “Map” in map.html.twig

<div id="{{ register_component('map', { lat: block.lat, lng: block.lng }) }}"></div>

2. In base.html.twig, ensure only the components that are actually used on the page are loaded. Twig knows which are used because WebJS has told it, and it stores the result in a PHP array.

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Test</title>
</head>
<body>
    {% block content %}{% endblock %}

    {# Embed Third Party JS only when map component is used on this page #}
    {% if 'map' in get_component_list() %}
        <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCPJpjD-qcR_yIxJnS8maR5W9KB0E3EzYI&libraries=&v=weekly"></script>
    {% endif %}

    {# Load custom JS #}
    <script src="/build/website/main.js"></script>

    {# Start used JS components #}
    <script>
        web.startComponents({{ get_components() }});
        web.webServices({{ get_services() }});
    </script>
</body>
</html>

3. In map.js, register the component. This gets registered in the backend.

export default class Map {
    initialize(el, options) {
        this.map = new google.maps.Map(el, {
            center: { lat: options.lat, lng: options.lng },
            zoom: options.zoom ? options.zoom : 8
        });
    }
}

Now that the component is ready to go, your content manager can input the longitude and latitude, which determines the center of the map.

When we use WebJS+Web Twig vs. when we use React

WebJS is great for simpler use cases, like when you need an image slider (we use Slick) or an embedded Google map. We recommend using it when your website has:

  • Minimal communication with server via APIs
  • Little user interaction
  • No complex logic

React works well for intricate user interactions. Use it when your website has:

  • Real-time interaction with the server via APIs
  • Complex application logic in the backend or frontend
  • Many components interacting with one another

Of course you can use whichever library you like, not just React or WebJS — Vue.js, Angular, or Bootstrap would all work well, to name a few.

Which brings us to our next point: you can combine multiple libraries. You could use React only on pages where it’s needed, but avoid loading it on the homepage. Or you can load both React and WebJs on the same page. But if you’re only using React, you don’t need to use Web Twig. You can just invoke it where you need it.

The Allianz Cinema website is a good example of how you can combine both WebJS and React. For order processing, which is more complex, the website uses React (though the menu on the order page is managed by WebJS and Web Twig.) Conversely, the more public-facing pages use WebJS, as there’s no complex logic: they simply display information.

Tell us how you do it

So there you have it: this is the basic frontend setup we start with whenever we have a new project. It’s worked well for us so far. Of course many roads lead to Rome (and Sulu lets you choose which one to take). A lot will depend on your team’s knowledge-base and experience. If you’ve got any hints and tips you’d like to share with us and the community, then please drop by the Slack channel — we’d love to hear them.

Check out our guide to templating in Sulu.