Cách nối và rút gọn nhiều tệp CSS và JavaScript với Grunt.js (0.3.x)


99

Lưu ý: Câu hỏi này chỉ liên quan đến Grunt 0.3.x và đã được để lại để tham khảo. Để được trợ giúp với bản phát hành Grunt 1.x mới nhất, vui lòng xem bình luận của tôi bên dưới câu hỏi này.

Tôi hiện đang cố gắng sử dụng Grunt.js để thiết lập quy trình xây dựng tự động để nối đầu tiên và sau đó rút gọn các tệp CSS và JavaScript.

Tôi đã có thể nối và rút gọn các tệp JavaScript của mình thành công, mặc dù mỗi lần tôi chạy, nó dường như chỉ thêm vào tệp thay vì ghi đè chúng.

Đối với CSS thu nhỏ hoặc thậm chí nối, tôi vẫn chưa thể làm điều này!

Trong điều kiện của module CSS grunt Tôi đã cố gắng sử dụng consolidate-css, grunt-csscssminnhưng vô ích. Tôi không thể hiểu được cách sử dụng chúng!

Cấu trúc thư mục của tôi như sau (là một ứng dụng node.js điển hình):

  • app.js
  • grunt.js
  • /public/index.html
  • / public / css / [các tệp css khác nhau]
  • / public / js / [các tệp javascript khác nhau]

Đây là tệp grunt.js của tôi hiện trông như thế nào trong thư mục gốc của ứng dụng của tôi:

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

};

Vì vậy, chỉ để tóm tắt, tôi cần trợ giúp với hai câu hỏi:

  1. Cách nối và rút gọn tất cả các tệp css của tôi trong thư mục /public/css/thành một tệp, giả sửmain.min.css
  2. Tại sao grunt.js tiếp tục thêm vào các tệp javascript được nối và rút gọn concat.jsconcat.min.jsbên dưới /public/js/thay vì ghi đè chúng mỗi khi gruntchạy lệnh ?

Cập nhật ngày 5 tháng 7 năm 2016 - Nâng cấp từ Grunt 0.3.x lên Grunt 0.4.x hoặc 1.x

Grunt.jsđã chuyển sang cấu trúc mới trong Grunt 0.4.x(tệp hiện được gọi Gruntfile.js). Vui lòng xem dự án mã nguồn mở Grunt.js Skeleton của tôi để được trợ giúp thiết lập quy trình xây dựng Grunt 1.x.

Chuyển từ Grunt 0.4.xsang Grunt 1.x không nên đưa ra nhiều thay đổi lớn .

Câu trả lời:


107

concat.js đang được bao gồm trong các concattệp nguồn của tác vụ public/js/*.js. Bạn có thể có một tác vụ xóa concat.js(nếu tệp tồn tại) trước khi nối lại, chuyển một mảng để xác định rõ ràng tệp nào bạn muốn nối và thứ tự của chúng hoặc thay đổi cấu trúc dự án của bạn.

Nếu làm theo cách sau, bạn có thể đặt tất cả các nguồn ./srccủa mình và các tệp đã tạo của bạn dưới./dest

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

Sau đó, thiết lập của bạn concat nhiệm vụ

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

Nhiệm vụ tối thiểu của bạn

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

Tác vụ min tích hợp sử dụng UglifyJS, vì vậy bạn cần thay thế. Tôi thấy grunt-css là khá tốt. Sau khi cài đặt nó, hãy tải nó vào tệp tin grunt của bạn

grunt.loadNpmTasks('grunt-css');

Và sau đó thiết lập nó

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

Lưu ý rằng cách sử dụng tương tự như min tích hợp sẵn.

Thay đổi defaultnhiệm vụ của bạn thành

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

Bây giờ, chạy gruntsẽ cho kết quả như bạn mong muốn.

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

1
Bạn là một thiên tài! Tất nhiên tôi chưa bao giờ nghĩ rằng nếu tôi đưa concatvào cùng một jsthư mục thì nó sẽ lấy nó ra và thêm nó vào! Tôi đã bắt đầu sử dụng cssmin và nó hoạt động rất tốt! Cảm ơn một lần nữa.
Jasdeep Khalsa

1
Tuyệt vời, thực sự tuyệt vời! Nhưng tên tệp luôn luôn là concat.min.cssconcat.min.js. Nếu tôi sửa đổi thứ gì đó, chạy lại và triển khai, mọi người sẽ không nhận được phiên bản mới nhất vì trình duyệt đã lưu vào bộ nhớ cache. Có một số cách để đặt tên tệp một cách ngẫu nhiên và liên kết chúng theo các thẻ <link><script>thẻ thích hợp ?
Tárcio Zemel

3
@ TárcioZemel Bạn có thể bao gồm phiên bản của package.json vào tên tệp:concat.min-<%= pkg.version %>.js
Rui Nunes

1
Bạn có thể sử dụng .destnhư thế này cssmin: { css:{ src: '<%= concat.css.dest %>', dest: './css/all.min.css'}} `` Đó là kết quả của hoạt độngconcat -> css
Ivan Black

12

Tôi muốn đề cập ở đây một kỹ thuật rất, RẤT, rất thú vị đang được sử dụng trong các dự án lớn như jQuery và Modernizr để nối những thứ.

Cả hai dự án này đều được phát triển hoàn toàn bằng các mô-đun requestjs (bạn có thể thấy điều đó trong github repos của họ) và sau đó họ sử dụng trình tối ưu hóa requestjs như một trình ghép nối rất thông minh. Điều thú vị là, như bạn có thể thấy, cả Modernizr và jQuery cũng không cần tới requestjs để hoạt động, và điều này xảy ra bởi vì họ xóa nghi thức cú pháp requestjs để loại bỏ requestjs trong mã của họ. Vì vậy, họ kết thúc với một thư viện độc lập được phát triển với các mô-đun requestjs! Nhờ đó, họ có thể thực hiện các bản dựng cắt ghép thư viện của họ, trong số các lợi thế khác.

Đối với tất cả những người quan tâm đến việc ghép nối với trình tối ưu hóa requestjs, hãy xem bài đăng này

Ngoài ra, có một công cụ nhỏ tóm tắt tất cả các bản soạn sẵn của quy trình: AlbanilJS


Điều này rất thú vị nhưng không liên quan đến câu hỏi từ RequireJS là một bộ nạp mô-đun, nó không concatenate hoặc giảm bớt AFAIK
Jasdeep Khalsa

Cảm ơn! Bạn nói đúng, RequiJS là một trình tải mô-đun và nó không nối cũng như rút gọn. Nhưng r.js (trình tối ưu hóa RequestJS -> requestjs.org/docs/optimization.html ) làm được điều đó. Cụ thể hơn, nó nối các mô-đun của bạn sắp xếp chúng theo các phụ thuộc. Những người từ Modernizr và jQuery đã tận dụng thuật toán sắp xếp của công cụ và sử dụng nó đặc biệt như một trình ghép nối thông minh. Bạn có thể kiểm tra các repo của họ để xem họ đang làm gì.
Augusto Altman Quaranta

Sử dụng concat hoặc uglify của grunt, tệp kết quả được tạo theo thứ tự từ các tệp nguồn được chỉ định được định cấu hình. Trong khi RequestJS dựa trên sự phụ thuộc. Cách tiếp cận khác nhau có thể đạt được cùng một kết quả.
priyabagus

10

Tôi đồng ý với câu trả lời trên. Nhưng đây là một cách nén CSS khác.

Bạn có thể nối CSS của mình bằng cách sử dụng trình nén 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;
    });
  });
}; 

Trong trường hợp nếu bạn đang sử dụng 'grunt-css', bạn phải cần mô-đun Locale Npm, vì vậy hãy đảm bảo rằng khi bạn cài đặt 'grunt-css' vào phải ở trong mô-đun Locale Npm.
Anshul 12/12/12

7
Tại sao bạn muốn thực hiện tất cả sự phức tạp này và gọi jvm trong quá trình xây dựng của mình? Chỉ làm chậm tất cả mà không có lý do.
cá hồi michael

3

Bạn không cần thêm gói concat, bạn có thể thực hiện việc này thông qua cssmin như sau:

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

Và đối với js, hãy sử dụng uglify như thế này:

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.