Forstå de forskellige javascript-modulformater
Når du som jeg skal bygge din applikation, spørger du altid dig selv: Hvilket format skal jeg bruge? CJS ? AMD ? UMD ? ESM ? Hvad er forskellene ? Hvorfor så mange formater?
Igennem denne artikel vil jeg forsøge at besvare disse spørgsmål 😊.
#De forskellige formater
#CommonJS (CJS)
Dette er et af de første formater, der blev oprettet. Jeg er ret sikker på, at du allerede har brugt det. Det er det modulsystem, der oprindeligt inspirerede NodeJS.
Dette system er baseret på import og eksport af moduler takket være nogle velkendte nøgleord: require
og exports
. module.exports
-objektet er virkelig specifikt for NodeJS.
// utils.js // we create a function function add(r){ return r + r; } // export (expose) add to other modules exports.add = add; // index.js var utils = require('./utils.js'); utils.add(4); // = 8
CommunJS-holdet skabte dette API som et synkront API, hvilket ikke er så godt for browsere … Desuden forstås Commonjs ikke nativt af browsere; det kræver enten et loader-bibliotek eller noget transpiling.
#Asynkronous Module Definition (AMD)
AMD er en slags opsplitning af CommonJS. Det er blevet oprettet af medlemmer af CJS-holdet, der var uenige med den retning, som resten af holdet har valgt.
De har besluttet at oprette AMD for at understøtte asynkron modulindlæsning. Dette er det modulsystem, der bruges af RequireJS, og som fungerer klientside (i browsere).
// add.js define(function() { return add = function(r) { return r + r; } }); // index.js define(function(require) { require('./add'); add(4); // = 8 }
Dette eksempel virker kun, hvis du har requirejs på dit websted. Du kan finde nogle andre AMD-eksempler.
#Universal Module Definition (UMD)
Som du måske har forstået, er disse 2 formater desværre gensidigt uforståelige for hinanden. Det er derfor, at UMD er blevet skabt. Det er baseret på AMD, men med nogle specielle tilfælde inkluderet for at håndtere CommonJS-kompatibilitet.
Denne kompatibilitet tilføjer desværre en vis kompleksitet, der gør det kompliceret at læse/skrive. Hvis du ønsker det, kan du finde flere skabeloner af UMD-kode på dette github-repository.
#ES2015 Modules (ESM)
Da disse 3 formater ikke er så nemme at læse, svære at analysere for statiske kodeanalysatorer og ikke understøttes overalt, besluttede ECMA-holdet (holdet bag standardiseringen af Javascript) at oprette ECMAScript 2015-standarden (også kendt som ES6).Dette format er virkelig simpelt at læse og skrive og understøtter både synkrone og asynkrone funktionsmåder.
// add.js export function add(r) { return r + r; } // index.js import add from "./add"; add(4); // = 8
Dertil kommer, at es-moduler kan statisk analyseres, hvilket gør det muligt for build-værktøjer (som Webpack eller Rollup) at udføre tree-shaking på koden. Tree-shaking er en proces, der fjerner ubrugt kode fra bundles.
Det er desværre stadig 2 ulemper ved dette format (men de er ved at blive bedre):
- ESM understøtter ikke dynamisk importerede moduler, men der er et forslag for måneder siden, som er begyndt at blive implementeret på nogle browsere.
- Det understøttes ikke på alle browsere, men heldigvis kan dette “rettes” takket være… transpiling !
#Transpiling
Transpiling er processen med at oversætte et sprog eller en version af et sprog til et andet. Så her er ideen at transpile ES6 til ES5 for at få en bedre browserunderstøttelse. desværre har denne transpilering en omkostning, da den tilføjer noget ekstra kode for at lappe de manglende funktioner i ES6, som ikke findes i ES5.
Den mest berømte transpiler, der normalt bruges i dette tilfælde, er Babel.
#videre læsning
Hvis du ønsker at gå videre (gennem eksempler, forklaringer osv.) for at forstå, hvordan disse forskellige formater fungerer, er her nogle læsninger, som jeg har fundet, og som har inspireret mig:
- JavaScript Module Systems Showdown: CommonJS vs AMD vs ES2015
- Du bør bruge esm
- Skrivning af modulært JavaScript med AMD, CommonJS & ES Harmony
- Hvad er AMD, CommonJS og UMD?
- Modulariseringsteknikker (der er flere sider her)
- The state of JavaScript modules