SlideShare a Scribd company logo
1 of 54
Download to read offline
lussoluca
How Drupal builds your pages
D10 edition
Luca Lusso
Drupal / PHP / Go developer @ SparkFabrik
Drupal contributor (WebProfiler, Monolog,
Symfony Messenger, …) and speaker
Drupal.org: www.drupal.org/u/lussoluca
Twitter: www.twitter.com/lussoluca
LinkedIn: www.linkedin.com/in/lussoluca
drupal.slack.com: lussoluca
@lussoluca
We are a tech company of engineers,
developers and designers, capable of
accompanying customers step by step
in the CLOUD NATIVE era,
with an agile and pragmatic approach.
We are committed to OPEN SOURCE
and we embrace its philosophy
in our internal practices.
TECHNOLOGY,
STRATEGY AND METHOD
4
5
All Drupal pages are built in the same way:
A Request is received and a Response is
produced
In this session we’ll see how Drupal turns an
HTTP Request into an HTML Response
6
GET /en/forecast/lille HTTP/2 <!DOCTYPE html
>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8" />
<meta
name
="Generator"
content
="Drupal 10 (https://www.drupal.org)
" />
...
</html>
7
➔ Custom module (machine name: weather)
➔ Custom page
➔ Not build using the Node system (even if the flow is
the same, the Node system is too complex to be
analyzed in a short time)
➔ There is a custom Entity called “City” used to store a
description and some geographic coordinates
➔ On this page we retrieve the city, call an external
service to get weather forecasts and build the
output
➔ Demo module repository:
https://github.com/lussoluca/weather
/en/forecast/lille
8
9
In the context of computer programming, instrumentation
refers to the measure of a product's performance, in order
to diagnose errors and to write trace information.
➔ Profiling
➔ Tracing
➔ Logging
Instrumentation
10
➔ New settings page available from Drupal 10.1
➔ /admin/config/development/settings
➔ Useful during inspection and development
➔
Disable optimizations
Profiling: WebProfiler
11
WebProfiler adds a toolbar at the bottom of every page and
shows you all sorts of stats, such as the amount of
database queries loaded on the page, which services are
used, and much more.
Depends on:
➔ Devel
➔ Tracer
https://www.drupal.org/project/webprofiler/
12
index.php
13
➔ Require the Composer
autoload file
➔ Create a new Kernel
➔ Handle the request to build a
response
➔ Return the response
➔ Terminate the Kernel
➔ Front controller pattern
use DrupalCoreDrupalKernel;
use SymfonyComponentHttpFoundationRequest;
$autoloader = require_once 'autoload.php';
$kernel = new DrupalKernel('prod', $autoloader);
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);
➔ https://stackphp.com/
➔ DrupalKernel is decorated by a set of middlewares
Stack middleware
14
DrupalKernel
➔ Ordered by priority desc on request and by priority
asc on response
Stack middleware
15
16
After passing through all the middlewares, the Request is
handled by a router that finds the code responsible for
converting the Request into a Response.
In this case the Request is managed by a Controller:
ForecastController.
Request collector
17
Routing and controllers
➔ weather.routing.yml
➔ Route name: weather.forecast
➔ {city} placeholder
➔ _controller
➔ _title
➔ Requirements
➔ Param converters
Routing
weather.forecast:
path: '/forecast/{city}'
defaults:
_controller: 'DrupalweatherControllerForecastController::page'
_title_callback: 'DrupalweatherControllerForecastController::title'
requirements:
_permission: 'access content'
options:
parameters:
city:
type: 'weather:city'
18
Routes collector
19
Routes collector
Param converters
weather.forecast:
path: '/forecast/{city}'
defaults:
_controller: 'DrupalweatherControllerForecastController::page'
_title_callback: 'DrupalweatherControllerForecastController::title'
requirements:
_permission: 'access content'
options:
parameters:
city:
type: 'weather:city'
The Node module uses the same
technique to upcast the nid to full
Node objects.
20
Param converters
public function applies( $definition , $name, Route $route):bool {
if (!empty($definition ['type']) && $definition ['type'] === 'weather:city' ) {
return TRUE;
}
return FALSE;
}
public function convert( $value, $definition , $name, array $defaults ):?CityInterface
{
$cities = $this
-> entityTypeManager
->getStorage( 'city')
->loadByProperties([ 'label' => $value]);
if (count( $cities) == 0) {
return NULL;
}
return reset($cities);
}
➔ applies is used to check if this
param converter should be
used for this route
➔ convert will takes the value
from the url (lille) and convert
it to something more
structured (typically an
object). If convert return
NULL, Drupal will return a 404
error page.
21
Services collector
22
Services collector
Services collector
23
Database collector
Title callback
weather.forecast:
path: '/forecast/{city}'
defaults:
_controller: 'DrupalweatherControllerForecastController::page'
_title_callback: 'DrupalweatherControllerForecastController::title'
requirements:
_permission: 'access content'
options:
parameters:
city:
type: 'weather:city'
Method used by Drupal to retrieve
the title of a route
24
Title callback
public function title(CityInterface $city): string {
return $this->t('Weather forecast for @city', [
'@city' => $city->label(),
]);
}
➔ Returns a string
➔ Can use the parameters
(upcasted) from the URL
25
Controller callback
weather.forecast:
path: '/forecast/{city}'
defaults:
_controller: 'DrupalweatherControllerForecastController::page'
_title_callback: 'DrupalweatherControllerForecastController::title'
requirements:
_permission: 'access content'
options:
parameters:
city:
type: 'weather:city'
Method used by Drupal to retrieve
the main content of a route
26
Controller callback
public function page(CityInterface $city): array {
$forecast = $this->weatherClient ->getForecastData( $city->label());
$build['content' ] = [
'#theme' => 'weather_forecast' ,
'#forecast' => $forecast ,
'#units' => $this->config( 'weather.settings' )->get('units'),
'#description' => $city->getDescription(),
'#coordinates' => $city->getCoordinates(),
'#cache' => [
'max-age' => 10800, // 3 hours.
'tags' => [
'forecast:' . strtolower( $city->label()),
],
'contexts' => [
'url',
],
],
];
return $build;
}
27
Services
public function page(CityInterface $city): array {
$forecast = $this->weatherClient ->getForecastData( $city->label());
$build['content'] = [
'#theme' => 'weather_forecast',
'#forecast' => $forecast,
'#units' => $this->config('weather.settings')->get('units'),
'#description' => $city->getDescription(),
'#coordinates' => $city->getCoordinates(),
'#cache' => [
'max-age' => 10800, // 3 hours.
'tags' => [
'forecast:' . strtolower($city->label()),
],
'contexts' => [
'url',
],
],
];
return $build;
}
➔ PHP classes to perform some
useful task
◆ Sending email
◆ Authenticate users
◆ Call external services
◆ …
➔ Drupal core has more than 500
services
➔ We’ve seen a couple of them
already:
◆ Middlewares are
services
◆ Param converters are
services
28
Services collector
29
Services collector
30
Http collector
31
➔ Well done! We found that the ForecastController has
the piece of code that render this route!
➔ But wait…
➔ ForecastController returns the title of the page and a
simple array…
◆ Where all this markup comes from?
◆ Where are loaded and placed the blocks (like
the header and the footer)?
◆ How CSS and JavaScript assets are managed?
Entering the Drupal render pipeline
/en/forecast/lille
32
Render pipeline
Render arrays
public function page(CityInterface $city): array {
$forecast = $this->weatherClient->getForecastData($city->label());
$build['content' ] = [
'#theme' => 'weather_forecast' ,
'#forecast' => $forecast ,
'#units' => $this->config( 'weather.settings' )->get('units'),
'#description' => $city->getDescription(),
'#coordinates' => $city->getCoordinates(),
'#cache' => [
'max-age' => 10800, // 3 hours.
'tags' => [
'forecast:' . strtolower( $city->label()),
],
'contexts' => [
'url',
],
],
];
return $build;
}
➔ weather_forecast: theme hook
➔ Keys that starts with ‘#’ are the
properties
➔ Keys that doesn’t start with ‘#’
are nested render arrays
➔ Must declare ‘#cache’
information
33
➔ Where I can find the whole list of
available theme hooks?
➔ Which arguments are available?
Theme registry
"weather_details" => array:6 [ ▶]
"weather_forecast" => array:6 [▼
"variables" => array:4 [▼
"forecast" => []
"units" => "metric"
"description" => ""
"coordinates" => []
]
"type" => "module"
"theme path" => "modules/custom/weather"
"template" => "weather-forecast"
"path" => "modules/custom/weather/templates"
"preprocess functions" => array:2 [▼
0 => "template_preprocess"
1 => "contextual_preprocess"
]
]
"weather_forecast_single" => array:6 [ ▶]
➔ Provided by Devel module (on
/devel/theme/registry)
➔ For each theme hook
◆ List of variables (with
default values)
◆ Path on the filesystem
◆ Template
◆ Proprocess functions
34
Defining a theme hook
function weather_theme(): array {
return [
'weather_forecast' => [
'variables' => [
'forecast' => [],
'units' => 'metric',
'description' => '',
'coordinates' => [],
],
],
];
}
➔ weather.module
➔ List of theme hooks defined by
a module, with a machine
name and a list of accepted
variables (and their default
values)
35
weather-forecast.html.twig
{{ attach_library('
weather/map
') }}
{{ attach_library('
weather/base
') }}
<div class="forecast-list
">
{% for item in forecast.list %}
<div class="forecast-element
">
<h3 class="forecast-element__date
">{{ item.dt_txt|date("
d/m/Y H:i") }}</h3>
<p class="forecast-element__temp
">{{ item.main.temp }} °{{ units == '
metric' ? 'C' : 'F' }}</p>
<p class="forecast-element__description
">{{ item.weather[
0].description|title }}</
p>
<a href="{{ path('weather.details
', {city:forecast.city.name, date:item.dt_txt}) }}" class="use-ajax"
data-dialog-type
="dialog"
data-dialog-options
='{"width":700,"title":"{{ 'Details'|t }}"}'>More info</
a>
</div>
{% endfor %}
</div>
<div class="city-wrapper
">
<div class="city-description
">
{{ description }}
</div>
<div class="city-map">
<div id="map" data-lat="{{ coordinates
.0 }}" data-lng="{{ coordinates
.1 }}"></div>
</div>
</div>
36
Controller output
public function page(CityInterface $city): array {
$forecast = $this->weatherClient->getForecastData($city->label());
$build['content'] = [
'#theme' => 'weather_forecast',
'#forecast' => $forecast,
'#units' => $this->config('weather.settings')->get('units'),
'#description' => $city->getDescription(),
'#coordinates' => $city->getCoordinates(),
'#cache' => [
'max-age' => 10800, // 3 hours.
'tags' => [
'forecast:' . strtolower($city->label()),
],
'contexts' => [
'url',
],
],
];
return $build;
}
➔ Controllers return a render
array most of the time
➔ This is still not a Response
37
Drupal uses the render array returned from a controller to
fill the main page content.
We now need to understand how Drupal builds the render
array for the whole page and how it turns it into an HTML
response.
But at this point, even if you follow the source code, it’s
challenging to understand where the conversion
happens.
Controller output
A lot of systems in Drupal are loosely coupled and the
communications between them happens through the
event system.
When a controller returns something different from a
Response object, the Drupal Kernel takes the render
array and dispatches a kernel.view event.
38
How we discover that?
By tracing our page!
Tracing: o11y
39
➔ Observability suite
➔ Uses data collected by the Tracer module
➔ https://www.drupal.org/project/o11y/
➔ https://www.slideshare.net/sparkfabrik/do-you-kn
ow-what-your-drupal-is-doing-observe-it-drupalco
n-prague-2022
Drupal timeline
40
Events collector
41
$request = $event->getRequest();
$result = $event->getControllerResult();
// Render the controller result into a response if it's a render array.
if (
is_array($result) &&
($request->query->has(static::WRAPPER_FORMAT) || $request->getRequestFormat() == 'html')) {
$wrapper = $request->query->get(static::WRAPPER_FORMAT, 'html');
...
$renderer = $this->classResolver->getInstanceFromDefinition($this->mainContentRenderers[$wrapper]);
$response = $renderer->renderResponse($result, $request, $this->routeMatch);
...
$event->setResponse($response);
}
42
MainContentViewSubscriber
Events collector
43
foreach (
$this->blockRepository
->getVisibleBlocksPerRegion( $cacheable_metadata_list ) as $region => $blocks) {
/** @var DrupalblockBlockInterface [] $blocks */
foreach ($blocks as $key => $block) {
$block_plugin = $block->getPlugin();
if ($block_plugin instanceof MainContentBlockPluginInterface ) {
$block_plugin ->setMainContent( $this->mainContent );
$main_content_block_displayed = TRUE;
}
elseif ($block_plugin instanceof TitleBlockPluginInterface ) {
$block_plugin ->setTitle( $this->title);
}
elseif ($block_plugin instanceof MessagesBlockPluginInterface ) {
$messages_block_displayed = TRUE;
}
$build[$region][$key] = $this->blockViewBuilder ->view($block);
...
44
➔ Builds a render array with all
the visible blocks
BlockPageVariant
Blocks collector
45
index.php
46
Finally, the full HTML has been built.
The latest steps are to send the
response back to the browser and to
terminate the kernel.
use DrupalCoreDrupalKernel;
use SymfonyComponentHttpFoundationRequest;
$autoloader = require_once 'autoload.php';
$kernel = new DrupalKernel('prod', $autoloader);
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);
47
Theme collector - Rendering Call Graph
48
Theme collector - Twig filters
49
Asset collector - Libraries
50
➔ Theme collector lists SDC components
➔ Frontend collector shows Core Web Vitals information (on Chrome)
➔ Ajax collector lists ajax calls made from a page
➔ Some pages are forms or views, you can inspect them too
➔ WebProfiler collects redirects and forwards
➔ WebProfiler collects sub-requests made by BigPipe
https://tech.sparkfabrik.com/en/blog/drupal-sdc/
https://tech.sparkfabrik.com/en/blog/webprofiler_updates/
Discover more
51
Chapter 1 - Setting Up a Local Environment
…
Chapter 3 - How Drupal Renders an HTML Page
Chapter 4 - Mapping the Design to Drupal Components
…
Chapter 11 - Single Directory Components
…
Chapter 15 - Building a Decoupled Frontend
Learn more
Join us for
contribution opportunities
17-20 October, 2023
Room 4.1 & 4.2
Mentored
Contribution
First Time
Contributor Workshop
General
Contribution
#DrupalContributions
17 - 20 October: 9:00 - 18:00
Room 4.1
17 October: 17:15 - 18:00
Room 2.4
18 October : 10:30 - 11:15
Room 2.4
20 October : 09:00 - 12:30
Room 4.2
20 October : 09:00 – 18:00
Room 4.2
What did you think?
Please fill in this session survey directly from the Mobile App.
We appreciate your feedback!
Please take a moment to fill out:
the Individual
session surveys
(in the Mobile App or
QR code at the entrance of each room)
1 2
the general
conference survey
Flash the QR code
OR
It will be sent by email

More Related Content

Similar to Drupalcon 2023 - How Drupal builds your pages.pdf

Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworksdiego_k
 
Curscatalyst
CurscatalystCurscatalyst
CurscatalystKar Juan
 
CodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkCodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkBo-Yi Wu
 
What's New In Laravel 5
What's New In Laravel 5What's New In Laravel 5
What's New In Laravel 5Darren Craig
 
Andy Postnikov - Drupal 7 vs Drupal 8: от бутстрапа до рендера
Andy Postnikov - Drupal 7 vs Drupal 8: от бутстрапа до рендераAndy Postnikov - Drupal 7 vs Drupal 8: от бутстрапа до рендера
Andy Postnikov - Drupal 7 vs Drupal 8: от бутстрапа до рендераLEDC 2016
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsMichael Peacock
 
Auto-loading of Drupal CCK Nodes
Auto-loading of Drupal CCK NodesAuto-loading of Drupal CCK Nodes
Auto-loading of Drupal CCK Nodesnihiliad
 
Convert modules from 6.x to 7.x
Convert modules from 6.x to 7.xConvert modules from 6.x to 7.x
Convert modules from 6.x to 7.xJoão Ventura
 
Automating Drupal Development: Makefiles, features and beyond
Automating Drupal Development: Makefiles, features and beyondAutomating Drupal Development: Makefiles, features and beyond
Automating Drupal Development: Makefiles, features and beyondNuvole
 
Drupal 8 simple page: Mi primer proyecto en Drupal 8.
Drupal 8 simple page: Mi primer proyecto en Drupal 8.Drupal 8 simple page: Mi primer proyecto en Drupal 8.
Drupal 8 simple page: Mi primer proyecto en Drupal 8.Samuel Solís Fuentes
 
Lviv 2013 d7 vs d8
Lviv 2013 d7 vs d8Lviv 2013 d7 vs d8
Lviv 2013 d7 vs d8Skilld
 
Михаил Крайнюк - Form API + Drupal 8: Form and AJAX
Михаил Крайнюк - Form API + Drupal 8: Form and AJAXМихаил Крайнюк - Form API + Drupal 8: Form and AJAX
Михаил Крайнюк - Form API + Drupal 8: Form and AJAXDrupalSib
 
Getting Started with Capistrano
Getting Started with CapistranoGetting Started with Capistrano
Getting Started with CapistranoLaunchAny
 

Similar to Drupalcon 2023 - How Drupal builds your pages.pdf (20)

Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworks
 
Curscatalyst
CurscatalystCurscatalyst
Curscatalyst
 
CodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkCodeIgniter PHP MVC Framework
CodeIgniter PHP MVC Framework
 
What's New In Laravel 5
What's New In Laravel 5What's New In Laravel 5
What's New In Laravel 5
 
Andy Postnikov - Drupal 7 vs Drupal 8: от бутстрапа до рендера
Andy Postnikov - Drupal 7 vs Drupal 8: от бутстрапа до рендераAndy Postnikov - Drupal 7 vs Drupal 8: от бутстрапа до рендера
Andy Postnikov - Drupal 7 vs Drupal 8: от бутстрапа до рендера
 
Lviv 2013 d7 vs d8
Lviv 2013   d7 vs d8Lviv 2013   d7 vs d8
Lviv 2013 d7 vs d8
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friends
 
Drupal 8 Services
Drupal 8 ServicesDrupal 8 Services
Drupal 8 Services
 
Auto-loading of Drupal CCK Nodes
Auto-loading of Drupal CCK NodesAuto-loading of Drupal CCK Nodes
Auto-loading of Drupal CCK Nodes
 
Introduction to angular js
Introduction to angular jsIntroduction to angular js
Introduction to angular js
 
Convert modules from 6.x to 7.x
Convert modules from 6.x to 7.xConvert modules from 6.x to 7.x
Convert modules from 6.x to 7.x
 
Automating Drupal Development: Makefiles, features and beyond
Automating Drupal Development: Makefiles, features and beyondAutomating Drupal Development: Makefiles, features and beyond
Automating Drupal Development: Makefiles, features and beyond
 
Drupal 8 simple page: Mi primer proyecto en Drupal 8.
Drupal 8 simple page: Mi primer proyecto en Drupal 8.Drupal 8 simple page: Mi primer proyecto en Drupal 8.
Drupal 8 simple page: Mi primer proyecto en Drupal 8.
 
Cache metadata
Cache metadataCache metadata
Cache metadata
 
Silex Cheat Sheet
Silex Cheat SheetSilex Cheat Sheet
Silex Cheat Sheet
 
Silex Cheat Sheet
Silex Cheat SheetSilex Cheat Sheet
Silex Cheat Sheet
 
Lviv 2013 d7 vs d8
Lviv 2013 d7 vs d8Lviv 2013 d7 vs d8
Lviv 2013 d7 vs d8
 
Михаил Крайнюк - Form API + Drupal 8: Form and AJAX
Михаил Крайнюк - Form API + Drupal 8: Form and AJAXМихаил Крайнюк - Form API + Drupal 8: Form and AJAX
Михаил Крайнюк - Form API + Drupal 8: Form and AJAX
 
Drupal 8 migrate!
Drupal 8 migrate!Drupal 8 migrate!
Drupal 8 migrate!
 
Getting Started with Capistrano
Getting Started with CapistranoGetting Started with Capistrano
Getting Started with Capistrano
 

Recently uploaded

Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝soniya singh
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
cybersecurity notes for mca students for learning
cybersecurity notes for mca students for learningcybersecurity notes for mca students for learning
cybersecurity notes for mca students for learningVitsRangannavar
 
Engage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyEngage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyFrank van der Linden
 

Recently uploaded (20)

Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
cybersecurity notes for mca students for learning
cybersecurity notes for mca students for learningcybersecurity notes for mca students for learning
cybersecurity notes for mca students for learning
 
Engage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyEngage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The Ugly
 

Drupalcon 2023 - How Drupal builds your pages.pdf

  • 1.
  • 2. lussoluca How Drupal builds your pages D10 edition
  • 3. Luca Lusso Drupal / PHP / Go developer @ SparkFabrik Drupal contributor (WebProfiler, Monolog, Symfony Messenger, …) and speaker Drupal.org: www.drupal.org/u/lussoluca Twitter: www.twitter.com/lussoluca LinkedIn: www.linkedin.com/in/lussoluca drupal.slack.com: lussoluca @lussoluca
  • 4. We are a tech company of engineers, developers and designers, capable of accompanying customers step by step in the CLOUD NATIVE era, with an agile and pragmatic approach. We are committed to OPEN SOURCE and we embrace its philosophy in our internal practices. TECHNOLOGY, STRATEGY AND METHOD 4
  • 5. 5 All Drupal pages are built in the same way: A Request is received and a Response is produced In this session we’ll see how Drupal turns an HTTP Request into an HTML Response
  • 6. 6 GET /en/forecast/lille HTTP/2 <!DOCTYPE html > <html lang="en" dir="ltr"> <head> <meta charset="utf-8" /> <meta name ="Generator" content ="Drupal 10 (https://www.drupal.org) " /> ... </html>
  • 7. 7 ➔ Custom module (machine name: weather) ➔ Custom page ➔ Not build using the Node system (even if the flow is the same, the Node system is too complex to be analyzed in a short time) ➔ There is a custom Entity called “City” used to store a description and some geographic coordinates ➔ On this page we retrieve the city, call an external service to get weather forecasts and build the output ➔ Demo module repository: https://github.com/lussoluca/weather /en/forecast/lille
  • 8. 8
  • 9. 9 In the context of computer programming, instrumentation refers to the measure of a product's performance, in order to diagnose errors and to write trace information. ➔ Profiling ➔ Tracing ➔ Logging Instrumentation
  • 10. 10 ➔ New settings page available from Drupal 10.1 ➔ /admin/config/development/settings ➔ Useful during inspection and development ➔ Disable optimizations
  • 11. Profiling: WebProfiler 11 WebProfiler adds a toolbar at the bottom of every page and shows you all sorts of stats, such as the amount of database queries loaded on the page, which services are used, and much more. Depends on: ➔ Devel ➔ Tracer https://www.drupal.org/project/webprofiler/
  • 12. 12
  • 13. index.php 13 ➔ Require the Composer autoload file ➔ Create a new Kernel ➔ Handle the request to build a response ➔ Return the response ➔ Terminate the Kernel ➔ Front controller pattern use DrupalCoreDrupalKernel; use SymfonyComponentHttpFoundationRequest; $autoloader = require_once 'autoload.php'; $kernel = new DrupalKernel('prod', $autoloader); $request = Request::createFromGlobals(); $response = $kernel->handle($request); $response->send(); $kernel->terminate($request, $response);
  • 14. ➔ https://stackphp.com/ ➔ DrupalKernel is decorated by a set of middlewares Stack middleware 14 DrupalKernel
  • 15. ➔ Ordered by priority desc on request and by priority asc on response Stack middleware 15
  • 16. 16 After passing through all the middlewares, the Request is handled by a router that finds the code responsible for converting the Request into a Response. In this case the Request is managed by a Controller: ForecastController. Request collector
  • 18. ➔ weather.routing.yml ➔ Route name: weather.forecast ➔ {city} placeholder ➔ _controller ➔ _title ➔ Requirements ➔ Param converters Routing weather.forecast: path: '/forecast/{city}' defaults: _controller: 'DrupalweatherControllerForecastController::page' _title_callback: 'DrupalweatherControllerForecastController::title' requirements: _permission: 'access content' options: parameters: city: type: 'weather:city' 18
  • 20. Param converters weather.forecast: path: '/forecast/{city}' defaults: _controller: 'DrupalweatherControllerForecastController::page' _title_callback: 'DrupalweatherControllerForecastController::title' requirements: _permission: 'access content' options: parameters: city: type: 'weather:city' The Node module uses the same technique to upcast the nid to full Node objects. 20
  • 21. Param converters public function applies( $definition , $name, Route $route):bool { if (!empty($definition ['type']) && $definition ['type'] === 'weather:city' ) { return TRUE; } return FALSE; } public function convert( $value, $definition , $name, array $defaults ):?CityInterface { $cities = $this -> entityTypeManager ->getStorage( 'city') ->loadByProperties([ 'label' => $value]); if (count( $cities) == 0) { return NULL; } return reset($cities); } ➔ applies is used to check if this param converter should be used for this route ➔ convert will takes the value from the url (lille) and convert it to something more structured (typically an object). If convert return NULL, Drupal will return a 404 error page. 21
  • 24. Title callback weather.forecast: path: '/forecast/{city}' defaults: _controller: 'DrupalweatherControllerForecastController::page' _title_callback: 'DrupalweatherControllerForecastController::title' requirements: _permission: 'access content' options: parameters: city: type: 'weather:city' Method used by Drupal to retrieve the title of a route 24
  • 25. Title callback public function title(CityInterface $city): string { return $this->t('Weather forecast for @city', [ '@city' => $city->label(), ]); } ➔ Returns a string ➔ Can use the parameters (upcasted) from the URL 25
  • 26. Controller callback weather.forecast: path: '/forecast/{city}' defaults: _controller: 'DrupalweatherControllerForecastController::page' _title_callback: 'DrupalweatherControllerForecastController::title' requirements: _permission: 'access content' options: parameters: city: type: 'weather:city' Method used by Drupal to retrieve the main content of a route 26
  • 27. Controller callback public function page(CityInterface $city): array { $forecast = $this->weatherClient ->getForecastData( $city->label()); $build['content' ] = [ '#theme' => 'weather_forecast' , '#forecast' => $forecast , '#units' => $this->config( 'weather.settings' )->get('units'), '#description' => $city->getDescription(), '#coordinates' => $city->getCoordinates(), '#cache' => [ 'max-age' => 10800, // 3 hours. 'tags' => [ 'forecast:' . strtolower( $city->label()), ], 'contexts' => [ 'url', ], ], ]; return $build; } 27
  • 28. Services public function page(CityInterface $city): array { $forecast = $this->weatherClient ->getForecastData( $city->label()); $build['content'] = [ '#theme' => 'weather_forecast', '#forecast' => $forecast, '#units' => $this->config('weather.settings')->get('units'), '#description' => $city->getDescription(), '#coordinates' => $city->getCoordinates(), '#cache' => [ 'max-age' => 10800, // 3 hours. 'tags' => [ 'forecast:' . strtolower($city->label()), ], 'contexts' => [ 'url', ], ], ]; return $build; } ➔ PHP classes to perform some useful task ◆ Sending email ◆ Authenticate users ◆ Call external services ◆ … ➔ Drupal core has more than 500 services ➔ We’ve seen a couple of them already: ◆ Middlewares are services ◆ Param converters are services 28
  • 31. 31 ➔ Well done! We found that the ForecastController has the piece of code that render this route! ➔ But wait… ➔ ForecastController returns the title of the page and a simple array… ◆ Where all this markup comes from? ◆ Where are loaded and placed the blocks (like the header and the footer)? ◆ How CSS and JavaScript assets are managed? Entering the Drupal render pipeline /en/forecast/lille
  • 33. Render arrays public function page(CityInterface $city): array { $forecast = $this->weatherClient->getForecastData($city->label()); $build['content' ] = [ '#theme' => 'weather_forecast' , '#forecast' => $forecast , '#units' => $this->config( 'weather.settings' )->get('units'), '#description' => $city->getDescription(), '#coordinates' => $city->getCoordinates(), '#cache' => [ 'max-age' => 10800, // 3 hours. 'tags' => [ 'forecast:' . strtolower( $city->label()), ], 'contexts' => [ 'url', ], ], ]; return $build; } ➔ weather_forecast: theme hook ➔ Keys that starts with ‘#’ are the properties ➔ Keys that doesn’t start with ‘#’ are nested render arrays ➔ Must declare ‘#cache’ information 33 ➔ Where I can find the whole list of available theme hooks? ➔ Which arguments are available?
  • 34. Theme registry "weather_details" => array:6 [ ▶] "weather_forecast" => array:6 [▼ "variables" => array:4 [▼ "forecast" => [] "units" => "metric" "description" => "" "coordinates" => [] ] "type" => "module" "theme path" => "modules/custom/weather" "template" => "weather-forecast" "path" => "modules/custom/weather/templates" "preprocess functions" => array:2 [▼ 0 => "template_preprocess" 1 => "contextual_preprocess" ] ] "weather_forecast_single" => array:6 [ ▶] ➔ Provided by Devel module (on /devel/theme/registry) ➔ For each theme hook ◆ List of variables (with default values) ◆ Path on the filesystem ◆ Template ◆ Proprocess functions 34
  • 35. Defining a theme hook function weather_theme(): array { return [ 'weather_forecast' => [ 'variables' => [ 'forecast' => [], 'units' => 'metric', 'description' => '', 'coordinates' => [], ], ], ]; } ➔ weather.module ➔ List of theme hooks defined by a module, with a machine name and a list of accepted variables (and their default values) 35
  • 36. weather-forecast.html.twig {{ attach_library(' weather/map ') }} {{ attach_library(' weather/base ') }} <div class="forecast-list "> {% for item in forecast.list %} <div class="forecast-element "> <h3 class="forecast-element__date ">{{ item.dt_txt|date(" d/m/Y H:i") }}</h3> <p class="forecast-element__temp ">{{ item.main.temp }} °{{ units == ' metric' ? 'C' : 'F' }}</p> <p class="forecast-element__description ">{{ item.weather[ 0].description|title }}</ p> <a href="{{ path('weather.details ', {city:forecast.city.name, date:item.dt_txt}) }}" class="use-ajax" data-dialog-type ="dialog" data-dialog-options ='{"width":700,"title":"{{ 'Details'|t }}"}'>More info</ a> </div> {% endfor %} </div> <div class="city-wrapper "> <div class="city-description "> {{ description }} </div> <div class="city-map"> <div id="map" data-lat="{{ coordinates .0 }}" data-lng="{{ coordinates .1 }}"></div> </div> </div> 36
  • 37. Controller output public function page(CityInterface $city): array { $forecast = $this->weatherClient->getForecastData($city->label()); $build['content'] = [ '#theme' => 'weather_forecast', '#forecast' => $forecast, '#units' => $this->config('weather.settings')->get('units'), '#description' => $city->getDescription(), '#coordinates' => $city->getCoordinates(), '#cache' => [ 'max-age' => 10800, // 3 hours. 'tags' => [ 'forecast:' . strtolower($city->label()), ], 'contexts' => [ 'url', ], ], ]; return $build; } ➔ Controllers return a render array most of the time ➔ This is still not a Response 37
  • 38. Drupal uses the render array returned from a controller to fill the main page content. We now need to understand how Drupal builds the render array for the whole page and how it turns it into an HTML response. But at this point, even if you follow the source code, it’s challenging to understand where the conversion happens. Controller output A lot of systems in Drupal are loosely coupled and the communications between them happens through the event system. When a controller returns something different from a Response object, the Drupal Kernel takes the render array and dispatches a kernel.view event. 38 How we discover that? By tracing our page!
  • 39. Tracing: o11y 39 ➔ Observability suite ➔ Uses data collected by the Tracer module ➔ https://www.drupal.org/project/o11y/ ➔ https://www.slideshare.net/sparkfabrik/do-you-kn ow-what-your-drupal-is-doing-observe-it-drupalco n-prague-2022
  • 42. $request = $event->getRequest(); $result = $event->getControllerResult(); // Render the controller result into a response if it's a render array. if ( is_array($result) && ($request->query->has(static::WRAPPER_FORMAT) || $request->getRequestFormat() == 'html')) { $wrapper = $request->query->get(static::WRAPPER_FORMAT, 'html'); ... $renderer = $this->classResolver->getInstanceFromDefinition($this->mainContentRenderers[$wrapper]); $response = $renderer->renderResponse($result, $request, $this->routeMatch); ... $event->setResponse($response); } 42 MainContentViewSubscriber
  • 44. foreach ( $this->blockRepository ->getVisibleBlocksPerRegion( $cacheable_metadata_list ) as $region => $blocks) { /** @var DrupalblockBlockInterface [] $blocks */ foreach ($blocks as $key => $block) { $block_plugin = $block->getPlugin(); if ($block_plugin instanceof MainContentBlockPluginInterface ) { $block_plugin ->setMainContent( $this->mainContent ); $main_content_block_displayed = TRUE; } elseif ($block_plugin instanceof TitleBlockPluginInterface ) { $block_plugin ->setTitle( $this->title); } elseif ($block_plugin instanceof MessagesBlockPluginInterface ) { $messages_block_displayed = TRUE; } $build[$region][$key] = $this->blockViewBuilder ->view($block); ... 44 ➔ Builds a render array with all the visible blocks BlockPageVariant
  • 46. index.php 46 Finally, the full HTML has been built. The latest steps are to send the response back to the browser and to terminate the kernel. use DrupalCoreDrupalKernel; use SymfonyComponentHttpFoundationRequest; $autoloader = require_once 'autoload.php'; $kernel = new DrupalKernel('prod', $autoloader); $request = Request::createFromGlobals(); $response = $kernel->handle($request); $response->send(); $kernel->terminate($request, $response);
  • 47. 47 Theme collector - Rendering Call Graph
  • 48. 48 Theme collector - Twig filters
  • 49. 49 Asset collector - Libraries
  • 50. 50 ➔ Theme collector lists SDC components ➔ Frontend collector shows Core Web Vitals information (on Chrome) ➔ Ajax collector lists ajax calls made from a page ➔ Some pages are forms or views, you can inspect them too ➔ WebProfiler collects redirects and forwards ➔ WebProfiler collects sub-requests made by BigPipe https://tech.sparkfabrik.com/en/blog/drupal-sdc/ https://tech.sparkfabrik.com/en/blog/webprofiler_updates/ Discover more
  • 51. 51 Chapter 1 - Setting Up a Local Environment … Chapter 3 - How Drupal Renders an HTML Page Chapter 4 - Mapping the Design to Drupal Components … Chapter 11 - Single Directory Components … Chapter 15 - Building a Decoupled Frontend Learn more
  • 52. Join us for contribution opportunities 17-20 October, 2023 Room 4.1 & 4.2 Mentored Contribution First Time Contributor Workshop General Contribution #DrupalContributions 17 - 20 October: 9:00 - 18:00 Room 4.1 17 October: 17:15 - 18:00 Room 2.4 18 October : 10:30 - 11:15 Room 2.4 20 October : 09:00 - 12:30 Room 4.2 20 October : 09:00 – 18:00 Room 4.2
  • 53. What did you think? Please fill in this session survey directly from the Mobile App.
  • 54. We appreciate your feedback! Please take a moment to fill out: the Individual session surveys (in the Mobile App or QR code at the entrance of each room) 1 2 the general conference survey Flash the QR code OR It will be sent by email