bauen ist ein schneller Bundler, der JavaScript-, TypeScript-, JSX- und CSS-Code optimieren kann. Dieser Artikel hilft Ihnen, sich mit esbuild vertraut zu machen und zeigt Ihnen, wie Sie Ihr eigenes Build-System ohne andere Abhängigkeiten erstellen.
Wie funktioniert esbuild?
Rahmen wie z Schraube haben esbuild übernommen, aber Sie können esbuild als eigenständiges Tool in Ihren eigenen Projekten verwenden.
-
esbuild bündelt JavaScript-Code in eine einzige Datei, ähnlich wie bei Bundlern wie z Aufrollen. Dies ist die Hauptfunktion von esbuild. Sie löst Module auf, meldet Syntaxprobleme, „Tree-Shakes“ zum Entfernen ungenutzter Funktionen, löscht Protokollierungs- und Debugger-Anweisungen, minimiert Code und stellt Quellzuordnungen bereit.
-
esbuild bündelt CSS-Code in eine einzige Datei. Es ist kein vollständiger Ersatz für Vorprozessoren wie z Sass or PostCSS, aber esbuild kann Partials, Syntaxprobleme, Verschachtelung, Inline-Asset-Kodierung, Quellzuordnungen, automatische Präfixierung und Minimierung verarbeiten. Das könnte alles sein, was Sie brauchen.
-
esbuild stellt außerdem einen lokalen Entwicklungsserver bereit mit automatischer Bündelung und Hot-Reloading, sodass keine Aktualisierung erforderlich ist. Es verfügt nicht über alle Funktionen, die von angeboten werden Browsersync, aber für die meisten Fälle ist es gut genug.
Der folgende Code hilft Ihnen, die Esbuild-Konzepte zu verstehen, damit Sie weitere Konfigurationsmöglichkeiten für Ihre Projekte untersuchen können.
Warum Bundle?
Das Bündeln von Code in einer einzigen Datei bietet verschiedene Vorteile. Hier sind einige davon:
- Sie können kleinere, eigenständige Quelldateien entwickeln, die einfacher zu verwalten sind
- Sie können den Code während des Bündelungsprozesses linten, verschönern und auf Syntax prüfen
- Der Bundler kann ungenutzte Funktionen entfernen – bekannt als Baumschütteln
- Sie können alternative Versionen desselben Codes bündeln und Ziele für ältere Browser, Node.js, Deno usw. erstellen
- Einzelne Dateien werden schneller geladen als mehrere Dateien und der Browser benötigt keine ES-Modulunterstützung
- Die Bündelung auf Produktionsebene kann die Leistung verbessern, indem Code minimiert und Protokollierungs- und Debugging-Anweisungen entfernt werden
Warum esbuild verwenden?
Im Gegensatz zu JavaScript-Bundlern ist esbuild eine kompilierte ausführbare Go-Datei, die eine starke Parallelverarbeitung implementiert. Es ist schnell und bis zu hundertmal schneller als Rollup, Parcel oder Webpack. Dies könnte über die gesamte Laufzeit eines Projekts Wochen an Entwicklungszeit einsparen.
Darüber hinaus bietet esbuild auch:
- integrierte Bündelung und Kompilierung für JavaScript, TypeScript, JSX und CSS
- Befehlszeilen-, JavaScript- und Go-Konfigurations-APIs
- Unterstützung für ES-Module und CommonJS
- ein lokaler Entwicklungsserver mit Überwachungsmodus und Live-Nachladen
- Plugins um weitere Funktionalität hinzuzufügen
- umfassende Dokumentation und ein Online-Experimentiertool
Warum Esbuild vermeiden?
Zum Zeitpunkt des Verfassens dieses Artikels hat esbuild Version 0.18 erreicht. Es ist zuverlässig, aber immer noch ein Betaprodukt.
esbuild wird häufig aktualisiert und die Optionen können sich zwischen den Versionen ändern. Der Dokumentation empfiehlt Ihnen, bei einer bestimmten Version zu bleiben. Sie können es aktualisieren, müssen jedoch möglicherweise Ihre Konfigurationsdateien migrieren und sich mit der neuen Dokumentation befassen, um wichtige Änderungen zu entdecken.
Beachten Sie auch, dass esbuild keine TypeScript-Typprüfung durchführt, Sie müssen es also trotzdem ausführen tsc -noEmit
.
Superschneller Start
Erstellen Sie bei Bedarf ein neues Node.js-Projekt mit npm init
, dann installieren Sie esbuild lokal als Entwicklungsabhängigkeit:
npm install esbuild --save-dev --save-exact
Die Installation benötigt ca. 9 MB. Überprüfen Sie, ob es funktioniert, indem Sie diesen Befehl ausführen, um die installierte Version anzuzeigen:
./node_modules/.bin/esbuild --version
Oder führen Sie diesen Befehl aus, um die CLI-Hilfe anzuzeigen:
./node_modules/.bin/esbuild --help
Verwenden Sie die CLI-API, um ein Eingabeskript zu bündeln (myapp.js
) und alle seine importierten Module in einer einzigen Datei mit dem Namen bundle.js
. esbuild gibt eine Datei im standardmäßigen, browserbasierten, sofort aufgerufenen Funktionsausdrucksformat (IIFE) aus:
./node_modules/.bin/esbuild myapp.js --bundle --outfile=bundle.js
Du kannst dich Installieren Sie esbuild auf andere Weise wenn Sie Node.js nicht verwenden.
Beispielprojekt
Laden Sie die Beispieldateien und eine herunter esbuild-Konfiguration von Github. Es handelt sich um ein Node.js-Projekt. Installieren Sie also die einzelne Esbuild-Abhängigkeit mit:
npm install
Bauen Sie die Quelldateien ein src
zum build
Verzeichnis und starten Sie einen Entwicklungsserver mit:
npm start
Navigiere jetzt zu localhost:8000
in Ihrem Browser, um eine Webseite mit einer Echtzeituhr anzuzeigen. Wenn Sie eine CSS-Datei aktualisieren in src/css/
or src/css/partials
, esbuild wird den Code neu bündeln und die Stile live neu laden.
Presse- Strg|Befehlstaste + Strg|Befehlstaste um den Server zu stoppen.
Erstellen Sie einen Produktions-Build für die Bereitstellung mit:
npm run build
Untersuchen Sie die CSS- und JavaScript-Dateien im build
Verzeichnis, um die minimierten Versionen ohne Quellkarten anzuzeigen.
Projektübersicht
Die Echtzeituhrseite ist in a aufgebaut build
Verzeichnis mit Quelldateien von src
.
Das package.json
Datei definiert fünf npm
Skripte. Der erste löscht die build
Verzeichnis:
"clean": "rm -rf ./build",
Bevor es zu einer Bündelung kommt, muss ein init
Skript läuft clean
, erstellt ein neues build
Verzeichnis und Kopien:
- eine statische HTML-Datei von
src/html/index.html
zubuild/index.html
- statische Bilder von
src/images/
zubuild/images/
"init": "npm run clean && mkdir ./build && cp ./src/html/* ./build/ && cp -r ./src/images ./build",
An esbuild.config.js
Die Datei steuert den esbuild-Bündelungsprozess mithilfe der JavaScript-API. Dies ist einfacher zu verwalten als die Übergabe von Optionen an die CLI-API, was unhandlich werden kann. Ein npm
bundle
Skript läuft init
gefolgt von node ./esbuild.config.js
:
"bundle": "npm run init && node ./esbuild.config.js",
Die letzten zwei npm
Skripte laufen bundle
mit entweder a production
or development
Parameter übergeben an ./esbuild.config.js
So steuern Sie den Build:
"build": "npm run bundle -- production",
"start": "npm run bundle -- development"
Wann ./esbuild.config.js
ausgeführt wird, bestimmt es, ob eine Minimierung erstellt werden soll production
Dateien (Standard) oder development
Dateien mit automatischen Updates, Quellkarten und einem Live-Neuladeserver. In beiden Fällen sind esbuild-Bundles:
- die Eintrags-CSS-Datei
src/css/main.css
zubuild/css/main.css
- die Eintrags-JavaScript-Datei
scr/js/main.js
zubuild/js/main.js
Esbuild konfigurieren
package.json
hat eine "type"
of "module"
so alles .js
Dateien können ES-Module verwenden. Der esbuild.config.js
Skript-Importe esbuild
und Sätze productionMode
zu true
beim Bündeln für die Produktion bzw false
beim Bündeln für die Entwicklung:
import { argv } from 'node:process';
import * as esbuild from 'esbuild'; const productionMode = ('development' !== (argv[2] || process.env.NODE_ENV)), target = 'chrome100,firefox100,safari15'.split(','); console.log(`${ productionMode ? 'production' : 'development' } build`);
Bündelziel
Beachten Sie, dass die Zielvariable definiert eine Reihe von Browsern und Versionsnummern, die in der Konfiguration verwendet werden sollen. Dies wirkt sich auf die gebündelte Ausgabe aus und ändert die Syntax, um bestimmte Plattformen zu unterstützen. Esbuild kann beispielsweise:
- erweitern native CSS-Verschachtelung in vollständige Selektoren (die Verschachtelung würde bestehen bleiben, wenn
"Chrome115"
war das einzige Ziel) - Fügen Sie bei Bedarf CSS-Herstellerpräfixe hinzu
- polyfill die
??
nullish Koaleszenzoperator - entfernen
#
aus privaten Klassenfeldern
Neben Browsern können Sie auch gezielt darauf abzielen node
und es
Versionen wie es2020
und esnext
(die neuesten JS- und CSS-Funktionen).
JavaScript-Bündelung
Die einfachste API zum Erstellen eines Bundles:
await esbuild.build({ entryPoints: ['myapp.js'], bundle: true outfile: 'bundle.js'
});
Dies repliziert den oben verwendeten CLI-Befehl:
./node_modules/.bin/esbuild myapp.js --bundle --outfile=bundle.js
Das Beispielprojekt verwendet erweiterte Optionen wie die Dateiüberwachung. Dies erfordert einen lang laufenden Build Kontext wodurch die Konfiguration festgelegt wird:
const buildJS = await esbuild.context({ entryPoints: [ './src/js/main.js' ], format: 'esm', bundle: true, target, drop: productionMode ? ['debugger', 'console'] : [], logLevel: productionMode ? 'error' : 'info', minify: productionMode, sourcemap: !productionMode && 'linked', outdir: './build/js' });
esbuild-Angebote Dutzende Konfigurationsoptionen. Hier ist eine Übersicht über die hier verwendeten:
-
entryPoints
definiert ein Array von Dateieintrittspunkten für die Bündelung. Das Beispielprojekt verfügt über ein Skript unter./src/js/main.js
. -
format
legt das Ausgabeformat fest. Das Beispiel verwendetesm
, aber Sie können optional festlegeniife
für ältere Browser bzwcommonjs
für Node.js. -
bundle
einstellentrue
Inlines importierte Module in die Ausgabedatei. -
target
ist das oben definierte Array der Zielbrowser. -
drop
ist ein Array vonconsole
und / oderdebugger
Anweisungen, die entfernt werden sollen. In diesem Fall entfernen Produktions-Builds beide und Entwicklungs-Builds behalten sie bei. -
logLevel
Definiert die Ausführlichkeit der Protokollierung. Das obige Beispiel zeigt Fehler während Produktions-Builds und ausführlichere Informationsmeldungen während Entwicklungs-Builds. -
minify
Reduziert die Codegröße, indem Kommentare und Leerzeichen entfernt und Variablen und Funktionen nach Möglichkeit umbenannt werden. Das Beispielprojekt wird jedoch während der Produktionserstellung minimiert verschönert Code während der Entwicklungs-Builds. -
sourcemap
einstellenlinked
(nur im Entwicklungsmodus) generiert eine verknüpfte Quellkarte in einem.map
Datei, damit die ursprüngliche Quelldatei und -zeile in den Browser-Entwicklertools verfügbar ist. Sie können auch einstelleninline
um die Quellkarte in die gebündelte Datei einzuschließen,both
beides zu schaffen, oderexternal
generieren.map
Datei ohne Link aus dem gebündelten JavaScript. -
outdir
Definiert das Ausgabeverzeichnis der gebündelten Datei.
Rufen Sie die Kontextobjekte auf rebuild()
Methode zum einmaligen Ausführen des Builds – normalerweise für einen Produktionsbuild:
await buildJS.rebuild();
buildJS.dispose();
Rufen Sie die Kontextobjekte auf watch()
Methode, um die Ausführung fortzusetzen und automatisch neu zu erstellen, wenn sich überwachte Dateien ändern:
await buildJS.watch();
Das Kontextobjekt stellt sicher, dass nachfolgende Builds inkrementell verarbeitet werden und dass sie Arbeit aus früheren Builds wiederverwenden, um die Leistung zu verbessern.
JavaScript-Eingabe- und Ausgabedateien
Der Eintritt src/js/main.js
Dateiimporte dom.js
und time.js
Module aus der lib
Unterordner. Es findet alle Elemente mit einer Klasse von clock
und setzt ihren Textinhalt jede Sekunde auf die aktuelle Zeit:
import * as dom from './lib/dom.js';
import { formatHMS } from './lib/time.js'; const clock = dom.getAll('.clock'); if (clock.length) { console.log('initializing clock'); setInterval(() => { clock.forEach(c => c.textContent = formatHMS()); }, 1000); }
dom.js
exportiert zwei Funktionen. main.js
importiert beide, verwendet aber nur getAll()
:
export function get(selector, doc = document) { return doc.querySelector(selector);
} export function getAll(selector, doc = document) { return Array.from(doc.querySelectorAll(selector));
}
time.js
exportiert zwei Funktionen. main.js
Importe formatHMS()
, aber das nutzt die anderen Funktionen im Modul:
function timePad(n) { return String(n).padStart(2, '0');
} export function formatHM(d = new Date()) { return timePad(d.getHours()) + ':' + timePad(d.getMinutes());
} export function formatHMS(d = new Date()) { return formatHM(d) + ':' + timePad(d.getSeconds());
}
Das resultierende Entwicklungsbündel entfernt (Tree Shakes) get()
für dom.js
aber beinhaltet alles time.js
Funktionen. Außerdem wird eine Quellkarte generiert:
function getAll(selector, doc = document) { return Array.from(doc.querySelectorAll(selector));
} function timePad(n) { return String(n).padStart(2, "0");
} function formatHM(d = new Date()) { return timePad(d.getHours()) + ":" + timePad(d.getMinutes());
} function formatHMS(d = new Date()) { return formatHM(d) + ":" + timePad(d.getSeconds());
} var clock = getAll(".clock");
if (clock.length) { console.log("initializing clock"); setInterval(() => { clock.forEach((c) => c.textContent = formatHMS()); }, 1e3);
}
(Beachten Sie, dass esbuild dies kann umschreiben let
und const
zu var
für Korrektheit und Geschwindigkeit.)
Das resultierende Produktionspaket minimiert den Code auf 322 Zeichen:
function o(t,c=document){return Array.from(c.querySelectorAll(t))}function e(t){return String(t).padStart(2,"0")}function l(t=new Date){return e(t.getHours())+":"+e(t.getMinutes())}function r(t=new Date){return l(t)+":"+e(t.getSeconds())}var n=o(".clock");n.length&&setInterval(()=>{n.forEach(t=>t.textContent=r())},1e3);
CSS-Bündelung
Die CSS-Bündelung im Beispielprojekt verwendet ein ähnliches Kontextobjekt wie JavaScript oben:
const buildCSS = await esbuild.context({ entryPoints: [ './src/css/main.css' ], bundle: true, target, external: ['/images/*'], loader: { '.png': 'file', '.jpg': 'file', '.svg': 'dataurl' }, logLevel: productionMode ? 'error' : 'info', minify: productionMode, sourcemap: !productionMode && 'linked', outdir: './build/css' });
Es definiert ein external
Option als Array von Dateien und Pfaden zu ausschließen aus dem Bau. Im Beispielprojekt sind Dateien im src/images/
Verzeichnis werden in das kopiert build
Verzeichnis, damit HTML, CSS oder JavaScript direkt darauf verweisen können. Wenn dies nicht festgelegt wäre, würde esbuild Dateien in die Ausgabe kopieren build/css/
Verzeichnis, wenn Sie sie verwenden background-image
oder ähnliche Eigenschaften.
Das loader
Die Option ändert, wie esbuild mit einer importierten Datei umgeht, auf die nicht verwiesen wird external
Vermögenswert. In diesem Beispiel:
- SVG-Bilder werden als Daten-URIs eingebunden
- PNG- und JPG-Bilder werden in kopiert
build/css/
Verzeichnis gespeichert und als Dateien referenziert
CSS-Eingabe- und Ausgabedateien
Der Eintritt src/css/main.css
Dateiimporte variables.css
und elements.css
von dem partials
Unterordner:
@import './partials/variables.css';
@import './partials/elements.css';
variables.css
definiert standardmäßige benutzerdefinierte Eigenschaften:
:root { --font-body: sans-serif; --color-fore: #fff; --color-back: #112;
}
elements.css
definiert alle Stile. Notiz:
-
body
hat ein Hintergrundbild, das von extern geladen wurdeimages
Verzeichnis -
h1
ist darin verschachteltheader
-
h1
hat eine Hintergrund-SVG, die eingebunden wird - Die Zielbrowser erfordern keine Herstellerpräfixe
*, *::before, ::after { box-sizing: border-box; font-weight: normal; padding: 0; margin: 0;
} body { font-family: var(--font-body); color: var(--color-fore); background: var(--color-back) url(/images/web.png) repeat; margin: 1em;
} header { & h1 { font-size: 2em; padding-left: 1.5em; margin: 0.5em 0; background: url(../../icons/clock.svg) no-repeat; } } .clock { display: block; font-size: 5em; text-align: center; font-variant-numeric: tabular-nums;
}
Das resultierende Entwicklungspaket erweitert die verschachtelte Syntax, integriert die SVG-Datei und generiert eine Quellzuordnung:
:root { --font-body: sans-serif; --color-fore: #fff; --color-back: #112;
} *,
*::before,
::after { box-sizing: border-box; font-weight: normal; padding: 0; margin: 0;
}
body { font-family: var(--font-body); color: var(--color-fore); background: var(--color-back) url(/images/web.png) repeat; margin: 1em;
}
header h1 { font-size: 2em; padding-left: 1.5em; margin: 0.5em 0; background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><defs><style>*{fill:none;stroke:%23fff;stroke-width:1.5;stroke-miterlimit:10}</style></defs><circle cx="12" cy="12" r="10.5"></circle><circle cx="12" cy="12" r="0.95"></circle><polyline points="12 4.36 12 12 16.77 16.77"></polyline></svg>') no-repeat;
}
.clock { display: block; font-size: 5em; text-align: center; font-variant-numeric: tabular-nums;
}
Das resultierende Produktionspaket minimiert den Code auf 764 Zeichen (das SVG wird hier weggelassen):
:root{--font-body: sans-serif;--color-fore: #fff;--color-back: #112}*,*:before,:after{box-sizing:border-box;font-weight:400;padding:0;margin:0}body{font-family:var(--font-body);color:var(--color-fore);background:var(--color-back) url(/images/web.png) repeat;margin:1em}header h1{font-size:2em;padding-left:1.5em;margin:.5em 0;background:url('data:image/svg+xml,<svg...></svg>') no-repeat}.clock{display:block;font-size:5em;text-align:center;font-variant-numeric:tabular-nums}
Beobachten, Wiederaufbauen und Dienen
Der Rest der esbuild.config.js
Skriptpakete einmal für Produktions-Builds vor dem Beenden:
if (productionMode) { await buildCSS.rebuild(); buildCSS.dispose(); await buildJS.rebuild(); buildJS.dispose(); }
Während der Entwicklungs-Builds läuft das Skript weiter, sucht nach Dateiänderungen und führt automatisch ein erneutes Bundle durch. Der buildCSS
context startet einen Entwicklungs-Webserver mit build/
als Stammverzeichnis:
else { await buildCSS.watch(); await buildJS.watch(); await buildCSS.serve({ servedir: './build' }); }
Starten Sie den Entwicklungs-Build mit:
npm start
Navigieren Sie dann zu localhost:8000
um die Seite anzuzeigen.
Im Gegensatz zu Browsersync müssen Sie zum Live-Neuladen Ihren eigenen Code zu den Entwicklungsseiten hinzufügen. Bei Änderungen sendet esbuild Informationen über das Update per Vom Server gesendetes Ereignis. Die einfachste Möglichkeit besteht darin, die Seite bei jeder Änderung vollständig neu zu laden:
new EventSource('/esbuild').addEventListener('change', () => location.reload());
Das Beispielprojekt verwendet das CSS-Kontextobjekt, um den Server zu erstellen. Das liegt daran, dass ich JavaScript-Änderungen lieber manuell aktualisiere – und weil ich für esbuild keine Möglichkeit gefunden habe, ein Ereignis sowohl für CSS- als auch für JS-Updates zu senden! Die HTML-Seite enthält das folgende Skript zum Ersetzen aktualisierter CSS-Dateien ohne eine vollständige Seitenaktualisierung (Hot-Reload):
<script type="module">
// esbuild server-sent event - live reload CSS
new EventSource('/esbuild').addEventListener('change', e => { const { added, removed, updated } = JSON.parse(e.data); // reload when CSS files are added or removed if (added.length || removed.length) { location.reload(); return; } // replace updated CSS files Array.from(document.getElementsByTagName('link')).forEach(link => { const url = new URL(link.href), path = url.pathname; if (updated.includes(path) && url.host === location.host) { const css = link.cloneNode(); css.onload = () => link.remove(); css.href = `${ path }?${ +new Date() }`; link.after(css); } }) });
Beachten Sie, dass esbuild derzeit kein Hot-Reloading von JavaScript unterstützt – Ich würde dem sowieso nicht vertrauen!
Zusammenfassung
Mit ein wenig Konfiguration könnte esbuild ausreichen, um alle Entwicklungs- und Produktions-Build-Anforderungen Ihres Projekts zu erfüllen.
Es gibt einen umfassenden Satz von Plugins Sollten Sie erweiterte Funktionen benötigen? Beachten Sie, dass diese häufig Sass, PostCSS oder ähnliche Build-Tools umfassen, sodass sie esbuild effektiv als Task-Runner verwenden. Du kannst immer Erstellen Sie Ihre eigenen Plugins wenn Sie leichtere, individuelle Optionen benötigen.
Ich benutze esbuild seit einem Jahr. Die Geschwindigkeit ist im Vergleich zu ähnlichen Bundlern erstaunlich und es erscheinen häufig neue Funktionen. Der einzige kleine Nachteil sind bahnbrechende Änderungen, die Wartungsaufwand erfordern.
esbuild erhebt nicht den Anspruch, ein einheitliches All-in-One-Build-Tool zu sein, aber es kommt diesem Ziel wahrscheinlich näher als Rom.
- SEO-gestützte Content- und PR-Distribution. Holen Sie sich noch heute Verstärkung.
- PlatoData.Network Vertikale generative KI. Motiviere dich selbst. Hier zugreifen.
- PlatoAiStream. Web3-Intelligenz. Wissen verstärkt. Hier zugreifen.
- PlatoESG. Automobil / Elektrofahrzeuge, Kohlenstoff, CleanTech, Energie, Umwelt, Solar, Abfallwirtschaft. Hier zugreifen.
- BlockOffsets. Modernisierung des Eigentums an Umweltkompensationen. Hier zugreifen.
- Quelle: https://www.sitepoint.com/esbuild-introduction/?utm_source=rss