The render pipeline

In Chapter 1, Developing for Drupal 8, when we outlined a high-level example of how Drupal 8 handles a user request in order to turn it into a response, we touched on the notion of a render pipeline. So let's see what this is about, as there are essentially two render pipelines to speak of: the Symfony render pipeline and the Drupal one.

As you know, Drupal 8 uses many Symfony components, one of which being the HTTPKernel component (http://symfony.com/doc/current/components/http_kernel.html). Its main role is to turn a user request (built from PHP super globals into a Request object) into a standardized response object that gets sent back to the user. These objects are defined in the Symfony HTTP Foundation component (http://symfony.com/components/HttpFoundation). To assist in this process, it uses the Event Dispatcher component to dispatch events meant to handle the workload on multiple layers. As we saw, this is what happens in Drupal 8 as well.

Controllers in Drupal 8 can return one of two things—either a Response object directly or a render array. If they return the first, the job is almost done, as the Symfony render pipeline knows exactly what to do with that (assuming the response is correct). However, if they return a render array, the Drupal render pipeline kicks in at a lower level to try to turn that into a Response. We always need a Response.

The kernel.view event is triggered in order to determine who can take care of this render array. Drupal 8 comes with the MainContentViewSubscriber which listens to this event and checks the request format and whether the controller has returned a render array. Based on the former, it instantiates a MainContentRendererInterface object (which, by default—and most of the time—will be the HTML-based HtmlRenderer) and asks it to turn the render array into a Response. Then, it sets the Response onto the event so that the Symfony render pipeline can continue on its merry way.

In addition to the HTML renderer, Drupal 8 comes with a few others that need to handle different types of requests:

Returning to the HTML renderer, let's see what it does to turn our render arrays into actual relevant HTML on a Response object. Without going into too much detail, here is the high-level of what it does:

So, as you see, the render pipeline starts at Symfony level, goes down into Drupal territory when it encounters render arrays, but continues going down to build each component found on a page around the main content returned by the Controller. Then, it comes back up those levels, all the way until a great render array is created and can be turned into HTML. Also, as it goes back up, various metadata can bubble up to the main render array.

I purposefully left out caching from this equation, which although very important, we will cover in a later chapter. However, suffice it to say, cache metadata is one such example that bubbles up from the lower levels all the way to the top and is gathered to determine page-level caching. But more on that later.