Cara menggabungkan dan mengecilkan beberapa file CSS dan JavaScript dengan Grunt.js (0.3.x)

99

Catatan: Pertanyaan ini hanya relevan untuk Grunt 0.3.x dan telah ditinggalkan untuk referensi. Untuk bantuan dengan rilis Grunt 1.x terbaru, silakan lihat komentar saya di bawah pertanyaan ini.

Saat ini saya mencoba menggunakan Grunt.js untuk menyiapkan proses pembuatan otomatis untuk penggabungan pertama dan kemudian mengecilkan file CSS dan JavaScript.

Saya berhasil menggabungkan dan mengecilkan file JavaScript saya, meskipun setiap kali saya menjalankan grunt sepertinya hanya menambahkan ke file daripada menimpanya.

Adapun untuk mengecilkan atau bahkan menggabungkan CSS, saya belum dapat melakukan ini!

Dalam hal modul CSS grunt saya telah mencoba menggunakan consolidate-css, grunt-css& cssmintetapi tidak berhasil. Tidak bisa memikirkan cara menggunakannya!

Struktur direktori saya adalah sebagai berikut (menjadi aplikasi node.js yang khas):

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

Inilah file grunt.js saya saat ini di folder root aplikasi saya:

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

};

Jadi untuk meringkas, saya butuh bantuan dengan dua pertanyaan:

  1. Misalnya, bagaimana menggabungkan dan mengecilkan semua file css saya di bawah folder /public/css/menjadi satu filemain.min.css
  2. Mengapa grunt.js terus menambahkan ke file javascript yang digabungkan dan dikecilkan concat.jsdan di concat.min.jsbawah /public/js/alih-alih menimpanya setiap kali perintah gruntdijalankan?

Diperbarui 5 Juli 2016 - Mengupgrade dari Grunt 0.3.x ke Grunt 0.4.x atau 1.x

Grunt.jstelah pindah ke struktur baru di Grunt 0.4.x(file sekarang disebut Gruntfile.js). Silakan lihat proyek open source saya Grunt.js Skeleton untuk bantuan dalam menyiapkan proses pembuatan untuk Grunt 1.x.

Pindah dari Grunt 0.4.xke Grunt 1.x seharusnya tidak menimbulkan banyak perubahan besar .

Jasdeep Khalsa
sumber

Jawaban:

107

concat.js disertakan dalam concatfile sumber tugas public/js/*.js. Anda dapat memiliki tugas yang menghapus concat.js(jika file ada) sebelum menggabungkan lagi, meneruskan array untuk secara eksplisit menentukan file mana yang ingin Anda gabungkan dan urutannya, atau mengubah struktur proyek Anda.

Jika melakukan yang terakhir, Anda dapat meletakkan semua sumber Anda di bawah ./srcdan file yang Anda bangun di bawah./dest

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

Kemudian atur tugas concat Anda

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

Tugas min Anda

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

Tugas min build-in menggunakan UglifyJS, jadi Anda perlu penggantinya. Saya menemukan grunt-css cukup bagus. Setelah menginstalnya, muat ke file grunt Anda

grunt.loadNpmTasks('grunt-css');

Dan kemudian atur

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

Perhatikan bahwa penggunaannya mirip dengan min built-in.

Ubah defaulttugas Anda menjadi

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

Sekarang, berlari gruntakan menghasilkan hasil yang Anda inginkan.

dest
├── css
   ├── concat.css
   └── concat.min.css
└── js
    ├── concat.js
    └── concat.min.js
jaime
sumber
1
Anda jenius! Tidak pernah terpikir oleh saya bahwa tentu saja jika saya memasukkannya ke concatdalam jsfolder yang sama , ia akan mengambilnya dan menambahkannya! Saya sudah mulai menggunakan cssmin dan itu berfungsi dengan baik! Terima kasih lagi.
Jasdeep Khalsa
1
Hebat, sangat bagus! Tetapi nama file selalu concat.min.cssdan concat.min.js. Jika saya memodifikasi sesuatu, menjalankan ulang & menerapkan, orang tidak akan mendapatkan versi terbaru karena browser sudah menyimpannya dalam cache. Ada cara untuk menamai file secara acak dan menautkannya sesuai dengan tag <link>dan yang benar <script>?
Tárcio Zemel
3
@ TárcioZemel Anda dapat menyertakan versi package.json pada nama file:concat.min-<%= pkg.version %>.js
Rui Nunes
1
Anda bisa menggunakan .destseperti ini cssmin: { css:{ src: '<%= concat.css.dest %>', dest: './css/all.min.css'}} `Ini adalah hasil dari operasiconcat -> css
Ivan Black
12

Saya ingin menyebutkan di sini teknik yang sangat, SANGAT menarik yang digunakan dalam proyek besar seperti jQuery dan Modernizr untuk hal-hal yang digabungkan.

Kedua proyek ini sepenuhnya dikembangkan dengan modul requirejs (Anda dapat melihatnya di repo github mereka) dan kemudian mereka menggunakan pengoptimal requirejs sebagai penggabung yang sangat cerdas. Hal yang menarik adalah bahwa, seperti yang Anda lihat, atau jQuery baik Modernizr tidak membutuhkan requirejs untuk bekerja, dan ini terjadi karena mereka menghapus ritual syntatic requirejs untuk menghilangkan requirejs dalam kode mereka. Jadi mereka berakhir dengan pustaka mandiri yang dikembangkan dengan modul requirejs! Berkat ini, mereka dapat melakukan pengembangan cutom pustaka mereka, di antara keuntungan lainnya.

Untuk semua yang tertarik dengan penggabungan dengan pengoptimal requirejs, lihat posting ini

Juga ada alat kecil yang mengabstraksi semua boilerplate proses: AlbanilJS

Augusto Altman Quaranta
sumber
Ini sangat menarik tetapi tidak relevan dengan pertanyaan karena RequireJS adalah pemuat modul, tidak menggabungkan atau mengecilkan AFAIK
Jasdeep Khalsa
Terima kasih! Anda benar, RequireJS adalah pemuat modul dan tidak menggabungkan atau mengecilkan. Tetapi r.js (pengoptimal RequireJS -> requirejs.org/docs/optimization.html ) melakukannya. Lebih khusus lagi, ini menggabungkan modul Anda yang mengurutkannya berdasarkan dependensi. Orang-orang dari Modernizr dan jQuery memanfaatkan algoritme pengurutan alat dan menggunakannya secara khusus sebagai penggabung cerdas. Anda dapat memeriksa repos mereka untuk melihat apa yang mereka lakukan.
Augusto Altman Quaranta
Menggunakan grunt's concat atau uglify, file yang dihasilkan dibuat menggunakan urutan dari file sumber yang dikonfigurasi. Sedangkan RequireJS didasarkan pada ketergantungan. Pendekatan yang berbeda dapat mencapai hasil yang sama.
priyabagus
10

Saya setuju dengan jawaban di atas. Tapi di sini ada cara lain untuk kompresi CSS.

Anda dapat menggabungkan CSS Anda dengan menggunakan kompresor 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
sumber
Jika Anda menggunakan 'grunt-css' Anda harus membutuhkan modul Npm Lokal, jadi pastikan saat Anda menginstal 'grunt-css' harus dalam modul Npm Lokal.
Anshul
7
Mengapa Anda ingin melakukan semua kerumitan ini dan memanggil jvm dalam proses pembuatan Anda? Hanya memperlambat semuanya tanpa alasan.
michael salmon
3

Anda tidak perlu menambahkan paket concat, Anda dapat melakukannya melalui cssmin seperti ini:

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

Dan untuk js, gunakan uglify seperti ini:

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