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 2023 - Drupalcon - How Drupal builds your pages

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
 
What's new in the Drupal 7 API?
What's new in the Drupal 7 API?What's new in the Drupal 7 API?
What's new in the Drupal 7 API?Alexandru Badiu
 

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

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
 
What's new in the Drupal 7 API?
What's new in the Drupal 7 API?What's new in the Drupal 7 API?
What's new in the Drupal 7 API?
 

More from sparkfabrik

KCD Italy 2023 - Secure Software Supply chain for OCI Artifact on Kubernetes
KCD Italy 2023 - Secure Software Supply chain for OCI Artifact on KubernetesKCD Italy 2023 - Secure Software Supply chain for OCI Artifact on Kubernetes
KCD Italy 2023 - Secure Software Supply chain for OCI Artifact on Kubernetessparkfabrik
 
20231129 - Platform @ localhost 2023 - Application-driven infrastructure with...
20231129 - Platform @ localhost 2023 - Application-driven infrastructure with...20231129 - Platform @ localhost 2023 - Application-driven infrastructure with...
20231129 - Platform @ localhost 2023 - Application-driven infrastructure with...sparkfabrik
 
IAD 2023 - 22 Years of Agile and all I got is this lousy t-shirt
IAD 2023 - 22 Years of Agile and all I got is this lousy t-shirtIAD 2023 - 22 Years of Agile and all I got is this lousy t-shirt
IAD 2023 - 22 Years of Agile and all I got is this lousy t-shirtsparkfabrik
 
2023 - TAC23 - Agile HR - Racconti dal fronte
2023 - TAC23 - Agile HR - Racconti dal fronte2023 - TAC23 - Agile HR - Racconti dal fronte
2023 - TAC23 - Agile HR - Racconti dal frontesparkfabrik
 
CodeMotion 2023 - Deep dive nella supply chain della nostra infrastruttura cl...
CodeMotion 2023 - Deep dive nella supply chain della nostra infrastruttura cl...CodeMotion 2023 - Deep dive nella supply chain della nostra infrastruttura cl...
CodeMotion 2023 - Deep dive nella supply chain della nostra infrastruttura cl...sparkfabrik
 
What is the Secure Supply Chain and the Current State of the PHP Ecosystem
What is the Secure Supply Chain and the Current State of the PHP EcosystemWhat is the Secure Supply Chain and the Current State of the PHP Ecosystem
What is the Secure Supply Chain and the Current State of the PHP Ecosystemsparkfabrik
 
UX e Web sostenibile (UXday 2023).pdf
UX e Web sostenibile (UXday 2023).pdfUX e Web sostenibile (UXday 2023).pdf
UX e Web sostenibile (UXday 2023).pdfsparkfabrik
 
Drupal Dev Days Vienna 2023 - What is the secure software supply chain and th...
Drupal Dev Days Vienna 2023 - What is the secure software supply chain and th...Drupal Dev Days Vienna 2023 - What is the secure software supply chain and th...
Drupal Dev Days Vienna 2023 - What is the secure software supply chain and th...sparkfabrik
 
Deep dive nella supply chain della nostra infrastruttura cloud
Deep dive nella supply chain della nostra infrastruttura cloudDeep dive nella supply chain della nostra infrastruttura cloud
Deep dive nella supply chain della nostra infrastruttura cloudsparkfabrik
 
KCD Italy 2022 - Application driven infrastructure with Crossplane
KCD Italy 2022 - Application driven infrastructure with CrossplaneKCD Italy 2022 - Application driven infrastructure with Crossplane
KCD Italy 2022 - Application driven infrastructure with Crossplanesparkfabrik
 
Come Drupal costruisce le tue pagine
Come Drupal costruisce le tue pagineCome Drupal costruisce le tue pagine
Come Drupal costruisce le tue paginesparkfabrik
 
Drupal 10: un framework PHP di sviluppo Cloud Native moderno
Drupal 10: un framework PHP di sviluppo Cloud Native modernoDrupal 10: un framework PHP di sviluppo Cloud Native moderno
Drupal 10: un framework PHP di sviluppo Cloud Native modernosparkfabrik
 
Do you know what your Drupal is doing Observe it! (DrupalCon Prague 2022)
Do you know what your Drupal is doing Observe it! (DrupalCon Prague 2022)Do you know what your Drupal is doing Observe it! (DrupalCon Prague 2022)
Do you know what your Drupal is doing Observe it! (DrupalCon Prague 2022)sparkfabrik
 
Do you know what your Drupal is doing_ Observe it!
Do you know what your Drupal is doing_ Observe it!Do you know what your Drupal is doing_ Observe it!
Do you know what your Drupal is doing_ Observe it!sparkfabrik
 
Progettare e sviluppare soluzioni serverless con AWS
Progettare e sviluppare soluzioni serverless con AWSProgettare e sviluppare soluzioni serverless con AWS
Progettare e sviluppare soluzioni serverless con AWSsparkfabrik
 
From React to React Native - Things I wish I knew when I started
From React to React Native - Things I wish I knew when I startedFrom React to React Native - Things I wish I knew when I started
From React to React Native - Things I wish I knew when I startedsparkfabrik
 
Headless Drupal: A modern approach to (micro)services and APIs
Headless Drupal: A modern approach to (micro)services and APIsHeadless Drupal: A modern approach to (micro)services and APIs
Headless Drupal: A modern approach to (micro)services and APIssparkfabrik
 
Cloud-Native Drupal: a survival guide
Cloud-Native Drupal: a survival guideCloud-Native Drupal: a survival guide
Cloud-Native Drupal: a survival guidesparkfabrik
 
Mobile Development: una introduzione per Web Developers
Mobile Development: una introduzione per Web DevelopersMobile Development: una introduzione per Web Developers
Mobile Development: una introduzione per Web Developerssparkfabrik
 
Retro gaming machine made with Javascript and Kubernetes
Retro gaming machine made with Javascript and Kubernetes Retro gaming machine made with Javascript and Kubernetes
Retro gaming machine made with Javascript and Kubernetes sparkfabrik
 

More from sparkfabrik (20)

KCD Italy 2023 - Secure Software Supply chain for OCI Artifact on Kubernetes
KCD Italy 2023 - Secure Software Supply chain for OCI Artifact on KubernetesKCD Italy 2023 - Secure Software Supply chain for OCI Artifact on Kubernetes
KCD Italy 2023 - Secure Software Supply chain for OCI Artifact on Kubernetes
 
20231129 - Platform @ localhost 2023 - Application-driven infrastructure with...
20231129 - Platform @ localhost 2023 - Application-driven infrastructure with...20231129 - Platform @ localhost 2023 - Application-driven infrastructure with...
20231129 - Platform @ localhost 2023 - Application-driven infrastructure with...
 
IAD 2023 - 22 Years of Agile and all I got is this lousy t-shirt
IAD 2023 - 22 Years of Agile and all I got is this lousy t-shirtIAD 2023 - 22 Years of Agile and all I got is this lousy t-shirt
IAD 2023 - 22 Years of Agile and all I got is this lousy t-shirt
 
2023 - TAC23 - Agile HR - Racconti dal fronte
2023 - TAC23 - Agile HR - Racconti dal fronte2023 - TAC23 - Agile HR - Racconti dal fronte
2023 - TAC23 - Agile HR - Racconti dal fronte
 
CodeMotion 2023 - Deep dive nella supply chain della nostra infrastruttura cl...
CodeMotion 2023 - Deep dive nella supply chain della nostra infrastruttura cl...CodeMotion 2023 - Deep dive nella supply chain della nostra infrastruttura cl...
CodeMotion 2023 - Deep dive nella supply chain della nostra infrastruttura cl...
 
What is the Secure Supply Chain and the Current State of the PHP Ecosystem
What is the Secure Supply Chain and the Current State of the PHP EcosystemWhat is the Secure Supply Chain and the Current State of the PHP Ecosystem
What is the Secure Supply Chain and the Current State of the PHP Ecosystem
 
UX e Web sostenibile (UXday 2023).pdf
UX e Web sostenibile (UXday 2023).pdfUX e Web sostenibile (UXday 2023).pdf
UX e Web sostenibile (UXday 2023).pdf
 
Drupal Dev Days Vienna 2023 - What is the secure software supply chain and th...
Drupal Dev Days Vienna 2023 - What is the secure software supply chain and th...Drupal Dev Days Vienna 2023 - What is the secure software supply chain and th...
Drupal Dev Days Vienna 2023 - What is the secure software supply chain and th...
 
Deep dive nella supply chain della nostra infrastruttura cloud
Deep dive nella supply chain della nostra infrastruttura cloudDeep dive nella supply chain della nostra infrastruttura cloud
Deep dive nella supply chain della nostra infrastruttura cloud
 
KCD Italy 2022 - Application driven infrastructure with Crossplane
KCD Italy 2022 - Application driven infrastructure with CrossplaneKCD Italy 2022 - Application driven infrastructure with Crossplane
KCD Italy 2022 - Application driven infrastructure with Crossplane
 
Come Drupal costruisce le tue pagine
Come Drupal costruisce le tue pagineCome Drupal costruisce le tue pagine
Come Drupal costruisce le tue pagine
 
Drupal 10: un framework PHP di sviluppo Cloud Native moderno
Drupal 10: un framework PHP di sviluppo Cloud Native modernoDrupal 10: un framework PHP di sviluppo Cloud Native moderno
Drupal 10: un framework PHP di sviluppo Cloud Native moderno
 
Do you know what your Drupal is doing Observe it! (DrupalCon Prague 2022)
Do you know what your Drupal is doing Observe it! (DrupalCon Prague 2022)Do you know what your Drupal is doing Observe it! (DrupalCon Prague 2022)
Do you know what your Drupal is doing Observe it! (DrupalCon Prague 2022)
 
Do you know what your Drupal is doing_ Observe it!
Do you know what your Drupal is doing_ Observe it!Do you know what your Drupal is doing_ Observe it!
Do you know what your Drupal is doing_ Observe it!
 
Progettare e sviluppare soluzioni serverless con AWS
Progettare e sviluppare soluzioni serverless con AWSProgettare e sviluppare soluzioni serverless con AWS
Progettare e sviluppare soluzioni serverless con AWS
 
From React to React Native - Things I wish I knew when I started
From React to React Native - Things I wish I knew when I startedFrom React to React Native - Things I wish I knew when I started
From React to React Native - Things I wish I knew when I started
 
Headless Drupal: A modern approach to (micro)services and APIs
Headless Drupal: A modern approach to (micro)services and APIsHeadless Drupal: A modern approach to (micro)services and APIs
Headless Drupal: A modern approach to (micro)services and APIs
 
Cloud-Native Drupal: a survival guide
Cloud-Native Drupal: a survival guideCloud-Native Drupal: a survival guide
Cloud-Native Drupal: a survival guide
 
Mobile Development: una introduzione per Web Developers
Mobile Development: una introduzione per Web DevelopersMobile Development: una introduzione per Web Developers
Mobile Development: una introduzione per Web Developers
 
Retro gaming machine made with Javascript and Kubernetes
Retro gaming machine made with Javascript and Kubernetes Retro gaming machine made with Javascript and Kubernetes
Retro gaming machine made with Javascript and Kubernetes
 

Recently uploaded

My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 

Recently uploaded (20)

My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 

2023 - Drupalcon - How Drupal builds your pages

  • 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