Perché scegliere i moduli ES2015, basati sullo stato dell'arte della modularizzazione JavaScript

In questo articolo vedremo perché è importante migrare subito ai moduli ES2015 per l'intera community.

Lo Stato dell'arte

Per capire perché è importante, dobbiamo prima descrivere un quadro generale del contesto reale. L'ecosistema JavaScript è cresciuto così tanto negli ultimi cinque anni che molti sviluppatori non hanno notato che in realtà ci sono cinque modi per creare moduli di script o applicazioni JavaScript!

  • L'ancestrale IIFE () : questo approccio è il modo più antico e più semplice per modularizzare un blocco JavaScript. Di seguito puoi vedere un esempio di base di come avvolgere un blocco JavaScript in un IIFE:
    const myModule = (function (...deps){
       // JavaScript chunk
       return {hello : () => console.log(‘hello from myModule’)};
    })(dependencies);
    

    Questo codice non dovrebbe sorprenderti, è un modello comune per l'ambito di variabili o/e funzioni e l'unica soluzione utilizzabile in modo nativo. Il suo problema è che non gestisce la dipendenza per noi.

  • necessarioAMD (dipendenza dal modulo asincrono) : Fortemente reso popolare da Require.js, questo formato di modulo è stato creato per inserire facilmente i moduli tra di loro (aka Injection Of Dependency). Un altro vantaggio è quello di poter caricare JavaScript in modo dinamico a blocchi.
    <pre>define(‘myModule’, [‘dep1’, ‘dep2’], function (dep1, dep2){
        // JavaScript chunk, with a potential deferred loading
        return {hello: () => console.log(‘hello from myModule’)};
    });
    // anywhere else
    require([‘myModule’], function (myModule) {
        myModule.hello() // display ‘hello form myModule’
    });
    

    Efficiente, ma un po' prolisso e non funziona in modo nativo su Node.js.

  • CommonJs : formato predefinito della piattaforma Node.js. Il caso d'uso comune si presenta così:
    // file1.js
    modules.export = {
        hello : () => console.log(‘hello from myModule’)
    }
    // file2;
    const myModule = require('./file1.js');
    myModule.hello();
    

    nodejsQuesto formato sembra piuttosto interessante, perché è in grado di analizzare le variabili e definire le dipendenze tra i moduli. Ma è stato progettato per Node, quindi non funziona in un browser, non è in grado di caricare moduli in modo asincrono. Tuttavia, puoi usarlo in un'app frontale grazie a Browserify o altri per usarlo in un browser.

  • UMD (Dipendenza dal modulo universale) : A questo punto vediamo che non esiste una soluzione per creare un modulo compatibile per browser e server Node contemporaneamente. AMD per browser, CommonJS per Node.
    UMD cerca di risolverlo combinando AMD e CommonJS in un formato in grado di essere integrabile in tutti i target, che assomiglia a questo:

    (function (global, factory) {
        typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
        typeof define === 'function' && define.amd ? define(factory) :
    (factory());
    }(this, function () {
        // JavaScript chunk
        return {
           hello : () => console.log(‘hello from myModule’)
        }
    });
    

    Come vedi, questo formato effettua la verifica del suo contesto per scegliere se utilizza AMD o CommonJS allora. È perfetto per il confezionamento di librerie multi-ambiente come lodash o moment.js.

Quindi, perché aggiungere un nuovo tipo di modulo?

Innanzitutto nessuna di queste soluzioni è uno standard, definito dal gruppo TC39 voglio dire. ECMA6 è ora utilizzato da molti sviluppatori, quindi perché non utilizzare la soluzione standard di questa versione di JavaScript, i moduli ES2015?
Questo standard offre una soluzione più flessibile e potente rispetto agli altri. Vi invito a vedere tutte le funzionalità dei moduli ECMA2015 qui. Perché in questo articolo voglio concentrarmi su una capacità speciale dei moduli ES2015. La sua capacità di definire con maggiore precisione ciò che viene esposto/importato da/verso ciascun modulo. Diamo un'occhiata al pezzo di codice qui sotto per dimostrare il concetto:

// file1.js
const f1 = ()=> console.log(‘f1’);
const f2 = ()=> console.log(‘f2’);
const f3 = ()=> console.log(‘f3’);
export {f1, f2, f3};
// file2.js
import {f1, f2} from “./file1”;
f1(); // display ‘f1’
f2(); // display ‘f2’

Vediamo sopra, che possiamo importare facilmente solo quello che vogliamo con una notazione statica. A contrario delle altre soluzioni, come CommonJS dove possiamo chiamare dinamicamente ciò che vogliamo. Se prendiamo lo stesso esempio in CommonJS con una piccola differenza.

// file1.js
const f1 = ()=> console.log(‘f1’);
const f2 = ()=> console.log(‘f2’);
const f3 = ()=> console.log(‘f3’);
modules.exports = {f1,f2,f3};
// file2.js
const file1 = require(‘./file1’);
file1.f1(); // display ‘f1’
file1.f2(); // display ‘f2’
file1[process.ENV.funcName]();

Ovviamente quest'ultima riga non apparirà mai in un codice reale, ma dimostra che alcuni valori sono fuori controllo, e quindi non prevedibili in un'analisi statica. Qui, possiamo chiamare potenzialmente f3 perché con CommonJS (ed è lo stesso con AMD o IIFE o UMD) non possiamo limitare ciò che viene importato.
 
scuotimento degli alberiE così? È importante sapere cosa viene utilizzato con un'analisi statica del codice?
Certo che lo fa!
Perché con questo controllo, gli strumenti di sviluppo possono rilevare alcuni bug e più interessanti se contate sull'utilizzo di WebPack 2 o Rollup.js, le risorse trasferite saranno più piccole con Tree Shaking. Il Tree Shaking è una funzionalità che rimuove il codice inutilizzato controllando se una risorsa esposta (funzione, variabile) è effettivamente utilizzata da un altro blocco (se è importato).
 
 
Possiamo vedere qui un esempio di scuotimento degli alberi:

Documento sorgente
//-------------
// main.js
import {cube} from './maths.js';
console.log( cube( 5 ) ); // 125
//-------------
// maths.js
export function square ( x ) {
   return x * x;
}
// This function gets included
export function cube ( x ) {
   return x * x * x;
}
File di uscita
function cube ( x ) {
   return x * x * x;
}
console.log( cube( 5 ) ); // 125
Matteo Bretone CTO a JS Repubblica
[tipo separatore=”” size=”” icon=”stella”] [actionbox color=”default” title=”” description=”JS-REPUBLIC è una società di servizi specializzata nello sviluppo di JavaScript. Siamo un centro di formazione riconosciuto. Trova tutta la nostra formazione tecnica sul nostro sito partner dedicato alla Formazione” btn_label=”La nostra formazione” btn_link=”http://training.ux-republic.com” btn_color=”primary” btn_size=”big” btn_icon=”star” btn_external =”1″]