Javascript patterns
&
Module loaders
Text
Obbiettivi
- Capire cos'è un pattern javascript e sapere quali sono quelli più utilizzati
- Primo approfondimento sul patterne CommonJS
- Cos'è un bundler e come usare Browserify
Il problema
Javascript non offre un metodo per gestire le dipendenze nativamente. Less ha @import, Php ha require(), ecc...
Questo crea non pochi problemi all'organizzazione dei progetti, soprattutto quelli di medie grandi dimensioni.
Javascript Patterns
-
IIFE (Immediately Invoked Function Expression)
-
CommonJS (Node)
- AMD (Require.js)
LA SOLUZIONE
Module
Un modulo è un pezzo di codice isolato e agnostico.
Un modulo può avere dipendenze, ma devono essere esplicitate.
Un modulo deve restituire un risultato.
IIFE
(Immediately Invoked Function Expression)
Una soluzione a metà
(function(root) {
var calculator = {
sum: function(a, b) {
return a + b;
}
};
root.calculator = calculator;
})(this);
console.log(calculator.sum(1, 2)); // => 3
calculator.js
app.js
All'interno delle funzioni abbiamo privacy, e possiamo esporre nello scope globale solo quello che ci serve
Con questo metodo però non creiamo nessuna alberatura esplicita delle nostre dipendenze.
Ci tocca farcelo a noi, con conseguente rischio di
TypeError: undefined is not a function
CommonJS
(Node.js [CommonJs è un comitato spontaneo]) link
module.exports = {
sum: function(a, b) { return a + b; }
};
var calculator = require('./calculator');
console.log(calculator.sum(1, 2));
calculator.js
app.js
- Molto più elegante di IIFE
- Non vi è modo di accedere al file calculator.js dall'esterno
- Viene esportato SOLO il contenuto di module.exports
Require() legge il file specificato e ritorna il contenuto dell'oggetto module.exports senza eseguirlo.
require('jquery'); // node_moules
require('./jquery'); // cartella attuale
require('../vendors/jquery'); // cartella vendors
La chiamata Require è sincrona. Per questo motivo per funzionare in un browser, il comitato CommonJS ha pensato ad un'alternativa: il pattern asincrono AMD.
AMD
(Asynchronous Module Definition)
define("calculator", function() {
return {
sum: function(a, b) { return a + b; }
};
});
define("app", ["calculator"], function(calculator) {
console.log(calculator.sum(1, 2)); // => 3
});
calculator.js
app.js
- define() definisce sia il modulo che le dipendenze necessarie per il funzionamento dello stesso.
- Le dipendenze vengono caricate in modo asincrono, e poi vengono passate alla callback sotto forma di parametro.
Se il modulo prevede più di una dipendenza occorre preoccuparsi di rispettare l'ordine dei parametri.
Questa soluzione è meno elegante rispetto a Node.js, ma è l'unica via percorribile all'interno di un browser.
(per caricare progressivamente solo gli script che ci servono e far avanzare la nostra app senza dover aspettare il caricamento completo di un unico monolite)
Nella pratica però, su progetti medio/grandi vi è un overhead http che compromette le prestazioni.
Require.js (popolare implementazione del pattern AMD)
propone di creare preventivamente un bundle. link
ECMAScript 6
(Javascript 2015) - link
var calculator = function() {
return {
sum: function(a, b) { return a + b; }
};
};
export default calculator;
import calculator from 'calculator';
console.log(calculator.sum(1, 2)); // => 3
calculator.js
app.js
L'obbiettivo di ES6 è di creare un module loader pattern che sia elegante come CommonJs e che abbia il supporto per il caricamento asincrono delle dipendenze come AMD
Browserify ci permette di utilizzare i moduli del pattern CommonJs (node) all'interno del un browser
Browserify fa un'analisi dell'alberatura delle dipendenze partendo da un entry-point.
Ordina le dipendenze del nostro progetto e si occupa di richiamarle (eventualmente ricorsivamente) quando necessario.
Cosa fa
I transformers
Un ulteriore vantaggio di usare un bundler è la possibilità di utilizzare dei transformers, come ad esempio coffeescript.
module.exports = (n) -> n * 111
baz.coffee
module.exports = require('./baz.coffee')(5)
bar.js
Oppure è possibile includere il transformer Babelify per poter utilizzare la sintassi del nuovo ES6.
Javascript Module Loaders
By giulico
Javascript Module Loaders
- 889