Frontend

Gestire gli assets statici con multipli ambienti con Magento 1

Lettura 5 minuti

Magento 2 ha introdotto tantissimi cambiamenti nella vita di noi sviluppatori Magento, primo fra tutti la quasi obbligatorietà di interfacciarsi con task runner, gestore di pacchetti, compilazione degli assets statici, ambienti diversificati (sviluppo, produzione).

Abbiamo già visto in diversi articoli come è possibile replicare alcune di queste caratteristiche anche su Magento 1.

In questo articolo vedremo come poter gestire gli assets statici diversificandoli in base all’ambiente di sviluppo,  e nel prossimo articolo, in base al tema/sottotema nel caso di template adaptive.

La procedura richiede l’utilizzo di task runner e nello specifico in questo articolo verrà trattato Gulp. Ciò non toglie che la stessa procedura sia tranquillamente replicabile anche su altri task runner come Grunt.

Immaginiamo di dover gestire un importante ecommerce con un tema custom e che il workflow imposto sia diviso su tre livelli:

  • Ambiente di sviluppo / locale (dev)
  • Ambiente di staging  (test)
  • Ambiente di produzione  (prod)

Ogni ambiente ha delle particolari necessità: prod dovrebbe avere gli assets statici unificati e minificati; dev dovrebbe averli separati e usando ad esempio LESS, anche una sourcemap per agevolare il lavoro di debugging e sviluppo; test potrebbe invece avere l’esigenza di passare da una modalità ad un’altra, sia per il debugging che per il test sulla corretta unificazione dei file (in particolare js che creano spesso dei problemi).

Modificare le impostazioni del proprio task runner per cambiare le modalità di generazione degli assets potrebbe essere alla lunga piuttosto oneroso in termini di tempo con rilasci abbastanza frequenti e espone comunque gli ambienti al rischio di possedere un’errata configurazione degli assets statici (es. su prod potrebbero finire css e js non minificati/unificati o in remoto potrebbero finire gli script di livereload e/o browsersync, generando errori per la mancanza del servizio).

Per ovviare a questi problemi abbiamo testato e provato diverse modalità. Quella che maggiormente riduce la possibilità di errore è quella di creare molteplici file statici in modalità differenti.

 

Generazione di file statici diversificati

 

Per ottenere diversi file dal medesimo sorgente è possibile modificare il proprio gulpfile.js creando le configurazioni e duplicando il task.

Supponendo di avere per ora solo due livelli. dev e prod partendo da un unico task e config:

var bitbullConfig = {

minifyCss: true,

uglifyJS: true

}

gulp.task('css', function() {

var stream = gulp

.src('src/less/style.less')

.pipe(less().on('error', notify.onError(function (error) {

return 'Errore compilazione LESS: ' + error.message;

})))

.pipe(gulp.dest('css'));

// Set Minify

if (bitbullConfig.minifyCss) {

stream.pipe(minifycss());

}

return stream;

return stream

.pipe(gulp.dest('css'))

.pipe(notify({ message: 'Successfully compiled LESS' }));

});

duplicando diventa:

var bitbullConfig = {
minifyCss: true,
uglifyJS: true,
minifyCss-Dev: false,
uglifyJS-Dev: false
}

gulp.task('css', function() {
var stream = gulp
.src('src/less/style.less')
.pipe(less().on('error', notify.onError(function (error) {
return 'Errore compilazione LESS: ' + error.message;
})))
.pipe(gulp.dest('css'));
// Set Minify
if (bitbullConfig.minifyCss) {
stream.pipe(minifycss());
}
return stream;

gulp.task('css-dev', function() {
var stream = gulp
.src('src/less/style-dev.less')
.pipe(less().on('error', notify.onError(function (error) {
return 'Errore compilazione LESS: ' + error.message;
})))
.pipe(gulp.dest('css'));
// Set Minify
if (bitbullConfig.minifyCss-Dev) {
stream.pipe(minifycss());
}
return stream;

Create il nuovo file less che il task userà per generare il file less. Essendo una copia di style.less, dovrebbe contenere solo:

@import “style.less”;

Ovviamente se dovesse servirvi qualche stile su dev per delle particolari casistiche, potete includerlo nel file creato.

Aggiungete ora il nuovo task creata anche nel task default e in altri task utilizzate (es. gulp watch) per poter così generare due file distinti:

style.css

style-dev.css

Per quanto riguarda invece i javascript, la procedura cambia.

Supponiamo di avere questo task:

var scripts = {
'bower_components/jquery/dist/jquery.js',
'bower_components/bootstrap/js/transition.js',
'bower_components/bootstrap/js/collapse.js',
'bower_components/bootstrap/js/carousel.js',
'src/js/script.js',
'src/js/browsersync.js',
'src/js/livereload.js'
}
gulp.task('js', function() {
var stream = gulp
.src(scripts)
.pipe(concat(scripts.js'));
if ( bitbullConfig.uglifyJS == true) {  // Uglify function
stream.pipe(uglify());
}
return stream;

.pipe(gulp.dest('js'))

.pipe(notify({ message: 'Successfully compiled JavaScript' }));

});

possiamo creare più variabili per racchiudere i js in ambiti diversi:

var scripts = {
'bower_components/jquery/dist/jquery.js',
'bower_components/bootstrap/js/transition.js',
'bower_components/bootstrap/js/collapse.js',
'bower_components/bootstrap/js/carousel.js',
'src/js/script.js'
}
var scripts-dev = {
'src/js/browsersync.js',
'src/js/livereload.js'
}

e quindi duplicare il task:

gulp.task('js', function() {

var stream = gulp

.src(scripts)

.pipe(concat('scripts.js'));

if ( bitbullConfig.uglifyJS == true) {  // Uglify function

stream.pipe(uglify());

}

return stream;

.pipe(gulp.dest('js'))

.pipe(notify({ message: 'Successfully compiled JavaScript' }));

});

gulp.task('js-dev', function() {

var scripts = scripts.concat(eval(scripts-dev));

var stream = gulp

.src(scripts)

.pipe(concat('scripts-dev.js'));

if ( bitbullConfig.uglifyJS-dev == true) {  // Uglify function

stream.pipe(uglify());

}

return stream;

.pipe(gulp.dest('js'))

.pipe(notify({ message: 'Successfully compiled JavaScript' }));

});

Fatto questo ora si avranno due file js:

scripts.js

scrips-dev.js

Creare le condizioni per ogni ambiente

Ora che abbiamo i nostri file diversificati, rimane il problema di dover assegnare i file ad ogni ambiente, cioè far sì che Magento sappia quali file caricare per ogni ambiente.

Per dare le giuste condizioni, abbiamo pensato di utilizzare un piccolo modulo che aggiunge una nuova configurazione alla tab sviluppatore e usare questa stessa configurazione come condizione nel layout xml del nostro tema.

Partiamo quindi dal modulo:

Creiamo il file xml di configurazione:

app/code/local/Bitbull/Theme/etc/config.xml

<config>
   <modules>
      <Bitbull_Theme>
         <version>1.0.0</version>
      </Bitbull_Theme>
   </modules>
</config>

il file di sistema:

<sections>
   <groups>
      <envcontrol translate="label">
         <label>Env Config</label>
         <frontend_type>text</frontend_type>
         <sort_order>200</sort_order>
         <show_in_default>1</show_in_default>
         <show_in_website>1</show_in_website>
         <show_in_store>1</show_in_store>
         <fields>
            <active translate="label,comment"></active>
            <label>Active Assets for Dev Env.</label>
            <comment><![CDATA[Use the development version of js and css]]>;</comment>;
            
            <frontend_type>select</frontend_type>
            
            <source_model>adminhtml/system_config_source_yesno</source_model>
            
            <sort_order>10</sort_order>
            
            <show_in_default>1</show_in_default>
            
            <show_in_website>0</show_in_website>
            
            <show_in_store>0</show_in_store>
         </fields>
      </envcontrol>
   </groups>
</sections>

E il file di dichiarazione del modulo in app/etc/modules:

<config>
   <modules>
      <Bitbull_Theme>
         <active>true</active>
         <codePool>local</codePool>
      </Bitbull_Theme>
   </modules>
</config>

Una volta fatto si dovrebbe ottenere la tendina di configurazione con valore booleano dell’ambiente di sviluppo (visibile in Sistema -> Configurazione -> Developer).

A questo punto è possibile usare questa condizione per attivare/disattivare gli stili e gli script di sviluppo; aprite il file xml del tema e usate la condizione per rimuovere gli stili standard e aggiungere quelli dev:

<action ifconfig="dev/envcontrol/active" method="removeItem"><type>skin_css</type><name>css/style.css</name><params/></action>

<action ifconfig="dev/envcontrol/active" method="removeItem"><type>skin_js</type><name>js/scripst.js</name><params/></action>

<action ifconfig="dev/envcontrol/active" method="addItem"><type>skin_css</type><name>css/style-dev.css</name></action>

<action ifconfig="dev/envcontrol/active" method="addItem"><type>skin_js</type><name>js/scripts-dev.js</name></action>

Usando questo semplice stratagemma è possibile quindi switchare i file statici passando dai file standard (destinati all’ambiente di prod) a quelli “-dev” destinati all’ambiente di sviluppo.

Possibili integrazioni e miglioramenti

La procedura che ho descritto è un esempio molto banale e semplificato di quello che è possibile fare con questo approccio. Modificando opportunamente il gulpfile è possibile migliorare il codice per renderlo più compatto (evitando duplicazioni massicce del codice ma centralizzando le funzioni), inserire nuovi ambienti e casistiche, prevedere opzioni aggiuntive ecc..

Nel prossimo articolo vedremo come usare questo approccio per creare dei temi adaptive seguendo un metodo simile a quello di Magento 2 (anche se molto più semplice) senza necessariamente creare eccessivi override e/o doppioni da mantenere e gestire.

Articolo scritto da

Antonio Carboni