Magento 2

La compilazione del Less in Magento2

Lettura 6 minuti

Inutile resistere! Sarete assimilati.

Sempre più sviluppatori Magento stanno iniziando a confrontarsi con la nuova versione della piattaforma. Per quanto riguarda il frontend i nuovi strumenti a disposizione sono tanti: RequireJs, Widget Jquery, preprocessori e task runner. Ma non è tutto oro quello che luccica.

E sì, perché tra le tante novità entusiasmanti e positive del frontend di Magento2 è nato anche un problema abbastanza serio che riguarda i tempi di compilazione del Less.

Nuove funzioni per Less

Andiamo con ordine. Magento2 cerca di estendere Less introducendo due nuove funzioni:

  • Un meccanismo di fallback per i file Less simile a quello che già conosciamo per i template.
  • La direttiva @magento_import che importa file Less con lo stesso nome da tutti i moduli presenti.

Queste funzioni non vengono eseguite da un task runner, come siamo abituati a vedere in ambiente frontend, ma da una classe di Magento, che elabora i file e li sposta all’interno della cartella pub/static, accessibile dal webserver.

L’idea è molto buona, ma il risultato finisce per creare più problemi che vantaggi.

Come funziona la compilazione Less in Magento2

Magento2 prevede due tipi di compilazione: una server side, l’unica utilizzabile in production mode, e una client side pensata per essere utilizzata in developer mode.

La compilazione server side è quella che garantisce le migliori prestazioni. Ad ogni richiesta, Magento serve direttamente i file .css se presenti nella cartella pub/static.

Se non trova un file, il preprocessore si mette alla ricerca di file con lo stesso nome ma con estensione .less prima all’interno del tema corrente, poi nei temi parent applicando il meccanismo di fallback.

Quando trova il file Less risolve le sintassi @import e _@magentoimport, ancora una volta seguendo la gerarchia di fallback, e copia tutti file all’interno della cartella etc/view_preprocessed.

Tutto il contenuto della cartella view_preprocessed viene dato in pasto al compilatore Less PHP che genera il css e lo pubblica nella cartella pub/static.

E’ facile immaginare, a questo punto, che la compilazione server side non si presta ad un ambiente di sviluppo. Infatti, in questa modalità, il preprocessore si attiva solo quando un file css non viene trovato e non quando viene modificato il Less del tema, come invece servirebbe.

La compilazione client side è quella deputata allo sviluppo. Funziona in maniera molto simile a quella server side con la differenza che nella cartella pub/static ci finiscono, anziché i css, i file Less con le direttive speciali già risolte. Con la compilazione client side attiva, infatti, è il browser che si occupa di compilare il Less tramite la libreria javascript Less.js. Questo risolve il problema di visualizzare le modifiche in tempo reale ma allunga terribilmente i tempi perché ad ogni reload della pagina deve mettersi in moto la compilazione, anche se nessun file Less è stato modificato.

Grunt Vs Gulp

Per permettere la compilazione del less anche con la compilazione server side attiva, Magento2 integra Grunt, un task runner che si occupa di osservare le modifiche fatte sui file Less e generare il css.

Il Gruntfile.js di Magento2, oltre al watch, ha 3 task principali:

  • Il task clean. Rimuove tutti i file dalla cartella pub/static e var/view_preprocessed e svuota la cache.
  • Il task exec. Esegue il task clean e poi chiama il comando per fare il deploy di tutti gli asset statici. Cioè crea in pub/static i symlinks di tutte le risorse statiche.
  • Il task less. Compila i file less nella cartella pub/static.

Grunt permette di lavorare sui file Less già elaborati da Magento: quelli all’interno della cartella pub/static. In questo modo Magento ad ogni chiamata si troverà sempre il file css pronto e non dovrà generarlo.

Anche la scelta del task runner, però, non è proprio all’insegna della velocità. Infatti Grunt è notevolmente più lento rispetto ad altri tool per l’automazione dei task, come ad esempio Gulp, reclamato a gran voce dalla community degli sviluppatori Magento.

Lo screen che segue serve a darvi un’idea di quale sia realmente la differenza tra i due task runner. Il test è stato fatto compilando i file .less del Boilerplate di Webcomm per Magento1 la prima volta con Grunt e la seconda con Gulp.

 

Dove si perde il tempo?

La domanda sorge spontanea: in quali di questi passaggi si perde il tempo?

  • La compilazione client side rallenta il tempo di caricamento delle pagine perché delega al browser il compito di interpretare il less.
  • Grunt è notevolmente più lento di Gulp (vd paragrafo precedente).
  • E’ percezione diffusa che il compilatore Less php non sia veloce come quello di node.
  • La sintassi @magento_import include i file less con lo stesso nome di tutti i moduli attivi sul Magento da tutti i temi presenti nella fallback di quello corrente. Questo fa sì che vadano processati anche alcuni file che non sono utili al tema. Ad esempio un tema mobile, che avesse come parent il tema desktop, si porterebbe dietro tutti gli stili del megamenu.

Possibili soluzioni per velocizzare il workflow

Questa questione è molto sentita all’interno della community e ha sollevato vivaci discussioni. Il team di Magento ha recepito i suggerimenti pervenuti e sta elaborando una soluzione che consenta agli sviluppatori di scegliere il task runner o il tool che preferiscono utilizzare.

Nel frattempo dal dibattito in rete sono nate diverse soluzioni che consentono di accelerare il workflow. La maggior parte di queste puntano a bypassare completamente la compilazione client side, compilare i file già processati da Magento e sostituire Grunt con Gulp.

Un esempio pratico

Questo è un esempio che in Bitbull utilizziamo su un progetto reale.

Per provarlo, prima di tutto, in developer mode e con la compilazione server side attiva, occorre lanciare il comando che elabora tutti gli asset statici del tema:

bin/magento dev:source-theme:deploy --theme <vendor>/<theme> --locale <locale>

A questo punto nella cartella pub/static/frontend// troveremo i file Less, i file javascript, i font e le immagini di tutti i moduli attivi all’interno di Magento. I file che ci interessano in questo momento si trovano nella cartella css, se stiamo ereditando dal tema blank saranno styles-l.less e styles-m.less. Questi contengono una serie di @import che includono i less di tutte le altre cartelle, cioè i symlink che puntano ai Less del tema corrente, e dei temi parent.

Adesso forse inizia ad essere tutto più chiaro. Il task watch all’interno del gulpfile.js osserva i file Less del tema, quando uno di questi viene modificato attiva la compilazione. Ma cosa compila? semplicemente i file style-l.less e style-m.less in pub static, che a loro volta si portano dietro i symlinks dei file modificati.

In questo esempio oltre al task watch abbiamo creato altri due task:

  • Il task css, che compila il Less, e che viene attivato dal watch.
  • Il task build che rimuove tutto il contenuto di pub/static, di var/view_preprocessed e la cache e lancia il comando per il deploy degli asset statici. Serve quando si aggiungono o rimuovono file Less.

La differenza tra il task Less di Magento/Grunt e il semplice task Less di Gulp del progetto:

 

Altre opzioni:

Approfondimenti

Gulp et al in Magento 2

http://devdocs.magento.com/guides/v2.0/frontend-dev-guide/css-topics/css_debug.html

http://devdocs.magento.com/guides/v2.0/frontend-dev-guide/css-topics/css-preprocess.html

http://gruntjs.com/

http://gulpjs.com/

Articolo scritto da