Cela fait plusieurs annĂ©es que je joue avec les bundlers JS. Restant convaincu de la nĂ©cessitĂ© de lâusage de ces outils (ne me laissez pas croire que vous ne packagez pas vos module JS en prod đ ), jâai beaucoup jouĂ© avec webpack. Notamment pour des sujets de performance, dâoptimisation et dâusage de plugins custom.
Je pense encore quâen 2021, webpack reste la solution la plus industrielle et aboutie pour bundler mes applications web. Jâentends que les outils comme parcel et rollup restent de bonnes alternatives. Cependant, webpack a probablement la plus grosse communautĂ© et est utilisĂ© par de nombreux projets.
Mais ne nous voilons pas la face, aujourdâhui on se satisfait de ces outils de bundling malgrĂ© des performances qui restent assez pauvres. Je travaille tous les jours sur un projet de plusieurs milliers de âmodulesâ rĂ©solus par webpack et câest parfois une souffrance đ„±.
Malgrés une utilisation intensive de cache et de workers, webpack montre certaines limitations pour packager des larges applications.
En quoi esbuild parait intéressant ?
Je ne vois pas de façon plus simple de lâexprimer que de vous expliquer simplement:
La premiĂšre fois oĂč jâai lancĂ©
esbuild
sur mon app web de test, jâai cru quâil avait plantĂ© alors quâen fait il sâĂ©tait exĂ©cutĂ© Ă une vitesse absoluement dingue.
Pour lâinstaller câest pas compliquĂ© :
yarn add -D esbuild
npm install --save-dev esbuild
Ou bien mĂȘme avec NPX
npx esbuild --version
Ătant Ă©crit en Go, sachez quâune version WASM et des binaires pour les principales architectures sont disponible.
esbuild
fait le pari du natif de Go pour profiter un maximum de solutions de parallélisation et une meilleure gestion de la mémoire.
Un API pauvre by design
Globalement lâAPI dâesbuild
est vraiment simple, en 30 minutes vous avez lu toute la doc des paramétrages possibles.
On est bien loin des 3-4 heures nĂ©cessaires pour lire lâensemble de la doc dâun webpack par exemple.
Malgré une configuration qui pourrait paraitre limitée, je reste agréablement surpris.
Jâai lâimpression quâon est vraiment pas loin dâavoir la âjuste grammaireâ dont on a besoin pour faire du bundling.
esbuild
propose 3 modes de consommation :
CLI
esbuild app.jsx --bundle --minify --sourcemap --target=chrome58,firefox57,safari11,edge16
GO
package main
import "github.com/evanw/esbuild/pkg/api"
import "os"
func main() {
result := api.Build(api.BuildOptions{
EntryPoints: []string{"app.jsx"},
Bundle: true,
MinifyWhitespace: true,
MinifyIdentifiers: true,
MinifySyntax: true,
Engines: []api.Engine{
{api.EngineChrome, "58"},
{api.EngineFirefox, "57"},
{api.EngineSafari, "11"},
{api.EngineEdge, "16"},
},
Write: true,
})
if len(result.Errors) > 0 {
os.Exit(1)
}
}
JS
require("esbuild").buildSync({
entryPoints: ["app.jsx"],
bundle: true,
minify: true,
sourcemap: true,
target: ["chrome58", "firefox57", "safari11", "edge16"],
outfile: "out.js",
});
Ă mes yeux le CLI reste hyper pratique pour tester des choses, mais dans un usage plus âindustrielâ on prĂ©fĂšrera quand mĂȘme le format JS ou GO.
Des mécaniques de plugins
Evan Wallace le crĂ©ateur et core mainteneur dâesbuild
ne sâen cache pas, il ne souhaite pas que son outil rĂ©ponde Ă 100% des besoins quâon peut avoir dans le monde du web.
Cependant, cela ne signifie pas quâon ne peut pas se servir de cette outil dans des cas spĂ©cifiques.
Comme on peut le voir avec les autres bundler, esbuild
propose la mécanique de plugins qui vous permettent beaucoup de choses.
Pour Ă©viter de maintenir tous ces besoins spĂ©cifiques, le crĂ©ateur compte donc sur la communautĂ© pour crĂ©er tous les plugins quâon peut souhaiter.
Et clairement, la communauté est la, je vous laisse voir cette page qui liste quelques plugins.
Les features les plus intéressantes
Je ne vais pas ici citer les features qui me semblent le coeur dâun bundler Web comme le code splitting, lâinjection, la minification. Cependant, jâai Ă©tĂ© Ă©tonnĂ© par quelques features quâon ne retrouve pas ailleurs.
Une architecture simple Ă comprendre
Clairement, ce qui fait la force dâesbuild
par rapport à ses concurrents est son architecture qui peut se résumer simplement.
On comprend bien quâen alliant parallĂ©lisation des Ă©tapes du build et reduction du nombre de lecture de lâAST.
Je vous invite Ă lire plus dâexplications dans la doc.
Browser targets
Par defaut esbuild
vous permet de définir la cible de votre compilation.
Quel niveau de javascript vous souhaitez atteindre ?
Habituellement on utilise une suite dâoutils comme @babel/preset-env
et une browserlist
pour faire en sorte de générer le JS compatible avec notre ciblage.
Babel câest gĂ©nial, je lâutilise tous les jours mais lâamoncellement dâoutils diffĂ©rents pour le bundling nâest clairement pas une bonne solution Ă mes yeux.
Cela ajoute beaucoup de complexité :
- au lieu dâapprendre a utiliser un simple outil de bundler, je dois apprendre en plus un outil de transpilation ciblĂ©
- jâai Ă maintenir deux dĂ©pendances
- passer par une librairy tierse peut rĂ©duire les performances (câest un peu le pari dâ
esbuild
)
Le mode server
esbuild
est tellement rapide quâil peut se permettre de vous exposer un server HTTP sur un dossier qui contient le rĂ©sultat de votre compilation Ă chaque requĂȘte.
Les autres outils se basent en général sur un mode watch qui surveille les fichiers qui changent pour lancer un build.
Le mode watch existe aussi avec esbuild
, mais le mode serve
me parait encore plus sympa car il vous suffit de refresh votre browser pour avoir la derniĂšre version de votre application en local.
require("esbuild")
.serve(
{
servedir: "www",
},
{
entryPoints: ["src/app.js"],
outdir: "www/js",
bundle: true,
}
)
.then(server => {
// Call "stop" on the web server when you're done
server.stop();
});
Mais du coup on arrĂȘte tout et on part la dessus ?
Gagnons du temps, la réponse pour moi est clairement non.
Comme le dit le crĂ©ateur dans la FAQ de la doc en toute honnĂȘtetĂ©, le projet nâest pas Ă considĂ©rer comme Ă©tant en alpha. Cependant, lâoutil en lui-mĂȘme ne possĂšde pas encore toutes les features qui ferait de lui un bon remplacant des bundler de la gĂ©nĂ©ration prĂ©cĂ©dente. Je pense notamment Ă lâabsence de HMR natif, ou bien encore un code splitting perfectible.
Il faut cependant ne pas rester fermé sur cette question.
Clairement esbuild
a de trĂšs gros points forts qui manquent Ă lâĂ©cosystĂšme actuel.
La communauté, encore naissante, est plutÎt active et les échanges dans les Issues et les PR du repo sont hyper intéressants.
Ce que jâapprĂ©cie vraiment dans ce projet, ce sont les parties pris : un focus sur les performances, une api qui reste simple.
Enfin, pour une fois quâun bundler nâa pas 1000 dĂ©pendances et me rajoute 100Mo dans mon dossier node_modules
, câest assez beau pour le noter.
Je finirais en vous disant quâ esbuild
nâest pas la seule alternative qui nous est proposĂ© dans cette nouvelle gĂ©nĂ©ration de bundler.
Je compte justement faire ce genre dâanalyse sur les outils comme Vite ou bien Snowpack.