Archivio per marzo 2020
Optimizing Angular–minimizzare momentjs & lodash
Pubblicato da sierrodc in Angular, Javascript il marzo 2, 2020
Partendo dal presupposto che, anche grazie ad Angular, ci siamo liberati dal fardello jQuery, oggi ci sono alcune librerie javascript utili, molto popolari, ma che tendono a occupare più risorse del dovuto, ovvero:
- Banda (in particolare su 3g 4g)
- Cpu lato client (che, come minimo, deve parsarsi il js
- Cpu lato sviluppatore (che deve inserire tutte le dipendenze)
Due di queste librerie sono:
- Lodash: contiene funzioni utili per lavorare con i tipi/oggetti javascript, gestire correttamente null e undefined…
- Momentjs: contiene funzioni e oggetti utili a gestire le date in javascript (come dice la pagina ufficiale, parsare, formattare, validare e manipolare le date)
Progetto base e strumenti
Proviamo ora a creare un progetto Angular ”vuoto” (Angular 9 al momento della scrittura), compilare in produzione con le statistiche e analizzare i bundles generati:
npm install -g @angular/cli ng new EmptyNg --style=css --routing=false cd EmptyNg npm install webpack-bundle-analyzer --save-dev ng build -prod -stat-json npx webpack-bundle-analyzer .\dist\EmptyNg\stats-es2015.json
Abbiamo anche installato Webpack-bundle-analyzer in quanto ci permette di capire come sono organizzati i bundle generati da webpack (usato internamente da angular/cli). La situazione è la seguente:
per un totale di circa 170Kb di javascript (escludendo i file –es5 usati dai browser )
Aggiungiamo Lodash e momentjs
npm install moment npm install lodash
e usiamoli, altrimenti il l’algoritmo di treeshaking si accorge che non lo usiamo. Modifichiamo così app.component.ts in questo modo:
import * as moment from 'moment'; import * as _ from 'lodash'; … title = moment().format('YYYY-MM-DD') + _.isNumber(1);
Vediamo cosa è successo:
ng build -prod -stat-json npx webpack-bundle-analyzer .\dist\EmptyNg\stats-es2015.json
Il nostro applicativo è cresciuto drasticamente, il main è passato da 136Kb a 547Kb!
Ma vediamo come risolvere la cosa.
Minimizzare Momentjs
Subito si può osservare che, moment ha una grossa parte che sono le configurazioni delle lingue che difficilmente nel nostro progetto andremo a utilizzare (al più ne useremo alcune). Eliminarle si può, ed è anche semplice, basta utilizzare un plugin webpack apposito e passare la configurazione in fase di build di webpack:
- installare il plugin:
npm install moment-locales-webpack-plugin -save-dev
- creare un file di config di estensione di webpack (nel mio caso extra-webpack.config.js) e modificarlo quanto segue:
const MomentLocalesPlugin = require('moment-locales-webpack-plugin'); module.exports = { plugins: [ new MomentLocalesPlugin({ localesToKeep: ['it', 'en-gb'] //uniche lingue da tenere }) ] };
- aggiungere la configurazione in fase di build. Per far questo modificare angular.json e aggiungere in
"customWebpackConfig": { "path": "./extra-webpack.config.js", "replaceDuplicatePlugins": true },
- Occorre estendere il processo di build utilizzando il paccketto
npm install @angular-builders/custom-webpack
- e configurare il builder in angular.json:
"builder": "@angular-builders/custom-webpack:browser"
rebuildiamo e vediamo l’output:
e voilà. main.js è passato da 547Kb a circa la metà, 262Kb.
Minimizzare Lodash
Lodash è (quasi) una libreria contenente tante funzioni. L’idea è quella di importare le singole funzioni in base alle nostre necessità. Per farlo, occorre cambiare pacchetto npm (da lodash a lodash-es), e modificare gli import per importare le singole funzioni:
-
- Cambiare pacchetto nuget:
npm uninstall lodash npm install lodash-es
- modificare l’import delle funzioni richieste
import * as _ from 'lodash'; import { isNumber } from 'lodash/isNumber';
Questo il risultato:
Come si può vedere, lodash è letteralmente sparito. Ovviamente la dimensione di lodash sarà sempre più grande più funzioni andremo ad utilizzare (spoiler: ma è veramente necessario lodash?