Come concatenare e minimizzare più file CSS e JavaScript con Grunt.js (0.3.x)


99

Nota: questa domanda è rilevante solo per Grunt 0.3.x ed è stata lasciata come riferimento. Per assistenza con l'ultima versione di Grunt 1.x, vedere il mio commento sotto questa domanda.

Attualmente sto cercando di utilizzare Grunt.js per impostare un processo di compilazione automatico per prima concatenare e poi minimizzare i file CSS e JavaScript.

Sono stato in grado di concatenare e minimizzare con successo i miei file JavaScript, anche se ogni volta che eseguo grugnito sembra che si aggiunga al file invece di sovrascriverli.

Per quanto riguarda la minimizzazione o anche la concatenazione dei CSS, non sono ancora stato in grado di farlo!

In termini di moduli CSS grugnito ho provato ad utilizzare consolidate-css, grunt-csse cssminma senza alcun risultato. Non riuscivo a capire come usarli!

La struttura della mia directory è la seguente (essendo una tipica applicazione node.js):

  • app.js
  • grunt.js
  • /public/index.html
  • / public / css / [vari file css]
  • / public / js / [vari file javascript]

Ecco come appare il mio file grunt.js attualmente nella cartella principale della mia applicazione:

module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: '<json:package.json>',
    concat: {
      dist: {
        src: 'public/js/*.js',
        dest: 'public/js/concat.js'
      }
    },
    min: {
      dist: {
        src: 'public/js/concat.js',
        dest: 'public/js/concat.min.js'
      }
    },
    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true,
        node: true
      },
      globals: {
        exports: true,
        module: false
      }
    },
    uglify: {}
  });

  // Default task.
  grunt.registerTask('default', 'concat min');

};

Quindi, solo per riassumere, ho bisogno di aiuto con due domande:

  1. Come concatenare e minimizzare tutti i miei file CSS nella cartella /public/css/in un unico file, ad esempiomain.min.css
  2. Perché continuano a grunt.js aggiungendo ai file JavaScript concatenati e minified concat.jse concat.min.jssotto /public/js/invece di sovrascrivere ogni volta il comando gruntviene eseguito?

Aggiornato il 5 luglio 2016 - Aggiornamento da Grunt 0.3.xa Grunt 0.4.xo 1.x.

Grunt.jssi è spostato in una nuova struttura in Grunt 0.4.x(il file è ora chiamato Gruntfile.js). Consulta il mio progetto open source Grunt.js Skeleton per assistenza con l'impostazione di un processo di compilazione per Grunt 1.x.

Il passaggio da Grunt 0.4.xa Grunt 1.x non dovrebbe introdurre molti cambiamenti importanti .

Risposte:


107

concat.js viene incluso nei concatfile di origine dell'attività public/js/*.js. Potresti avere un'attività che rimuove concat.js(se il file esiste) prima di concatenarlo di nuovo, passare un array per definire esplicitamente quali file vuoi concatenare e il loro ordine, o cambiare la struttura del tuo progetto.

In quest'ultimo caso, potresti mettere tutti i tuoi sorgenti sotto ./srce i tuoi file compilati sotto./dest

src
├── css
   ├── 1.css
   ├── 2.css
   └── 3.css
└── js
    ├── 1.js
    ├── 2.js
    └── 3.js

Quindi imposta il tuo compito concatenato

concat: {
  js: {
    src: 'src/js/*.js',
    dest: 'dest/js/concat.js'
  },
  css: {
    src: 'src/css/*.css',
    dest: 'dest/css/concat.css'
  }
},

Il tuo compito minimo

min: {
  js: {
    src: 'dest/js/concat.js',
    dest: 'dest/js/concat.min.js'
  }
},

L' attività min incorporata utilizza UglifyJS, quindi è necessaria una sostituzione. Ho trovato grunt-css abbastanza buono. Dopo averlo installato, caricalo nel tuo file grugnito

grunt.loadNpmTasks('grunt-css');

E poi impostalo

cssmin: {
  css:{
    src: 'dest/css/concat.css',
    dest: 'dest/css/concat.min.css'
  }
}

Si noti che l'utilizzo è simile al min.

Cambia il tuo defaultcompito in

grunt.registerTask('default', 'concat min cssmin');

Ora, la corsa gruntprodurrà i risultati desiderati.

dest
├── css
   ├── concat.css
   └── concat.min.css
└── js
    ├── concat.js
    └── concat.min.js

1
Sei un genio! Non mi è mai venuto in mente che, ovviamente, se lo includessi concatnella stessa jscartella, lo avrebbe raccolto e aggiunto! Ho iniziato a usare cssmin e funziona benissimo! Grazie ancora.
Jasdeep Khalsa

1
Fantastico, davvero fantastico! Ma i nomi dei file sono sempre concat.min.csse concat.min.js. Se modifico qualcosa, rieseguo e distribuisco, le persone non otterranno la versione più recente perché il browser l'ha già memorizzata nella cache. C'e 'un modo per nominare in modo casuale i file e collegarli secondo i tag appropriati <link>e <script>?
Tárcio Zemel

3
@ TárcioZemel Puoi includere la versione di package.json nel nome del file:concat.min-<%= pkg.version %>.js
Rui Nunes

1
Puoi usare in .destquesto modo cssmin: { css:{ src: '<%= concat.css.dest %>', dest: './css/all.min.css'}} `È il risultato dell'operazioneconcat -> css
Ivan Black

12

Voglio menzionare qui una tecnica molto, MOLTO interessante che viene utilizzata in progetti enormi come jQuery e Modernizr per cose concatenate.

Entrambi questi progetti sono interamente sviluppati con moduli requirejs (puoi vederlo nei loro repository github) e quindi usano l'ottimizzatore requirejs come un concatenatore molto intelligente. La cosa interessante è che, come puoi vedere, né jQuery né Modernizr hanno bisogno di requirejs per funzionare, e questo accade perché cancellano il rituale sintatico requirejs per sbarazzarsi di requirejs nel loro codice. Quindi finiscono con una libreria standalone che è stata sviluppata con i moduli requirejs! Grazie a questo sono in grado di eseguire build ridotte delle loro librerie, tra gli altri vantaggi.

Per tutti coloro che sono interessati alla concatenazione con l'ottimizzatore requirejs, dai un'occhiata a questo post

Inoltre c'è un piccolo strumento che astrae tutto il boilerplate del processo: AlbanilJS


Questo è molto interessante ma non rilevante per la domanda poiché RequireJS è un caricatore di moduli, non concatena o minimizza AFAIK
Jasdeep Khalsa

Grazie! Hai ragione, RequireJS è un caricatore di moduli e non concatena né minimizza. Ma r.js (l'ottimizzatore RequireJS -> requirejs.org/docs/optimization.html ) lo fa. Più specificamente, concatena i moduli ordinandoli in base alle dipendenze. I ragazzi di Modernizr e jQuery hanno approfittato dell'algoritmo di ordinamento dello strumento e lo usano specificamente come concatenatore intelligente. Puoi controllare i loro repository per vedere cosa stanno facendo.
Augusto Altman Quaranta

Utilizzando concat o uglify di grunt, il file risultante viene composto utilizzando l'ordine dei file di origine specificati configurati. Mentre RequireJS si basa sulla dipendenza. Un approccio diverso può tuttavia ottenere lo stesso risultato.
priyabagus

10

Sono d'accordo con la risposta di cui sopra. Ma ecco un altro modo di compressione CSS.

Puoi concatenare il tuo CSS usando il compressore YUI :

module.exports = function(grunt) {
  var exec = require('child_process').exec;
   grunt.registerTask('cssmin', function() {
    var cmd = 'java -jar -Xss2048k '
      + __dirname + '/../yuicompressor-2.4.7.jar --type css '
      + grunt.template.process('/css/style.css') + ' -o '
      + grunt.template.process('/css/style.min.css')
    exec(cmd, function(err, stdout, stderr) {
      if(err) throw err;
    });
  });
}; 

Nel caso in cui tu stia usando 'grunt-css' devi aver bisogno del modulo Locale Npm, quindi assicurati che quando installi 'grunt-css' in deve essere nel modulo Locale Npm.
Anshul

7
Perché dovresti voler fare tutta questa complessità e chiamare una jvm nel tuo processo di compilazione? Rallenta tutto senza motivo.
michael salmon

3

Non è necessario aggiungere il pacchetto concat, puoi farlo tramite cssmin in questo modo:

cssmin : {
      options: {
            keepSpecialComments: 0
      },
      minify : {
            expand : true,
            cwd : '/library/css',
            src : ['*.css', '!*.min.css'],
            dest : '/library/css',
            ext : '.min.css'
      },
      combine : {
        files: {
            '/library/css/app.combined.min.css': ['/library/css/main.min.css', '/library/css/font-awesome.min.css']
        }
      }
    }

E per js, usa uglify in questo modo:

uglify: {
      my_target: {
        files: {
            '/library/js/app.combined.min.js' : ['/app.js', '/controllers/*.js']
        }
      }
    }

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.