Verketten und Minimieren mehrerer CSS- und JavaScript-Dateien mit Grunt.js (0.3.x)

99

Hinweis: Diese Frage ist nur für Grunt 0.3.x relevant und wurde als Referenz hinterlassen. Hilfe zur neuesten Version von Grunt 1.x finden Sie in meinem Kommentar unter dieser Frage.

Ich versuche derzeit, mit Grunt.js einen automatischen Erstellungsprozess einzurichten, um zuerst CSS- und JavaScript-Dateien zu verketten und dann zu minimieren.

Ich konnte meine JavaScript-Dateien erfolgreich verketten und minimieren, obwohl jedes Mal, wenn ich grunze, nur an die Datei angehängt zu werden scheint, anstatt sie zu überschreiben.

Was das Minimieren oder sogar Verketten von CSS betrifft, konnte ich dies bisher nicht tun!

In Bezug auf grunzende CSS-Module habe ich versucht consolidate-css, grunt-css& cssminaber ohne Erfolg. Ich konnte mir nicht vorstellen, wie man sie benutzt!

Meine Verzeichnisstruktur ist wie folgt (eine typische node.js-Anwendung):

  • app.js.
  • grunt.js
  • /public/index.html
  • / public / css / [verschiedene CSS-Dateien]
  • / public / js / [verschiedene Javascript-Dateien]

So sieht meine grunt.js-Datei derzeit im Stammordner meiner Anwendung aus:

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

};

Um es zusammenzufassen, ich brauche Hilfe bei zwei Fragen:

  1. So verketten und minimieren Sie beispielsweise alle meine CSS-Dateien unter dem Ordner /public/css/in einer Dateimain.min.css
  2. Warum hängt grunt.js weiterhin an die verketteten und minimierten Javascript-Dateien concat.jsund concat.min.jsdarunter an, /public/js/anstatt sie bei jeder gruntAusführung des Befehls zu überschreiben ?

Aktualisiert am 5. Juli 2016 - Upgrade von Grunt 0.3.x auf Grunt 0.4.x oder 1.x.

Grunt.jswurde in eine neue Struktur verschoben Grunt 0.4.x(die Datei heißt jetzt Gruntfile.js). Weitere Informationen zum Einrichten eines Erstellungsprozesses für finden Sie in meinem Open Source-Projekt Grunt.js SkeletonGrunt 1.x .

Der Wechsel von Grunt 0.4.xnach Grunt 1.x sollte nicht viele wesentliche Änderungen mit sich bringen .

Jasdeep Khalsa
quelle

Antworten:

107

concat.js wird in die concatQuelldateien der Aufgabe aufgenommen public/js/*.js. Sie könnten eine Aufgabe haben, die entfernt wirdconcat.js vor dem erneuten Verketten (sofern die Datei vorhanden ist), ein Array übergeben, um explizit zu definieren, welche Dateien und deren Reihenfolge verkettet werden sollen, oder die Struktur Ihres Projekts ändern.

Wenn Sie Letzteres tun, können Sie alle Ihre Quellen ./srcund Ihre erstellten Dateien unter ablegen./dest

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

Richten Sie dann Ihre Concat- Aufgabe ein

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

Ihre min Aufgabe

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

Die integrierte min- Task verwendet UglifyJS, sodass Sie einen Ersatz benötigen. Ich fand grunt-css ziemlich gut. Laden Sie es nach der Installation in Ihre Grunzdatei

grunt.loadNpmTasks('grunt-css');

Und dann einrichten

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

Beachten Sie, dass die Verwendung der eingebauten min ähnlich ist.

Ändern Sie Ihre defaultAufgabe in

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

Wenn gruntSie jetzt laufen , erhalten Sie die gewünschten Ergebnisse.

dest
├── css
   ├── concat.css
   └── concat.min.css
└── js
    ├── concat.js
    └── concat.min.js
jaime
quelle
1
Du bist ein Genie! Mir ist natürlich nie concatin den jsSinn gekommen, dass ich es in denselben Ordner aufnehmen würde, in dem es aufgenommen und angehängt würde! Ich habe angefangen, cssmin zu verwenden und es funktioniert großartig! Danke noch einmal.
Jasdeep Khalsa
1
Großartig, wirklich großartig! Aber die Dateinamen sind immer concat.min.cssund concat.min.js. Wenn ich etwas ändere, erneut ausführe und bereitstelle, erhalten die Benutzer nicht die neueste Version, da der Browser sie bereits zwischengespeichert hat. Es gibt eine Möglichkeit , zufällig die Datei zu benennen und Glied nach ihnen in den richtigen <link>und <script>Tags?
Tárcio Zemel
3
@ TárcioZemel Sie können die Version von package.json in den Dateinamen aufnehmen:concat.min-<%= pkg.version %>.js
Rui Nunes
1
Sie können .destwie folgt verwenden cssmin: { css:{ src: '<%= concat.css.dest %>', dest: './css/all.min.css'}} `Es ist das Ergebnis der Operationconcat -> css
Ivan Black
12

Ich möchte hier eine sehr, SEHR interessante Technik erwähnen, die in großen Projekten wie jQuery und Modernizr zum Verketten von Dingen verwendet wird.

Beide Projekte wurden vollständig mit requirejs-Modulen entwickelt (das sehen Sie in ihren Github-Repos) und verwenden dann den requirejs-Optimierer als sehr intelligenten Verketter. Das Interessante ist, dass, wie Sie sehen können, weder jQuery noch Modernizr Anforderungen benötigen, um zu funktionieren, und dies geschieht, weil sie das syntaktische Ritual von requirejs löschen, um requirejs in ihrem Code loszuwerden. So erhalten sie eine eigenständige Bibliothek, die mit requirejs-Modulen entwickelt wurde! Dank dessen sind sie unter anderem in der Lage, maßgeschneiderte Builds ihrer Bibliotheken durchzuführen.

Für alle, die an einer Verkettung mit dem Optimierer requirejs interessiert sind, lesen Sie diesen Beitrag

Es gibt auch ein kleines Tool, das die gesamte Kesselplatte des Prozesses abstrahiert : AlbanilJS

Augusto Altman Quaranta
quelle
Dies ist sehr interessant, aber für die Frage nicht relevant, da RequireJS ein Modullader ist und AFAIK
Jasdeep Khalsa
Vielen Dank! Sie haben Recht, RequireJS ist ein Modullader, der weder verkettet noch minimiert. Aber r.js (das RequireJS-Optimierungsprogramm -> requirejs.org/docs/optimization.html ) tut es. Insbesondere werden Ihre Module nach Abhängigkeiten sortiert. Die Mitarbeiter von Modernizr und jQuery nutzten den Bestellalgorithmus des Tools und verwendeten ihn speziell als intelligenten Verketter. Sie können ihre Repos überprüfen, um zu sehen, was sie tun.
Augusto Altman Quaranta
Unter Verwendung von grunts concat oder uglify wird die resultierende Datei in der Reihenfolge der angegebenen konfigurierten Quelldateien erstellt. Während RequireJS auf Abhängigkeit basiert. Unterschiedliche Ansätze können jedoch das gleiche Ergebnis erzielen.
Priyabagus
10

Ich stimme der obigen Antwort zu. Hier ist jedoch eine andere Möglichkeit der CSS-Komprimierung.

Sie können Ihr CSS mithilfe des YUI-Kompressors verknüpfen :

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
quelle
Wenn Sie 'grunt-css' verwenden, müssen Sie das Locale Npm-Modul benötigen. Stellen Sie daher sicher, dass sich bei der Installation von 'grunt-css' das Locale Npm-Modul befindet.
Anshul
7
Warum sollten Sie all diese Komplexität nutzen und in Ihrem Erstellungsprozess ein JVM aufrufen? Verlangsamt einfach alles ohne Grund.
Michael Salmon
3

Sie müssen das concat-Paket nicht hinzufügen, Sie können dies über cssmin wie folgt tun:

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

Und für js verwenden Sie uglify wie folgt:

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