Hva er egentlig greia med Webpack?
Jeg skjønner at du spør. I samme åndedrag hører du gjerne “loaders”, “plugins” og annen babbel. Webpack er litt mystisk. Jeg har undret når jeg trenger det, hva den lange Webpack-konfigurasjons-filen betyr og hva som egentlig foregår i praksis når Webpack er i bruk.
I denne artikkelen ønsker jeg å demystifisere Webpack. Hvilket problem er det Webpack egentlig prøver å løse?
Visste du at Git kan bety 'goddamn idiotic truckload of sh*t'?
Problemet med kun HTML og JavaScript
La oss først ta noen steg tilbake - til en verden uten Webpack. Når du lager en enkel nettside med HTML og JavaScript trenger du ikke Webpack.
Prosjektet er lite, og du simpelthen importerer JavaScripten i HTML-filen.
<pre><code><!-- index.html -->
<head>
<script src="index.js" type="text/javascript"></script>
</head></pre></code>
Det er greit nok når du kun har én script-tag som importerer inn JavaScripten. Det er derimot noen problemer som dukker opp etter hvert som kodebasen blir større.
Som utvikler, ønsker du ikke å ha all kode i én fil, så du lager flere JavaScript-filer. For at også de filene skal fungere, må flere script-tags importeres i HTML-filen.
<!-- index.html -->
<head>
<script src="index.js" type="text/javascript"></script>
<script src="script1.js" type="text/javascript"></script>
<script src="script2.js" type="text/javascript"></script>
</head>
Løsningen er ikke all kode i en fil
Du kan kanskje allerede nå ane et problem? Det er lite vedlikeholdbart å stadig legge til alle nye JavaScript-filer i HTML-filen. Ikke bare er det ork, men du må også legge inn scriptene i riktig rekkefølge. Om script2.js avhenger av script1.js, må script1.js importeres først.
Et annet problem er at ved å importere JavaScript i HTML-filen, blir alle disse variablene globalt tilgjengelig. Det betyr at de globale variablene kan bli overskrevet av andre scripter. Som utvikler er det heller ikke en løsning å legge all kode i én fil, da det er vanskelig å ha oversikt i én enorm fil.
En løsning for import-problemet kommer fra JavaScript-kjøretidssystemet Node.js, som vanligvis kjøres på serveren. Med bruken av require klarer Node.js å hente opp riktige filer og løse opp i avhengigheter selv - ved å lete frem i filsystemet.
// index.js
const script1 = require("script1.js");
Ikke tilgang til filsystemet
Selv om det fungerer på serveren, fungerer det dessverre ikke (i utgangspunktet) på nettleseren. Siden nettleseren ikke har tilgang til filsystemet, får du en feil som opplyser deg om at require ikke er definert.
Det er her Webpack kommer inn. Webpack er en modul-bundler. En modul-bundler samler (bundler) alle filer (moduler) til et format som nettleseren kan forstå. Webpack pakker om alle JavaScript-filene om til én fil.
Dermed vil ikke nettleseren ha behov for tilgang til filsystemet. Webpack gjør dette ved å ta utgangspunkt i index.js, og så bytter den ut alle import-setningene med faktisk innhold. Dermed vil Webpack lage en veldig lang fil, som inneholder all koden.
La oss ta et enkelt eksempel for å vise hvordan koden Webpack spytter ut ser ut. I kodesnutten bruker jeg import, som er en mer moderne standard for å importere kode enn require. I index.js importerer jeg filen script1.js.
// index.js
import script1 from "./script1";
console.log("hei");
// script1.js
console.log("hallo");
Finner du igjen consol.log-ene?
I kodesnutten under ser du koden Webpack spytter ut etter å ha massert innholdet koden til noe en nettleser vil forstå. Det vil være denne nye filen som importeres i index.html for å levere rett kode til nettleseren.
Her er en liten utfordring: Finner du igjen console.log-ene?
// main.js
(() => {
var e = {
442: () => {
console.log("hallo");
},
},
r = {};
function o(t) {
var n = r[t];
if (void 0 !== n) return n.exports;
var a = (r[t] = { exports: {} });
return e[t](a, a.exports, o), a.exports;
}
(o.n = (e) => {
var r = e && e.__esModule ? () => e.default : () => e;
return o.d(r, { a: r }), r;
}),
(o.d = (e, r) => {
for (var t in r)
o.o(r, t) &&
!o.o(e, t) &&
Object.defineProperty(e, t, { enumerable: !0, get: r[t] });
}),
(o.o = (e, r) => Object.prototype.hasOwnProperty.call(e, r)),
(() => {
"use strict";
o(442), console.log("hei");
})();
})();
KOPIER TIL CLIPBOA
Enkelt sagt gjør Webpack om koden din til noe nettleseren kan forstå. Dette gjør Webpack ved å ordne avhengighetene mellom filene dine.