Jak łączyć i zmniejszać wiele plików CSS i JavaScript za pomocą Grunt.js (0.3.x)

99

Uwaga: to pytanie dotyczy tylko Grunt 0.3.x i zostało pozostawione w celach informacyjnych. Aby uzyskać pomoc dotyczącą najnowszej wersji Grunt 1.x, zobacz mój komentarz pod tym pytaniem.

Obecnie próbuję użyć Grunt.js do skonfigurowania automatycznego procesu kompilacji, aby najpierw połączyć, a następnie minifikować pliki CSS i JavaScript.

Udało mi się pomyślnie połączyć i zminimalizować moje pliki JavaScript, chociaż za każdym razem, gdy uruchamiam grunt, wydaje się, że po prostu dołącza do pliku, zamiast je nadpisywać.

Jeśli chodzi o minifikację, a nawet konkatenację CSS, na razie nie mogłem tego zrobić!

Grunt pod względem modułów CSS Próbowałem, używając consolidate-css, grunt-css& cssmin, ale bezskutecznie. Nie mogłem się dowiedzieć, jak ich używać!

Moja struktura katalogów jest następująca (jest to typowa aplikacja node.js):

  • app.js
  • grunt.js
  • /public/index.html
  • / public / css / [różne pliki css]
  • / public / js / [różne pliki javascript]

Oto jak obecnie wygląda mój plik grunt.js w folderze głównym mojej aplikacji:

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

};

Podsumowując, potrzebuję pomocy z dwoma pytaniami:

  1. /public/css/Powiedzmy, jak połączyć i zminimalizować wszystkie moje pliki css w folderze w jeden plikmain.min.css
  2. Dlaczego grunt.js zachować na dołączenie do łączone i minified plików javascript concat.jsi concat.min.jspod /public/js/zamiast nadpisywania ich za każdym razem, gdy polecenie gruntjest uruchamiane?

Zaktualizowano 5 lipca 2016 r. - Aktualizacja z Grunt 0.3.x do Grunt 0.4.x lub 1.x

Grunt.jsprzeniósł się do nowej struktury w Grunt 0.4.x(plik ma teraz nazwę Gruntfile.js). Proszę zobaczyć mój projekt Open Source Grunt.js Skeleton, aby uzyskać pomoc w konfiguracji procesu kompilacji dla Grunt 1.x.

Przejście z Grunt 0.4.xdo Grunt 1.x nie powinno wprowadzać wielu większych zmian .

Jasdeep Khalsa
źródło

Odpowiedzi:

107

concat.js jest dołączany do concat plików źródłowych zadania public/js/*.js. Możesz mieć zadanie, które usuwa concat.js(jeśli plik istnieje) przed ponownym połączeniem, przekazuje tablicę, aby jawnie określić, które pliki chcesz połączyć i ich kolejność, lub zmienić strukturę projektu.

Jeśli robisz to drugie, możesz umieścić wszystkie swoje źródła pod, ./srca zbudowane pliki pod./dest

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

Następnie skonfiguruj konkat zadanie

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

Twój min zadanie

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

Nagromadzenie w min zadania wykorzystuje UglifyJS, więc trzeba wymienić. Znalazłem grunt-css jest całkiem niezły. Po zainstalowaniu załaduj go do swojego pliku gruntowego

grunt.loadNpmTasks('grunt-css');

A potem skonfiguruj

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

Zwróć uwagę, że użycie jest podobne do wbudowanego min.

Zmień swoje defaultzadanie na

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

Teraz bieganie gruntprzyniesie oczekiwane rezultaty.

dest
├── css
   ├── concat.css
   └── concat.min.css
└── js
    ├── concat.js
    └── concat.min.js
jaime
źródło
1
Jesteś geniuszem! Nigdy nie przyszło mi do głowy, że oczywiście gdybym umieścił concatw tym samym jsfolderze, zgarnąłby go i dołączył! Zacząłem używać cssmin i działa świetnie! Dzięki jeszcze raz.
Jasdeep Khalsa
1
Świetnie, naprawdę świetnie! Ale nazwy plików to zawsze concat.min.cssi concat.min.js. Jeśli coś zmodyfikuję, uruchomię ponownie i wdrożę, ludzie nie otrzymają najnowszej wersji, ponieważ przeglądarka już ją zapisała w pamięci podręcznej. Czy istnieje sposób, aby losowo nazwać plik i połączyć je zgodnie z właściwymi tagami <link>i <script>?
Tárcio Zemel
3
@ TárcioZemel Możesz dołączyć wersję package.json do nazwy pliku:concat.min-<%= pkg.version %>.js
Rui Nunes
1
Możesz użyć w .destten sposób cssmin: { css:{ src: '<%= concat.css.dest %>', dest: './css/all.min.css'}} `To wynik operacjiconcat -> css
Ivan Black
12

Chcę tutaj wspomnieć o bardzo, BARDZO, interesującej technice, która jest używana w dużych projektach, takich jak jQuery i Modernizr, do łączenia rzeczy.

Oba te projekty są w całości opracowane z modułami requirejs (widać to w ich repozytoriach na githubie), a następnie używają optymalizatora requirejs jako bardzo inteligentnego konkatenatora. Ciekawostką jest to, że jak widać, ani jQuery, ani Modernizr nie potrzebuje do działania requirejs, a dzieje się tak, ponieważ wymazują rytuał syntatyczny requirejs, aby pozbyć się requirejs w swoim kodzie. W rezultacie otrzymali samodzielną bibliotekę, która została opracowana z modułami requirejs! Dzięki temu są w stanie między innymi wykonywać skromne kompilacje swoich bibliotek.

Dla wszystkich zainteresowanych konkatenacją z optymalizatorem requirejs, sprawdź ten post

Jest też małe narzędzie, które wyabstrahuje wszystkie schematy tego procesu: AlbanilJS

Augusto Altman Quaranta
źródło
Jest to bardzo interesujące, ale nie dotyczy pytania, ponieważ RequireJS to moduł ładujący, nie łączy ani nie
minimalizuje
Dzięki! Masz rację, RequireJS to program ładujący moduły, który nie łączy się ani nie minifikuje. Ale r.js (optymalizator RequireJS -> requirejs.org/docs/optimization.html ) to robi. Dokładniej, łączy moduły, porządkując je według zależności. Faceci z Modernizr i jQuery wykorzystali algorytm porządkowania narzędzia i używają go specjalnie jako inteligentnego konkatenatora. Możesz sprawdzić ich repozytoria, aby zobaczyć, co robią.
Augusto Altman Quaranta,
Używając concat lub uglify grunta, plik wynikowy jest tworzony przy użyciu kolejności z określonych skonfigurowanych plików źródłowych. Podczas gdy RequireJS jest oparta na zależności. Inne podejście może jednak przynieść ten sam rezultat.
priyabagus
10

Zgadzam się z powyższą odpowiedzią. Ale oto inny sposób kompresji CSS.

Możesz połączyć swoje CSS za pomocą kompresora 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
źródło
W przypadku, gdy używasz 'grunt-css', musisz mieć moduł Locale Npm, więc upewnij się, że podczas instalacji 'grunt-css' musi znajdować się w module Locale Npm.
Anshul
7
Dlaczego miałbyś chcieć robić całą tę złożoność i wywoływać jvm w procesie budowania? Po prostu spowalnia to wszystko bez powodu.
michael łosoś
3

Nie musisz dodawać pakietu concat, możesz to zrobić za pomocą cssmin w następujący sposób:

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

A dla js użyj uglify w ten sposób:

uglify: {
      my_target: {
        files: {
            '/library/js/app.combined.min.js' : ['/app.js', '/controllers/*.js']
        }
      }
    }
Inc33
źródło