Comment concaténer et réduire plusieurs fichiers CSS et JavaScript avec Grunt.js (0.3.x)

99

Remarque: Cette question n'est pertinente que pour Grunt 0.3.x et a été laissée pour référence. Pour obtenir de l'aide sur la dernière version de Grunt 1.x, veuillez consulter mon commentaire sous cette question.

J'essaie actuellement d'utiliser Grunt.js pour configurer un processus de construction automatique pour d'abord concaténer puis réduire les fichiers CSS et JavaScript.

J'ai réussi à concaténer et à réduire mes fichiers JavaScript, bien que chaque fois que je lance grunt, il semble simplement s'ajouter au fichier au lieu de les écraser.

En ce qui concerne le CSS de minification ou même de concaténation, je n'ai pas encore pu le faire!

En termes de modules grognement CSS j'ai essayé d' utiliser consolidate-css, grunt-csset cssminmais en vain. Je n'ai pas pu comprendre comment les utiliser!

Ma structure de répertoires est la suivante (étant une application node.js typique):

  • app.js
  • grunt.js
  • /public/index.html
  • / public / css / [divers fichiers css]
  • / public / js / [divers fichiers javascript]

Voici à quoi ressemble actuellement mon fichier grunt.js dans le dossier racine de mon application:

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');

};

Donc, pour résumer, j'ai besoin d'aide pour deux questions:

  1. Comment concaténer et réduire tous mes fichiers css sous le dossier /public/css/en un seul fichier, par exemplemain.min.css
  2. Pourquoi grunt.js continue-t-il d'ajouter aux fichiers javascript concaténés et minifiés concat.jset concat.min.jssous /public/js/au lieu de les écraser à chaque fois que la commande gruntest exécutée?

Mise à jour le 5 juillet 2016 - Mise à niveau de Grunt 0.3.x vers Grunt 0.4.x ou 1.x

Grunt.jsa été déplacé vers une nouvelle structure dans Grunt 0.4.x(le fichier est maintenant appelé Gruntfile.js). Veuillez consulter mon projet open source Grunt.js Skeleton pour obtenir de l'aide sur la configuration d'un processus de construction pour Grunt 1.x.

Passer de Grunt 0.4.xà Grunt 1.x ne devrait pas introduire beaucoup de changements majeurs .

Jasdeep Khalsa
la source

Réponses:

107

concat.js est inclus dans le concat fichiers source de tâche public/js/*.js. Vous pouvez avoir une tâche qui supprime concat.js(si le fichier existe) avant de concaténer à nouveau, transmettre un tableau pour définir explicitement les fichiers que vous souhaitez concaténer et leur ordre, ou modifier la structure de votre projet.

Si vous faites ce dernier, vous pouvez mettre toutes vos sources sous ./srcet vos fichiers construits sous./dest

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

Ensuite, configurez votre tâche concat

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

Votre tâche min

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

La construction en min tâche utilise UglifyJS, vous avez donc besoin d' un remplacement. J'ai trouvé que grunt-css était plutôt bon. Après l'avoir installé, chargez-le dans votre fichier grunt

grunt.loadNpmTasks('grunt-css');

Et puis configurez-le

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

Notez que l'utilisation est similaire à celle du min.

Changez votre defaulttâche en

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

Maintenant, courir gruntproduira les résultats souhaités.

dest
├── css
   ├── concat.css
   └── concat.min.css
└── js
    ├── concat.js
    └── concat.min.js
jaime
la source
1
Tu es un génie! Il ne m'est jamais venu à l'esprit que, bien sûr, si j'inclus concatdans le même jsdossier, il le ramasserait et l'ajouterait! J'ai commencé à utiliser cssmin et cela fonctionne très bien! Merci encore.
Jasdeep Khalsa
1
Super, vraiment super! Mais les noms de fichiers sont toujours concat.min.csset concat.min.js. Si je modifie quelque chose, que je le réexécute et que je le déploie, les utilisateurs n'obtiendront pas la version la plus récente car le navigateur l'a déjà mise en cache. Il existe un moyen de nommer le fichier au hasard et de les lier selon les balises <link>et appropriées <script>?
Tárcio Zemel
3
@ TárcioZemel Vous pouvez inclure la version de package.json sur le nom du fichier:concat.min-<%= pkg.version %>.js
Rui Nunes
1
Vous pouvez utiliser .destcomme ceci cssmin: { css:{ src: '<%= concat.css.dest %>', dest: './css/all.min.css'}} `C'est le résultat de l'opérationconcat -> css
Ivan Black
12

Je veux mentionner ici une technique très, TRÈS, intéressante qui est utilisée dans d'énormes projets comme jQuery et Modernizr pour concaténer des choses.

Ces deux projets sont entièrement développés avec des modules requirejs (vous pouvez le voir dans leurs dépôts github), puis ils utilisent l'optimiseur requirejs comme un concaténateur très intelligent. La chose intéressante est que, comme vous pouvez le voir, ni jQuery ni Modernizr n'a besoin de requirejs pour fonctionner, et cela se produit parce qu'ils effacent le rituel syntatique requirejs afin de se débarrasser des requirejs dans leur code. Ils se retrouvent donc avec une bibliothèque autonome qui a été développée avec des modules requirejs! Grâce à cela, ils sont en mesure d'effectuer des constructions coupées de leurs bibliothèques, entre autres avantages.

Pour tous ceux qui s'intéressent à la concaténation avec l'optimiseur requirejs, consultez cet article

Il existe également un petit outil qui résume tout le passe-partout du processus: AlbanilJS

Augusto Altman Quaranta
la source
Ceci est très intéressant mais pas pertinent par rapport à la question puisque RequireJS est un chargeur de module, il ne concatène ni ne minimise AFAIK
Jasdeep Khalsa
Merci! Vous avez raison, RequireJS est un chargeur de module et il ne concatène ni ne minimise. Mais r.js (l'optimiseur RequireJS -> requirejs.org/docs/optimization.html ) le fait. Plus précisément, il concatène vos modules en les triant par dépendances. Les gars de Modernizr et jQuery ont profité de l'algorithme de commande de l'outil et l'utilisent spécifiquement comme concaténateur intelligent. Vous pouvez vérifier leurs dépôts pour voir ce qu'ils font.
Augusto Altman Quaranta
En utilisant concat ou uglify de grunt, le fichier résultant est composé en utilisant l'ordre des fichiers source spécifiés configurés. Alors que RequireJS est basé sur la dépendance. Une approche différente peut encore aboutir au même résultat.
priyabagus
10

Je suis d'accord avec la réponse ci-dessus. Mais voici une autre méthode de compression CSS.

Vous pouvez concater votre CSS en utilisant compresseur 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;
    });
  });
}; 
Anshul
la source
Dans le cas où vous utilisez 'grunt-css', vous devez avoir besoin du module Locale Npm, alors assurez-vous que lorsque vous installez 'grunt-css', il doit être dans le module Locale Npm.
Anshul
7
Pourquoi voudriez-vous faire toute cette complexité et appeler un jvm dans votre processus de construction? Ralentit tout cela sans raison.
michael salmon le
3

Vous n'avez pas besoin d'ajouter le package concat, vous pouvez le faire via cssmin comme ceci:

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']
        }
      }
    }

Et pour js, utilisez uglify comme ceci:

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