This repository has been archived by the owner on Oct 12, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
webperfs-webpack.html
207 lines (164 loc) · 11.2 KB
/
webperfs-webpack.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
<!DOCTYPE html>
<html lang="en">
<head>
<title>Découpage du code JavaScript grâce à webpack</title>
<meta charset="utf-8" />
<link href="https://techblog.mappy.com/feeds/rss.xml" type="application/atom+xml" rel="alternate" title="Mappy Labs Full Atom Feed" />
<link href="https://techblog.mappy.com/feeds/web/rss.xml" type="application/atom+xml" rel="alternate" title="Mappy Labs Categories Atom Feed" />
<!-- Mobile viewport optimized: j.mp/bplateviewport -->
<meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1">
<link rel="stylesheet" type="text/css" href="./theme/gumby.css" />
<link rel="stylesheet" type="text/css" href="./theme/style.css" />
<link rel="stylesheet" type="text/css" href="./theme/pygment.css" />
<link rel="icon" type="image/png" href="images/favicon-96x96.png" sizes="96x96">
<link rel="icon" type="image/png" href="images/favicon-16x16.png" sizes="16x16">
<link rel="icon" type="image/png" href="images/favicon-32x32.png" sizes="32x32">
</head>
<body id="index" class="home">
<div class="container">
<header id="banner" class="body">
<h1><a href="/"><img src="/images/logo.png" /> Labs</a></h1>
<div id="navigation" class="navbar row">
<a href="#" gumby-trigger="#navigation > ul" class="toggle"><i class="icon-menu"></i></a>
</div>
</header><!-- /#banner -->
<div class="row">
<section id="content" class="body">
<div class="row">
<div class="ten columns">
<header>
<h2 class="entry-title">
<a href="./webperfs-webpack.html" rel="bookmark"
title="Permalink to Découpage du code JavaScript grâce à webpack">Découpage du code JavaScript grâce à webpack</a></h2>
</header>
<footer class="post-info">
<abbr class="published" title="2018-05-22T00:00:00+02:00">
Tue 22 May 2018
</abbr>
<address class="vcard author">
By <a class="url fn" href="./author/nicolas-betheuil-manuel-emeriau-jonathan-saget-gregory-paul.html">Nicolas Bétheuil, Manuel Emeriau, Jonathan Saget, Grégory Paul</a>
</address>
</footer><!-- /.post-info -->
<div class="entry-content">
<p>Après <a href="webperfs-sitespeed.html">avoir mis en place SiteSpeed</a>, il était temps de procéder à des améliorations de performances.</p>
<p>En regardant la composition de nos pages web (grâce à SiteSpeed), on se rend compte que le JavaScript en est la plus grosse partie du site <a href="https://fr.mappy.com/">mappy</a> :</p>
<p><img alt="taille avant optimisations" src="images/web/webperfs/size-before-js.png"></p>
<p><em>Les barres bleues correspondent à la taille du contenu non compressé, les barres vertes au contenu compressé (<code>gzip</code>).</em></p>
<p>C’est donc sur cette partie que nous nous sommes concentrés dans un premier temps.</p>
<h2>Optimisations sur le JavaScript</h2>
<h3>Suppression de code</h3>
<p>Une première action a été de supprimer des fonctionnalités ayant peu de valeur ajoutée pour l’utilisateur.</p>
<h3>Webpack à notre secours</h3>
<p>La deuxième action, plus conséquente, est de découper le JavaScript en plusieurs parties, pour ne charger que le minimum de code par page.</p>
<p>Nous utilisions <code>browserify</code> pour construire notre JavaScript mais ce dernier est moins outillé pour répondre à ce besoin (popularité en baisse donc écosystème assez pauvre).
Par conséquent, nous avons tout d’abord migré de <code>browserify</code> vers <code>webpack</code>.</p>
<p>Nous avons alors séparé notre code en deux avec un « vendors.js » (contenant nos bibliothèques) et le code de notre application.</p>
<p>Cette séparation a en effet du sens, puisque en utilisant des entêtes de cache relativement long (6 mois sur nos fichiers JavaScript), ce fichier vendors.js aura tendance à rester dans le cache du navigateur. Il ne sera donc pas re-téléchargé pour les prochaines visites sur notre site, tant que ce fichier n’aura pas été mis à jour.
Bien sûr, il convient d’ajouter un suffixe au nom du fichier (une empreinte ou <code>hash</code>) qui changera si une bibliothèque était mise à jour.
Cette technique est celle du « <a href="https://developers.google.com/web/fundamentals/performance/webpack/use-long-term-caching">long term caching</a> ».</p>
<p><img alt="découpage du vendors.js" src="images/web/webperfs/size-js-vendors.png"></p>
<p>Puis, nous avons commencé à découper le code de façon plus fine pour aboutir a de nombreux plus petits fichiers ou <code>chunks</code> dans la dénomination <code>webpack</code>.
Dans un premier temps, nous avons abandonné la séparation par langue (qui était intéressant en HTTP/1.1 où l’on cherchait à limiter les fichiers à télécharger mais plus depuis HTTP/2.0, <a href="https://caniuse.com/#feat=http2">massivement supporté aujourd’hui</a>).
Puis nous avons extrait certaines parties de code qui n’étaient chargées que sur une page dédiée (page d’impression, note de frais).
Enfin, certains <code>chunks</code> sont maintenant chargés automatiquement par <code>webpack</code> à l’exécution :</p>
<p><img alt="découpage au chargement initial" src="images/web/webperfs/size-js-more-bundles.png"></p>
<p>On remarque une diminution de 13 Ko par rapport à l’exemple précédent.</p>
<p>Et, au click sur le bouton itinéraire, le code nécessaire se charge à la volée :</p>
<p><img alt="découpage de la partie itinéraire" src="images/web/webperfs/size-js-bundle-iti.png"></p>
<p><em>La resource JavaScript 1.9798069481970534e737.js est le découpage via webpack du code de l’itinéraire.</em></p>
<p>Voici une autre représentation avant / après via <a href="https://github.com/webpack-contrib/webpack-bundle-analyzer">WebPack Bundle Analyzer</a>, un formidable outil pour inspecter les <code>chunks</code> <code>webpack</code> :</p>
<p>Avec la séparation du vendors.js :</p>
<p><img alt="séparation du vendors.js" src="images/web/webperfs/bundle-vendors.png"></p>
<p>Avec la séparation en multiples <code>chunks</code> :</p>
<p><img alt="séparation d’autres morceaux de code" src="images/web/webperfs/more-js-bundles.png"></p>
<p>On remarque de nombreux <code>chunks</code>, heureusement gérés par <code>webpack</code>.</p>
<h3>Résultats</h3>
<p>Avec ces optimisations, nous sommes passés de 375 Ko de JavaScript (<code>gzip</code>) à 335 Ko sur le chargement de la page d’accueil.</p>
<p><img alt="taille après optimisations" src="images/web/webperfs/size-after-js.png"></p>
<p>La séparation du code JavaScript n’est toutefois pas encore totalement finalisée.
Nous avons en effet encore d’autres point de coupes à effectuer pour diminuer encore la taille du code JavaScript.</p>
<p>Le JavaScript n’étant qu’une partie (certes importante) de notre site, le <a href="webperfs-split-fonts.html">prochain article</a> détaillera des optimisations sur d’autres types de ressources.</p>
</div><!-- /.entry-content -->
</div><!-- /.eleven.columns -->
<div class="four columns" id="sidebar">
<h4>Pages</h4>
<ul>
</ul>
<h4>Categories</h4>
<ul>
<li><a href="./category/agile.html">Agile</a></li>
<li><a href="./category/android.html">Android</a></li>
<li><a href="./category/gis.html">GIS</a></li>
<li><a href="./category/mapping.html">Mapping</a></li>
<li><a href="./category/solr.html">Solr</a></li>
<li><a href="./category/web.html">Web</a></li>
</ul>
<h4>Tags</h4>
<ul>
<li class="tag-4"><a href="./tag/panorama.html">panorama</a></li>
<li class="tag-4"><a href="./tag/responsive.html">responsive</a></li>
<li class="tag-4"><a href="./tag/osm.html">osm</a></li>
<li class="tag-1"><a href="./tag/javascript.html">javascript</a></li>
<li class="tag-4"><a href="./tag/retrospective.html">rétrospective</a></li>
<li class="tag-4"><a href="./tag/gis.html">GIS</a></li>
<li class="tag-4"><a href="./tag/sotm.html">sotm</a></li>
<li class="tag-4"><a href="./tag/android.html">android</a></li>
<li class="tag-4"><a href="./tag/agilite.html">agilité</a></li>
<li class="tag-4"><a href="./tag/webgl.html">webgl</a></li>
<li class="tag-4"><a href="./tag/openlr.html">openlr</a></li>
<li class="tag-3"><a href="./tag/postgis.html">postGIS</a></li>
<li class="tag-3"><a href="./tag/mapnik.html">mapnik</a></li>
<li class="tag-4"><a href="./tag/abtest.html">abtest</a></li>
<li class="tag-3"><a href="./tag/leaflet.html">leaflet</a></li>
<li class="tag-4"><a href="./tag/python.html">python</a></li>
<li class="tag-3"><a href="./tag/backbone.html">backbone</a></li>
<li class="tag-1"><a href="./tag/opensource.html">opensource</a></li>
<li class="tag-1"><a href="./tag/francais.html">français</a></li>
<li class="tag-4"><a href="./tag/watch.html">watch</a></li>
<li class="tag-4"><a href="./tag/meetup.html">meetup</a></li>
<li class="tag-4"><a href="./tag/browserify.html">browserify</a></li>
<li class="tag-4"><a href="./tag/opengl.html">opengl</a></li>
<li class="tag-4"><a href="./tag/docker.html">docker</a></li>
<li class="tag-3"><a href="./tag/solr.html">solr</a></li>
<li class="tag-2"><a href="./tag/nodejs.html">node.js</a></li>
<li class="tag-2"><a href="./tag/webperfs.html">webperfs</a></li>
<li class="tag-2"><a href="./tag/english.html">english</a></li>
<li class="tag-4"><a href="./tag/livereload.html">livereload</a></li>
</ul>
<nav class="widget">
<h4>Links</h4>
<ul>
<li><a href="https://www.mappy.com/">Mappy</a></li>
<li><a href="https://play.google.com/store/apps/details?id=com.mappy.app">Appli Android</a></li>
<li><a href="https://itunes.apple.com/fr/app/mappy-itineraire-et-recherche/id313834655?mt=8">Appli iOS</a></li>
<li><a href="http://corporate.mappy.com">Blog Mappy</a></li>
<li><a href="http://corporate.mappy.com/faq/integrez-mappy/">API Mappy</a></li>
</ul>
</nav>
</div> </div><!-- /.row -->
</section>
</div><!-- /.row -->
</div><!-- /.container -->
<div class="container.nopad bg">
<footer id="credits" class="row">
<div class="seven columns left-center">
<address id="about" class="vcard body">
Proudly powered by <a href="http://getpelican.com/">Pelican</a>,
which takes great advantage of <a href="http://python.org">Python</a>.
<br />
Based on the <a target="_blank" href="http://gumbyframework.com">Gumby Framework</a>
</address>
</div>
<div class="seven columns">
<div class="row">
<ul class="socbtns">
<li><div class="btn primary"><a href="https://github.com/Mappy" target="_blank">Github</a></div></li>
<li><div class="btn twitter"><a href="https://twitter.com/Mappy" target="_blank">Twitter</a></div></li>
<li><div class="btn facebook"><a href="https://www.facebook.com/MappyOnline" target="_blank">Facebook</a></div></li>
</ul>
</div>
</div>
</footer>
</div>
</body>
</html>