Web perf : analyser et optimiser un front
Jonathan Hervieux @djow__
🕐 PLUS QUE
14 mins et 42 s
- Amabay
- Cdiscount
- Rakuten
Jonathan Hervieux
Développeur
@Takima / @Cartier
1. Du vocabulaire
Indicateurs de performance, les web vitals
1. Du vocabulaire
- FCP (First Contentful Paint)
- TTFB (Time To First Byte)
1. Du vocabulaire
- TBT (Total Blocking Time)
- TTI (Time To Interactive)
1. Du vocabulaire
1. Du vocabulaire
1. Du vocabulaire
- Les web vitals
- FCP, LCP, CLS...
📝 Take Away
✔️
✔️
Comment on les mesure ?
❓
2. Comment mesurer les web vitals ?
LightHouse
Avec une simulation
- DevTools
2. Comment mesurer les web vitals ?
Avec une simulation
- DevTools
2. Comment mesurer les web vitals ?
- DevTools
- Sur un outil de CI/CD avec ligthouse-ci
Avec une simulation
2. Comment mesurer les web vitals ?
- DevTools
- Sur un outil de CI/CD avec ligthouse-ci
Avec une simulation
En conditions réelles
(Real User Monitoring)
- librairie js web-vitals
import { getCLS, getFID, getLCP } from 'web-vitals';
getCLS(console.log);
getFID(console.log);
getLCP(console.log);
2. Comment mesurer les web vitals ?
2. Comment mesurer les web vitals ?
2. Comment mesurer les web vitals ?
2. Comment mesurer les web vitals ?
1. Du vocabulaire
- Les web vitals
- FCP, LCP, CLS...
📝 Take Away
✔️
✔️
Comment on les améliore ?
❓
2. Mesurer les web vitals
- DevTools / lightouse-ci
- RUM (librairie web-vitals)
✔️
✔️
T = 0
T = beaucoup de temps après T0
html
css
js
png / jpg
temps (ms)
FCP
réseau
CPU
TTI
}
exécution
3. Améliorer les web-vitals
3. Améliorer les web vitals
Envoyer moins de contenu
Images
3. Améliorer les web vitals
WebP
AVIF
JPEG XL
Javascript
3. Améliorer les web vitals
Minification
Tree shaking
TerserWebpackPlugin
Javascript
3. Améliorer les web vitals
webpack-bundle-analyzer
bundlephobia
Tree shaking
{
// ...
webpack: {
plugins: {
add: [
// ...
new PurgecssPlugin({
paths: glob.sync(`${path.join(__dirname, './src')}/**/*`, { nodir: true }),
}),
]
}
}
}
Minification
PurgeCssPlugin
CssMinimizerWebpackPlugin
craco.config.js
CSS
3. Améliorer les web vitals
Gzip
brotli
craco.config.js
{
// ...
webpack: {
plugins: {
add: [
// ...
new CompressionPlugin({
filename: '[path].gz',
algorithm: 'gzip',
test: /\.(js|css|html)$/,
minRatio: 0.8,
}),
new CompressionPlugin({
filename: '[path].br',
algorithm: 'brotliCompress',
test: /\.(js|css|html)$/,
compressionOptions: { level: 11 },
minRatio: 0.8,
}),
]
}
}
}
-55%
-60%
Compression
3. Améliorer les web vitals
1. Du vocabulaire
- Les web vitals
- FCP, LCP, CLS...
📝 Take Away
✔️
✔️
2. Mesurer les web vitals
- DevTools / lightouse-ci
- RUM (librairie web-vitals)
✔️
✔️
3. Améliorer les web vitals
- Utiliser des formats modernes
- Minification + tree shaking
- S'applique aussi au CSS
- Compresser
✔️
✔️
✔️
✔️
T = 0
html
css
js
png / jpg
temps (ms)
FCP
réseau
CPU
TTI
}
exécution
T = un peu moins de temps après
3. Améliorer les web vitals
App.jsx
import React from 'react';
import Navbar from '../Navbar';
import Shelf from '../Shelf';
import Filter from '../Shelf/Filter';
import FloatCart from '../FloatCart';
const App = () => (
<>
<Navbar />
<main>
<Filter />
<Shelf />
</main>
<FloatCart />
<>
);
export default App;
const Navbar = import('../Navbar');
const Shelf = import('../Shelf');
const Filter = import('../Shelf/Filter');
const FloatCart = import('../FloatCart');
3. Améliorer les web vitals
Code splitting
App.jsx
import React, { Suspense } from 'react';
import Loader from '../Loader';
const Navbar = React.lazy(() => import('../Navbar'));
const Shelf = React.lazy(() => import('../Shelf'));
const Filter = React.lazy(() => import('../Filter'));
const FloatCart = React.lazy(() => import('../FloatCart'));
const App = () => (
<React.Fragment>
<Suspense fallback={<Loader/>}>
<Navbar />
</Suspense>
<main>
<Suspense fallback={<Loader/>}>
<Filter />
</Suspense>
<Suspense fallback={<Loader/>}>
<Shelf />
</Suspense>
</main>
<Suspense fallback={<Loader/>}>
<FloatCart />
</Suspense>
</React.Fragment>
);
3. Améliorer les web vitals
Lazy Loading
<link rel=”preload”>
<link rel=”prefetch”>
3. Améliorer les web vitals
Preload / prefetch
App.jsx
const Navbar = React.lazy(() => import(/* webpackChunkName: 'navbar' */ '../Navbar'));
const Shelf = React.lazy(() => import(/* webpackChunkName: 'shelf' */ '../Shelf'));
const Filter = React.lazy(() => import(/* webpackChunkName: 'filter' */ '../Shelf/Filter'));
const FloatCart = React.lazy(() => import(/* webpackChunkName: 'float-cart' */'../FloatCart'));
// ...
plugins: [
// ...
new PreloadPlugin({
rel: 'preload',
include: ['navbar', 'shelf']
)},
new PreloadPlugin({
rel: 'prefetch',
include: ['filter', 'float-cart']
)},
],
craco.config.js
3. Améliorer les web vitals
Preload / prefetch
navbar.a4dee578.chunk.js
3. Améliorer les web vitals
Preconnect
{
//...
webpack: {
plugins: {
add: [
new HtmlWebpackPreconnectPlugin(),
],
},
configure: (webpackConfig) => {
const { isFound, match } = getPlugin(webpackConfig, pluginByName("HtmlWebpackPlugin"));
if (isFound) {
match.userOptions.preconnect = ["http://localhost:8081"];
}
return webpackConfig;
},
},
};
craco.config.js
3. Améliorer les web vitals
Preconnect
<!doctype html>
<html lang="fr">
<head>
<title>Mon App</title>
<script defer="defer" src="/static/js/main.eabb2562.js"></script>
<link href="/static/css/main.00b42aeb.css" rel="stylesheet">
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
index.html
3. Améliorer les web vitals
Inline JS et CSS
temps (ms)
index.html
main.js
main.css
1.chunk.js
2.chunk.js
3.chunk.js
// ...
plugins: [
// ...
new HtmlInlineScriptPlugin([
/main~.+[.]js$/,
]),
],
craco.config.js
3. Améliorer les web vitals
Inline JS et CSS
3. Améliorer les web vitals
1. Du vocabulaire
- Les web vitals
- FCP, LCP, CLS...
📝 Take Away
✔️
✔️
2. Mesurer les web vitals
- DevTools / lightouse-ci
- librairie web-vitals
✔️
✔️
3. Améliorer les web vitals
- Utiliser des formats modernes
- Minification + tree shaking
- S'applique aussi au CSS
- Compresser
- Code splitting + lazy loading
- Preload / prefetch
- Preconnect
- Penser à inline
✔️
✔️
✔️
✔️
✔️
✔️
✔️
✔️
Et plein d'autres choses...
stratégie de mise en cache (assets, app shell...)
lazy loading des images
HTTP2
cache réponses API
SSR
Merci !
🙏
[Paris.js] Web perf : analyser et optimiser un front
By Jonathan HERVIEUX
[Paris.js] Web perf : analyser et optimiser un front
“Out of the box, webpack fait le café ! React c’est génial ; Uber, Airbnb, …, tout le monde l’utilise, avec ça le front de ton appli va être dingue !”. Ce sont plus ou moins les phrases que j’ai pu entendre auprès des équipes des quelques projets sur lesquels j’ai eu l’occasion de travailler, et c’est vrai, ça marche. Ça marche même très bien. Mais au fait, qu’est ce que ça signifie “ça marche” ? Pourquoi mon application affiche-t-elle systématiquement un loader à son démarrage ? Pourquoi la version web de reddit me transfère-t-elle 16Mo de data avec pas moins de 236 requêtes rien que sur la page d'accueil ? Est ce qu'un "web instantané" est possible ? Je vous propose plusieurs optimisations simples à mettre en place pour enfin maîtriser le contenu affiché sur vos applications web et ainsi bluffer vos futurs utilisateurs.
- 410