Les services workers à la rescousse de nos monolithes
Kévin Jean
Architecte développeur
@kevinj_50886
KevinJean17
Miniplop
LE PREMIER CHARGEMENT
LE SECOND CHARGEMENT
S U A
Single
USAGE
APPLICATION
.
.
-
UNe machine de production qui tombe à chaque requête
-
UN TTFB > 1 MIN
LA STACK TECHNIQUE
HTML Response
1 min
GET js / Css / images
30 s
Assets Responses
GET /
POURQUOI UN TTFB > 1 Min
HTML Response
1 min
GET js / Css / images
30 s
Assets Responses
GET /
POURQUOI ça crash ?
/**
* Homepage action for serving / routes
*/
public function homepageAction(Request $request)
{
// Get data from DB for filter bar
$dataForFilterBar = $this->getDataForFilterBar();
// Get data from DB for every graph
$dataForGraph1 = $this->getDataForGraph1();
$dataForGraph2 = $this->getDataForGraph2();
$dataForGraph3 = $this->getDataForGraph3();
$dataForGraph4 = $this->getDataForGraph4();
$dataForGraph5 = $this->getDataForGraph5();
// Render the page with all the data
return $this->render('homepage.twig.html', [
'dataForFilterBar' => $dataForFilterBar,
'dataForGraph1' => $dataForGraph1,
'dataForGraph2' => $dataForGraph2,
'dataForGraph3' => $dataForGraph3,
'dataForGraph4' => $dataForGraph4,
'dataForGraph5' => $dataForGraph5,
]);
}
/**
* Homepage action for serving / routes
*/
public function homepageAction(Request $request)
{
// Get data from DB for filter bar
$dataForFilterBar = $this->getDataForFilterBar();
// Get data from DB for every graph
$dataForGraph1 = $this->getDataForGraph1();
$dataForGraph2 = $this->getDataForGraph2();
$dataForGraph3 = $this->getDataForGraph3();
$dataForGraph4 = $this->getDataForGraph4();
$dataForGraph5 = $this->getDataForGraph5();
// Render the page with all the data
return $this->render('homepage.twig.html', [
'dataForFilterBar' => $dataForFilterBar,
'dataForGraph1' => $dataForGraph1,
'dataForGraph2' => $dataForGraph2,
'dataForGraph3' => $dataForGraph3,
'dataForGraph4' => $dataForGraph4,
'dataForGraph5' => $dataForGraph5,
]);
}
Extraire LA COQUILLE HTML
EXtraire lA COQUILLE HTML
homepage.html.twig
<!DOCTYPE html>
<html>
<body>
<nav>...</nav>
<main>...</main>
<footer>...</footer>
</body>
</html>
<!DOCTYPE html>
<html>
<body>
<nav>...</nav>
<main>Loading...</main>
<footer>...</footer>
</body>
</html>
<!DOCTYPE html>
<main>...</main>
homepage.html.twig
data.html.twig
EXtraire lA COQUILLE HTML
/**
* Homepage action for serving "/" route
*/
public function homepageAction(Request $request)
{
// Render the page with all the data
return $this->render('homepage.twig.html');
}
/**
* Homepage action for serving "/data" route
*/
public function dataAction(Request $request)
{
// Get data from DB for filter bar
$dataForFilterBar = $this->getDataForFilterBar();
// Get data from DB for every graph
$dataForGraph1 = $this->getDataForGraph1();
$dataForGraph2 = $this->getDataForGraph2();
$dataForGraph3 = $this->getDataForGraph3();
$dataForGraph4 = $this->getDataForGraph4();
$dataForGraph5 = $this->getDataForGraph5();
// Render the page with all the data
return $this->render('data.twig.html', [
'dataForFilterBar' => $dataForFilterBar,
'dataForGraph1' => $dataForGraph1,
'dataForGraph2' => $dataForGraph2,
'dataForGraph3' => $dataForGraph3,
'dataForGraph4' => $dataForGraph4,
'dataForGraph5' => $dataForGraph5,
]);
}
EXtraire lA COQUILLE HTML
1 s
GET /data
HTML Response
1 min
GET /
GET js / Css / images
Assets Responses
10 s
EXtraire lA COQUILLE HTML
1 s
GET /data
HTML Response
1 min
GET /
GET js / Css / images
Assets Responses
10 s
EXtraire lA COQUILLE HTML
data.html.twig
<main>
<div class="filter-bar">...</div>
<div class="graph1">...</div>
<div class="graph2">...</div>
<div class="graph3">...</div>
<div class="graph4">...</div>
<div class="graph5">...</div>
</main>
<main>
<div class="filter-bar">
<p>Loading ...</p>
</div>
<div class="graph1">...</div>
<div class="graph2">...</div>
<div class="graph3">...</div>
<div class="graph4">...</div>
<div class="graph5">...</div>
</main>
<div>...</div>
data.html.twig
filterbar.html.twig
RECUPerer en asynchrone la barre des filtres
/**
* Homepage action for serving "/filter" route
*/
public function filterAction(Request $request)
{
$dataForFilterBar = $this->getDataForFilterBar();
// Render the page with all the data
return $this->render('filter.twig.html', [
'dataForFilterBar' => $dataForFilterBar,
]);
}
/**
* Homepage action for serving "/data" route
*/
public function dataAction(Request $request)
{
// Get data from DB for every graph
$dataForGraph1 = $this->getDataForGraph1();
$dataForGraph2 = $this->getDataForGraph2();
$dataForGraph3 = $this->getDataForGraph3();
$dataForGraph4 = $this->getDataForGraph4();
$dataForGraph5 = $this->getDataForGraph5();
// Render the page with all the data
return $this->render('data.twig.html', [
'dataForGraph1' => $dataForGraph1,
'dataForGraph2' => $dataForGraph2,
'dataForGraph3' => $dataForGraph3,
'dataForGraph4' => $dataForGraph4,
'dataForGraph5' => $dataForGraph5,
]);
}
RECUPerer en asynchrone la barre des filtres
11s
GET /filterBar
HTML Response
50 s
GET /data
HTML Response
10 s
RECUPerer en asynchrone la barre des filtres
...
50 s
Découper les calls APIs
20 s
2 Threads sur le serveur
70 s
30 S
Le Service WORKER
Mise EN PLACE D'un SErvice Worker
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/sw.js').then(function(registration) {
// Registration was successful
console.log('ServiceWorker registration successful with scope: ', registration.scope);
}, function(err) {
// registration failed :(
console.log('ServiceWorker registration failed: ', err);
});
});
}
OFFLINE-FIRST
(CACHE FALLING BACK TO NETWORK)
1
2
3
4
Mise EN PLACE D'un SErvice Worker
self.addEventListener('fetch', function(event) {
var requestURL = new URL(event.request.url);
event.respondWith(
caches.open('cache').then(function(cache) {
return cache.match(event.request).then(function (response) {
return response || fetch(event.request).then(function(response) {
cache.put(event.request, response.clone());
return response;
});
});
})
);
});
2 s
-
UNe machine de production qui tombe à chaque requete
-
UN TTFB > 1 MIN
-
UN TTFB DE 1S
-
UNe machine de production qui EST PLUS PETITE
GESTION DE La CACHE API
self.addEventListener('fetch', function(event) {
var requestURL = new URL(event.request.url);
var urlsWhichResetCache = [
/\/reset\//,
/\/search/,
/\/drilldown/
];
// Reset all the stored cache
if (pathNameMatchInExpression(requestURL.pathname, urlsWhichResetCache)) {
caches.keys().then(function(cacheNames) {
return Promise.all(
cacheNames.map(function(cacheName) {
return caches.delete(cacheName);
})
);
})
}
});
-
DESSINER LE PROBLEME
-
Utiliser les différents outils du webs (réseau, outil front)
-
Utiliser les services workers :)
MERCI
.businessChallengeContainer {
display:flex;
flex-direction: row;
@include isDesktop() {
margin-bottom: 48px;
}
@include isMobile() {
flex-direction: column;
}
}
.businessChallengeContainer {
display: flex;
flex-direction: row;
margin-bottom: 48px;
}
.businessChallengeContainer {
display:flex;
flex-direction: row;
margin-bottom: 48px;
@include isMobile() {
flex-direction: column;
}
}
.businessChallengeContainer {
display:flex;
flex-direction: row;
@include isDesktop() {
margin-bottom: 48px;
}
@include isMobile() {
flex-direction: column-reverse;
}
}
.businessChallengeContainer {
display:flex;
flex-direction: row;
margin-bottom: 48px;
}
.businessChallengeContainer {
display:flex;
@include isDesktop() {
flex-direction: row;
margin-bottom: 48px;
}
@include isMobile() {
flex-direction: column-reverse;
}
}
Les services workers à la rescousse de nos monolithes
By miniplop
Les services workers à la rescousse de nos monolithes
- 888